• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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