1*042d53a7SEvalZero /* 2*042d53a7SEvalZero * Licensed to the Apache Software Foundation (ASF) under one 3*042d53a7SEvalZero * or more contributor license agreements. See the NOTICE file 4*042d53a7SEvalZero * distributed with this work for additional information 5*042d53a7SEvalZero * regarding copyright ownership. The ASF licenses this file 6*042d53a7SEvalZero * to you under the Apache License, Version 2.0 (the 7*042d53a7SEvalZero * "License"); you may not use this file except in compliance 8*042d53a7SEvalZero * with the License. You may obtain a copy of the License at 9*042d53a7SEvalZero * 10*042d53a7SEvalZero * http://www.apache.org/licenses/LICENSE-2.0 11*042d53a7SEvalZero * 12*042d53a7SEvalZero * Unless required by applicable law or agreed to in writing, 13*042d53a7SEvalZero * software distributed under the License is distributed on an 14*042d53a7SEvalZero * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15*042d53a7SEvalZero * KIND, either express or implied. See the License for the 16*042d53a7SEvalZero * specific language governing permissions and limitations 17*042d53a7SEvalZero * under the License. 18*042d53a7SEvalZero */ 19*042d53a7SEvalZero 20*042d53a7SEvalZero /** 21*042d53a7SEvalZero * @addtogroup OSKernel 22*042d53a7SEvalZero * @{ 23*042d53a7SEvalZero * @defgroup OSMempool Memory Pools 24*042d53a7SEvalZero * @{ 25*042d53a7SEvalZero */ 26*042d53a7SEvalZero 27*042d53a7SEvalZero 28*042d53a7SEvalZero #ifndef _OS_MEMPOOL_H_ 29*042d53a7SEvalZero #define _OS_MEMPOOL_H_ 30*042d53a7SEvalZero 31*042d53a7SEvalZero #include <stdbool.h> 32*042d53a7SEvalZero #include "os/os.h" 33*042d53a7SEvalZero #include "os/queue.h" 34*042d53a7SEvalZero 35*042d53a7SEvalZero #ifdef __cplusplus 36*042d53a7SEvalZero extern "C" { 37*042d53a7SEvalZero #endif 38*042d53a7SEvalZero 39*042d53a7SEvalZero /** 40*042d53a7SEvalZero * A memory block structure. This simply contains a pointer to the free list 41*042d53a7SEvalZero * chain and is only used when the block is on the free list. When the block 42*042d53a7SEvalZero * has been removed from the free list the entire memory block is usable by the 43*042d53a7SEvalZero * caller. 44*042d53a7SEvalZero */ 45*042d53a7SEvalZero struct os_memblock { 46*042d53a7SEvalZero SLIST_ENTRY(os_memblock) mb_next; 47*042d53a7SEvalZero }; 48*042d53a7SEvalZero 49*042d53a7SEvalZero /* XXX: Change this structure so that we keep the first address in the pool? */ 50*042d53a7SEvalZero /* XXX: add memory debug structure and associated code */ 51*042d53a7SEvalZero /* XXX: Change how I coded the SLIST_HEAD here. It should be named: 52*042d53a7SEvalZero SLIST_HEAD(,os_memblock) mp_head; */ 53*042d53a7SEvalZero 54*042d53a7SEvalZero /** 55*042d53a7SEvalZero * Memory pool 56*042d53a7SEvalZero */ 57*042d53a7SEvalZero struct os_mempool { 58*042d53a7SEvalZero /** Size of the memory blocks, in bytes. */ 59*042d53a7SEvalZero uint32_t mp_block_size; 60*042d53a7SEvalZero /** The number of memory blocks. */ 61*042d53a7SEvalZero uint16_t mp_num_blocks; 62*042d53a7SEvalZero /** The number of free blocks left */ 63*042d53a7SEvalZero uint16_t mp_num_free; 64*042d53a7SEvalZero /** The lowest number of free blocks seen */ 65*042d53a7SEvalZero uint16_t mp_min_free; 66*042d53a7SEvalZero /** Bitmap of OS_MEMPOOL_F_[...] values. */ 67*042d53a7SEvalZero uint8_t mp_flags; 68*042d53a7SEvalZero /** Address of memory buffer used by pool */ 69*042d53a7SEvalZero uintptr_t mp_membuf_addr; 70*042d53a7SEvalZero STAILQ_ENTRY(os_mempool) mp_list; 71*042d53a7SEvalZero SLIST_HEAD(,os_memblock); 72*042d53a7SEvalZero /** Name for memory block */ 73*042d53a7SEvalZero char *name; 74*042d53a7SEvalZero }; 75*042d53a7SEvalZero 76*042d53a7SEvalZero /** 77*042d53a7SEvalZero * Indicates an extended mempool. Address can be safely cast to 78*042d53a7SEvalZero * (struct os_mempool_ext *). 79*042d53a7SEvalZero */ 80*042d53a7SEvalZero #define OS_MEMPOOL_F_EXT 0x01 81*042d53a7SEvalZero 82*042d53a7SEvalZero struct os_mempool_ext; 83*042d53a7SEvalZero 84*042d53a7SEvalZero /** 85*042d53a7SEvalZero * Block put callback function. If configured, this callback gets executed 86*042d53a7SEvalZero * whenever a block is freed to the corresponding extended mempool. Note: The 87*042d53a7SEvalZero * os_memblock_put() function calls this callback instead of freeing the block 88*042d53a7SEvalZero * itself. Therefore, it is the callback's responsibility to free the block 89*042d53a7SEvalZero * via a call to os_memblock_put_from_cb(). 90*042d53a7SEvalZero * 91*042d53a7SEvalZero * @param ome The extended mempool that a block is being 92*042d53a7SEvalZero * freed back to. 93*042d53a7SEvalZero * @param data The block being freed. 94*042d53a7SEvalZero * @param arg Optional argument configured along with the 95*042d53a7SEvalZero * callback. 96*042d53a7SEvalZero * 97*042d53a7SEvalZero * @return Indicates whether the block was successfully 98*042d53a7SEvalZero * freed. A non-zero value should only be 99*042d53a7SEvalZero * returned if the block was not successfully 100*042d53a7SEvalZero * released back to its pool. 101*042d53a7SEvalZero */ 102*042d53a7SEvalZero typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data, 103*042d53a7SEvalZero void *arg); 104*042d53a7SEvalZero 105*042d53a7SEvalZero struct os_mempool_ext { 106*042d53a7SEvalZero struct os_mempool mpe_mp; 107*042d53a7SEvalZero 108*042d53a7SEvalZero /* Callback that is executed immediately when a block is freed. */ 109*042d53a7SEvalZero os_mempool_put_fn *mpe_put_cb; 110*042d53a7SEvalZero void *mpe_put_arg; 111*042d53a7SEvalZero }; 112*042d53a7SEvalZero 113*042d53a7SEvalZero #define OS_MEMPOOL_INFO_NAME_LEN (32) 114*042d53a7SEvalZero 115*042d53a7SEvalZero /** 116*042d53a7SEvalZero * Information describing a memory pool, used to return OS information 117*042d53a7SEvalZero * to the management layer. 118*042d53a7SEvalZero */ 119*042d53a7SEvalZero struct os_mempool_info { 120*042d53a7SEvalZero /** Size of the memory blocks in the pool */ 121*042d53a7SEvalZero int omi_block_size; 122*042d53a7SEvalZero /** Number of memory blocks in the pool */ 123*042d53a7SEvalZero int omi_num_blocks; 124*042d53a7SEvalZero /** Number of free memory blocks */ 125*042d53a7SEvalZero int omi_num_free; 126*042d53a7SEvalZero /** Minimum number of free memory blocks ever */ 127*042d53a7SEvalZero int omi_min_free; 128*042d53a7SEvalZero /** Name of the memory pool */ 129*042d53a7SEvalZero char omi_name[OS_MEMPOOL_INFO_NAME_LEN]; 130*042d53a7SEvalZero }; 131*042d53a7SEvalZero 132*042d53a7SEvalZero /** 133*042d53a7SEvalZero * Get information about the next system memory pool. 134*042d53a7SEvalZero * 135*042d53a7SEvalZero * @param mempool The current memory pool, or NULL if starting iteration. 136*042d53a7SEvalZero * @param info A pointer to the structure to return memory pool information 137*042d53a7SEvalZero * into. 138*042d53a7SEvalZero * 139*042d53a7SEvalZero * @return The next memory pool in the list to get information about, or NULL 140*042d53a7SEvalZero * when at the last memory pool. 141*042d53a7SEvalZero */ 142*042d53a7SEvalZero struct os_mempool *os_mempool_info_get_next(struct os_mempool *, 143*042d53a7SEvalZero struct os_mempool_info *); 144*042d53a7SEvalZero 145*042d53a7SEvalZero /* 146*042d53a7SEvalZero * To calculate size of the memory buffer needed for the pool. NOTE: This size 147*042d53a7SEvalZero * is NOT in bytes! The size is the number of os_membuf_t elements required for 148*042d53a7SEvalZero * the memory pool. 149*042d53a7SEvalZero */ 150*042d53a7SEvalZero #if (OS_CFG_ALIGNMENT == OS_CFG_ALIGN_4) 151*042d53a7SEvalZero #define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 3) / 4) * (n)) 152*042d53a7SEvalZero typedef uint32_t os_membuf_t; 153*042d53a7SEvalZero #else 154*042d53a7SEvalZero #define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 7) / 8) * (n)) 155*042d53a7SEvalZero typedef uint64_t os_membuf_t; 156*042d53a7SEvalZero #endif 157*042d53a7SEvalZero 158*042d53a7SEvalZero /** Calculates the number of bytes required to initialize a memory pool. */ 159*042d53a7SEvalZero #define OS_MEMPOOL_BYTES(n,blksize) \ 160*042d53a7SEvalZero (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize))) 161*042d53a7SEvalZero 162*042d53a7SEvalZero /** 163*042d53a7SEvalZero * Initialize a memory pool. 164*042d53a7SEvalZero * 165*042d53a7SEvalZero * @param mp Pointer to a pointer to a mempool 166*042d53a7SEvalZero * @param blocks The number of blocks in the pool 167*042d53a7SEvalZero * @param blocks_size The size of the block, in bytes. 168*042d53a7SEvalZero * @param membuf Pointer to memory to contain blocks. 169*042d53a7SEvalZero * @param name Name of the pool. 170*042d53a7SEvalZero * 171*042d53a7SEvalZero * @return os_error_t 172*042d53a7SEvalZero */ 173*042d53a7SEvalZero os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks, 174*042d53a7SEvalZero uint32_t block_size, void *membuf, char *name); 175*042d53a7SEvalZero 176*042d53a7SEvalZero /** 177*042d53a7SEvalZero * Initializes an extended memory pool. Extended attributes (e.g., callbacks) 178*042d53a7SEvalZero * are not specified when this function is called; they are assigned manually 179*042d53a7SEvalZero * after initialization. 180*042d53a7SEvalZero * 181*042d53a7SEvalZero * @param mpe The extended memory pool to initialize. 182*042d53a7SEvalZero * @param blocks The number of blocks in the pool. 183*042d53a7SEvalZero * @param block_size The size of each block, in bytes. 184*042d53a7SEvalZero * @param membuf Pointer to memory to contain blocks. 185*042d53a7SEvalZero * @param name Name of the pool. 186*042d53a7SEvalZero * 187*042d53a7SEvalZero * @return os_error_t 188*042d53a7SEvalZero */ 189*042d53a7SEvalZero os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, 190*042d53a7SEvalZero uint32_t block_size, void *membuf, char *name); 191*042d53a7SEvalZero 192*042d53a7SEvalZero /** 193*042d53a7SEvalZero * Clears a memory pool. 194*042d53a7SEvalZero * 195*042d53a7SEvalZero * @param mp The mempool to clear. 196*042d53a7SEvalZero * 197*042d53a7SEvalZero * @return os_error_t 198*042d53a7SEvalZero */ 199*042d53a7SEvalZero os_error_t os_mempool_clear(struct os_mempool *mp); 200*042d53a7SEvalZero 201*042d53a7SEvalZero /** 202*042d53a7SEvalZero * Performs an integrity check of the specified mempool. This function 203*042d53a7SEvalZero * attempts to detect memory corruption in the specified memory pool. 204*042d53a7SEvalZero * 205*042d53a7SEvalZero * @param mp The mempool to check. 206*042d53a7SEvalZero * 207*042d53a7SEvalZero * @return true if the memory pool passes the integrity 208*042d53a7SEvalZero * check; 209*042d53a7SEvalZero * false if the memory pool is corrupt. 210*042d53a7SEvalZero */ 211*042d53a7SEvalZero bool os_mempool_is_sane(const struct os_mempool *mp); 212*042d53a7SEvalZero 213*042d53a7SEvalZero /** 214*042d53a7SEvalZero * Checks if a memory block was allocated from the specified mempool. 215*042d53a7SEvalZero * 216*042d53a7SEvalZero * @param mp The mempool to check as parent. 217*042d53a7SEvalZero * @param block_addr The memory block to check as child. 218*042d53a7SEvalZero * 219*042d53a7SEvalZero * @return 0 if the block does not belong to the mempool; 220*042d53a7SEvalZero * 1 if the block does belong to the mempool. 221*042d53a7SEvalZero */ 222*042d53a7SEvalZero int os_memblock_from(const struct os_mempool *mp, const void *block_addr); 223*042d53a7SEvalZero 224*042d53a7SEvalZero /** 225*042d53a7SEvalZero * Get a memory block from a memory pool 226*042d53a7SEvalZero * 227*042d53a7SEvalZero * @param mp Pointer to the memory pool 228*042d53a7SEvalZero * 229*042d53a7SEvalZero * @return void* Pointer to block if available; NULL otherwise 230*042d53a7SEvalZero */ 231*042d53a7SEvalZero void *os_memblock_get(struct os_mempool *mp); 232*042d53a7SEvalZero 233*042d53a7SEvalZero /** 234*042d53a7SEvalZero * Puts the memory block back into the pool, ignoring the put callback, if any. 235*042d53a7SEvalZero * This function should only be called from a put callback to free a block 236*042d53a7SEvalZero * without causing infinite recursion. 237*042d53a7SEvalZero * 238*042d53a7SEvalZero * @param mp Pointer to memory pool 239*042d53a7SEvalZero * @param block_addr Pointer to memory block 240*042d53a7SEvalZero * 241*042d53a7SEvalZero * @return os_error_t 242*042d53a7SEvalZero */ 243*042d53a7SEvalZero os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); 244*042d53a7SEvalZero 245*042d53a7SEvalZero /** 246*042d53a7SEvalZero * Puts the memory block back into the pool 247*042d53a7SEvalZero * 248*042d53a7SEvalZero * @param mp Pointer to memory pool 249*042d53a7SEvalZero * @param block_addr Pointer to memory block 250*042d53a7SEvalZero * 251*042d53a7SEvalZero * @return os_error_t 252*042d53a7SEvalZero */ 253*042d53a7SEvalZero os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr); 254*042d53a7SEvalZero 255*042d53a7SEvalZero #ifdef __cplusplus 256*042d53a7SEvalZero } 257*042d53a7SEvalZero #endif 258*042d53a7SEvalZero 259*042d53a7SEvalZero #endif /* _OS_MEMPOOL_H_ */ 260*042d53a7SEvalZero 261*042d53a7SEvalZero 262*042d53a7SEvalZero /** 263*042d53a7SEvalZero * @} OSMempool 264*042d53a7SEvalZero * @} OSKernel 265*042d53a7SEvalZero */ 266