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