ChibiOS/RT  5.1.0
chmempools.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
3 
4  This file is part of ChibiOS.
5 
6  ChibiOS is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 3 of the License, or
9  (at your option) any later version.
10 
11  ChibiOS is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /**
21  * @file chmempools.c
22  * @brief Memory Pools code.
23  *
24  * @addtogroup pools
25  * @details Memory Pools related APIs and services.
26  * <h2>Operation mode</h2>
27  * The Memory Pools APIs allow to allocate/free fixed size objects in
28  * <b>constant time</b> and reliably without memory fragmentation
29  * problems.<br>
30  * Memory Pools do not enforce any alignment constraint on the
31  * contained object however the objects must be properly aligned
32  * to contain a pointer to void.
33  * @pre In order to use the memory pools APIs the @p CH_CFG_USE_MEMPOOLS option
34  * must be enabled in @p chconf.h.
35  * @note Compatible with RT and NIL.
36  * @{
37  */
38 
39 #include "ch.h"
40 
41 #if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__)
42 
43 /*===========================================================================*/
44 /* Module exported variables. */
45 /*===========================================================================*/
46 
47 /*===========================================================================*/
48 /* Module local types. */
49 /*===========================================================================*/
50 
51 /*===========================================================================*/
52 /* Module local variables. */
53 /*===========================================================================*/
54 
55 /*===========================================================================*/
56 /* Module local functions. */
57 /*===========================================================================*/
58 
59 /*===========================================================================*/
60 /* Module exported functions. */
61 /*===========================================================================*/
62 
63 /**
64  * @brief Initializes an empty memory pool.
65  *
66  * @param[out] mp pointer to a @p memory_pool_t structure
67  * @param[in] size the size of the objects contained in this memory pool,
68  * the minimum accepted size is the size of a pointer to
69  * void.
70  * @param[in] align required memory alignment
71  * @param[in] provider memory provider function for the memory pool or
72  * @p NULL if the pool is not allowed to grow
73  * automatically
74  *
75  * @init
76  */
77 void chPoolObjectInitAligned(memory_pool_t *mp, size_t size,
78  unsigned align, memgetfunc_t provider) {
79 
80  chDbgCheck((mp != NULL) && (size >= sizeof(void *)));
81 
82  mp->next = NULL;
83  mp->object_size = size;
84  mp->align = align;
85  mp->provider = provider;
86 }
87 
88 /**
89  * @brief Loads a memory pool with an array of static objects.
90  * @pre The memory pool must already be initialized.
91  * @pre The array elements must be of the right size for the specified
92  * memory pool.
93  * @pre The array elements size must be a multiple of the alignment
94  * requirement for the pool.
95  * @post The memory pool contains the elements of the input array.
96  *
97  * @param[in] mp pointer to a @p memory_pool_t structure
98  * @param[in] p pointer to the array first element
99  * @param[in] n number of elements in the array
100  *
101  * @api
102  */
103 void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) {
104 
105  chDbgCheck((mp != NULL) && (n != 0U));
106 
107  while (n != 0U) {
108  chPoolAdd(mp, p);
109  /*lint -save -e9087 [11.3] Safe cast.*/
110  p = (void *)(((uint8_t *)p) + mp->object_size);
111  /*lint -restore*/
112  n--;
113  }
114 }
115 
116 /**
117  * @brief Allocates an object from a memory pool.
118  * @pre The memory pool must already be initialized.
119  *
120  * @param[in] mp pointer to a @p memory_pool_t structure
121  * @return The pointer to the allocated object.
122  * @retval NULL if pool is empty.
123  *
124  * @iclass
125  */
127  void *objp;
128 
130  chDbgCheck(mp != NULL);
131 
132  objp = mp->next;
133  /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
134  if (objp != NULL) {
135  mp->next = mp->next->next;
136  }
137  else if (mp->provider != NULL) {
138  objp = mp->provider(mp->object_size, mp->align);
139  }
140  /*lint -restore*/
141 
142  return objp;
143 }
144 
145 /**
146  * @brief Allocates an object from a memory pool.
147  * @pre The memory pool must already be initialized.
148  *
149  * @param[in] mp pointer to a @p memory_pool_t structure
150  * @return The pointer to the allocated object.
151  * @retval NULL if pool is empty.
152  *
153  * @api
154  */
156  void *objp;
157 
158  chSysLock();
159  objp = chPoolAllocI(mp);
160  chSysUnlock();
161 
162  return objp;
163 }
164 
165 /**
166  * @brief Releases an object into a memory pool.
167  * @pre The memory pool must already be initialized.
168  * @pre The freed object must be of the right size for the specified
169  * memory pool.
170  * @pre The added object must be properly aligned.
171  *
172  * @param[in] mp pointer to a @p memory_pool_t structure
173  * @param[in] objp the pointer to the object to be released
174  *
175  * @iclass
176  */
177 void chPoolFreeI(memory_pool_t *mp, void *objp) {
178  struct pool_header *php = objp;
179 
181  chDbgCheck((mp != NULL) && (objp != NULL));
182 
183  chDbgAssert(((size_t)objp & MEM_ALIGN_MASK(mp->align)) == 0U,
184  "unaligned object");
185 
186  php->next = mp->next;
187  mp->next = php;
188 }
189 
190 /**
191  * @brief Releases an object into a memory pool.
192  * @pre The memory pool must already be initialized.
193  * @pre The freed object must be of the right size for the specified
194  * memory pool.
195  * @pre The added object must be properly aligned.
196  *
197  * @param[in] mp pointer to a @p memory_pool_t structure
198  * @param[in] objp the pointer to the object to be released
199  *
200  * @api
201  */
202 void chPoolFree(memory_pool_t *mp, void *objp) {
203 
204  chSysLock();
205  chPoolFreeI(mp, objp);
206  chSysUnlock();
207 }
208 
209 #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
210 /**
211  * @brief Initializes an empty guarded memory pool.
212  *
213  * @param[out] gmp pointer to a @p guarded_memory_pool_t structure
214  * @param[in] size the size of the objects contained in this guarded
215  * memory pool, the minimum accepted size is the size
216  * of a pointer to void.
217  * @param[in] align required memory alignment
218  *
219  * @init
220  */
222  size_t size,
223  unsigned align) {
224 
225  chPoolObjectInitAligned(&gmp->pool, size, align, NULL);
226  chSemObjectInit(&gmp->sem, (cnt_t)0);
227 }
228 
229 /**
230  * @brief Loads a guarded memory pool with an array of static objects.
231  * @pre The guarded memory pool must already be initialized.
232  * @pre The array elements must be of the right size for the specified
233  * guarded memory pool.
234  * @post The guarded memory pool contains the elements of the input array.
235  *
236  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
237  * @param[in] p pointer to the array first element
238  * @param[in] n number of elements in the array
239  *
240  * @api
241  */
242 void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n) {
243 
244  chDbgCheck((gmp != NULL) && (n != 0U));
245 
246  while (n != 0U) {
247  chGuardedPoolAdd(gmp, p);
248  /*lint -save -e9087 [11.3] Safe cast.*/
249  p = (void *)(((uint8_t *)p) + gmp->pool.object_size);
250  /*lint -restore*/
251  n--;
252  }
253 }
254 
255 /**
256  * @brief Allocates an object from a guarded memory pool.
257  * @pre The guarded memory pool must already be initialized.
258  *
259  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
260  * @param[in] timeout the number of ticks before the operation timeouts,
261  * the following special values are allowed:
262  * - @a TIME_IMMEDIATE immediate timeout.
263  * - @a TIME_INFINITE no timeout.
264  * .
265  * @return The pointer to the allocated object.
266  * @retval NULL if the operation timed out.
267  *
268  * @sclass
269  */
271  sysinterval_t timeout) {
272  msg_t msg;
273 
274  msg = chSemWaitTimeoutS(&gmp->sem, timeout);
275  if (msg != MSG_OK) {
276  return NULL;
277  }
278 
279  return chPoolAllocI(&gmp->pool);
280 }
281 
282 /**
283  * @brief Allocates an object from a guarded memory pool.
284  * @pre The guarded memory pool must already be initialized.
285  *
286  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
287  * @param[in] timeout the number of ticks before the operation timeouts,
288  * the following special values are allowed:
289  * - @a TIME_IMMEDIATE immediate timeout.
290  * - @a TIME_INFINITE no timeout.
291  * .
292  * @return The pointer to the allocated object.
293  * @retval NULL if the operation timed out.
294  *
295  * @api
296  */
298  sysinterval_t timeout) {
299  void *p;
300 
301  chSysLock();
302  p = chGuardedPoolAllocTimeoutS(gmp, timeout);
303  chSysUnlock();
304 
305  return p;
306 }
307 
308 /**
309  * @brief Releases an object into a guarded memory pool.
310  * @pre The guarded memory pool must already be initialized.
311  * @pre The freed object must be of the right size for the specified
312  * guarded memory pool.
313  * @pre The added object must be properly aligned.
314  *
315  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
316  * @param[in] objp the pointer to the object to be released
317  *
318  * @api
319  */
320 void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp) {
321 
322  chSysLock();
323  chGuardedPoolFreeI(gmp, objp);
325  chSysUnlock();
326 }
327 #endif
328 
329 #endif /* CH_CFG_USE_MEMPOOLS == TRUE */
330 
331 /** @} */
Memory pool descriptor.
Definition: chmempools.h:68
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:150
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:353
void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n)
Loads a memory pool with an array of static objects.
Definition: chmempools.c:103
void chPoolFree(memory_pool_t *mp, void *objp)
Releases an object into a memory pool.
Definition: chmempools.c:202
msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout)
Performs a wait operation on a semaphore with timeout specification.
Definition: chsem.c:264
void * chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp, sysinterval_t timeout)
Allocates an object from a guarded memory pool.
Definition: chmempools.c:297
memgetfunc_t provider
Memory blocks provider for this pool.
Definition: chmempools.h:73
unsigned align
Required alignment.
Definition: chmempools.h:72
Memory pool free object header.
Definition: chmempools.h:60
memory_pool_t pool
The memory pool itself.
Definition: chmempools.h:84
#define MEM_ALIGN_MASK(a)
Alignment mask constant.
Definition: chalign.h:59
static void chGuardedPoolAdd(guarded_memory_pool_t *gmp, void *objp)
Adds an object to a guarded memory pool.
Definition: chmempools.h:327
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:365
void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n)
Loads a guarded memory pool with an array of static objects.
Definition: chmempools.c:242
size_t object_size
Memory pool objects size.
Definition: chmempools.h:70
static void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp)
Releases an object into a guarded memory pool.
Definition: chmempools.h:289
void chDbgCheckClassI(void)
I-class functions context check.
Definition: chdebug.c:235
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition: chschd.c:456
void * chPoolAlloc(memory_pool_t *mp)
Allocates an object from a memory pool.
Definition: chmempools.c:155
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
struct pool_header * next
Pointer to the header.
Definition: chmempools.h:69
struct pool_header * next
Pointer to the next pool header in the list.
Definition: chmempools.h:61
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
void * chPoolAllocI(memory_pool_t *mp)
Allocates an object from a memory pool.
Definition: chmempools.c:126
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
void chSemObjectInit(semaphore_t *sp, cnt_t n)
Initializes a semaphore with the specified counter value.
Definition: chsem.c:97
void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, size_t size, unsigned align)
Initializes an empty guarded memory pool.
Definition: chmempools.c:221
void * chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, sysinterval_t timeout)
Allocates an object from a guarded memory pool.
Definition: chmempools.c:270
void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp)
Releases an object into a guarded memory pool.
Definition: chmempools.c:320
semaphore_t sem
Counter semaphore guarding the memory pool.
Definition: chmempools.h:82
void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, unsigned align, memgetfunc_t provider)
Initializes an empty memory pool.
Definition: chmempools.c:77
void *(* memgetfunc_t)(size_t size, unsigned align)
Memory get function.
Definition: chmemcore.h:75
Guarded memory pool descriptor.
Definition: chmempools.h:81
static void chPoolAdd(memory_pool_t *mp, void *objp)
Adds an object to a memory pool.
Definition: chmempools.h:214
ChibiOS/RT main include file.
void chPoolFreeI(memory_pool_t *mp, void *objp)
Releases an object into a memory pool.
Definition: chmempools.c:177