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