ChibiOS/RT  6.0.3
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 oslib_mempools
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) &&
81  (size >= sizeof(void *)) &&
82  (align >= PORT_NATURAL_ALIGN) &&
83  MEM_IS_VALID_ALIGNMENT(align));
84 
85  mp->next = NULL;
86  mp->object_size = size;
87  mp->align = align;
88  mp->provider = provider;
89 }
90 
91 /**
92  * @brief Loads a memory pool with an array of static objects.
93  * @pre The memory pool must already be initialized.
94  * @pre The array elements must be of the right size for the specified
95  * memory pool.
96  * @pre The array elements size must be a multiple of the alignment
97  * requirement for the pool.
98  * @post The memory pool contains the elements of the input array.
99  *
100  * @param[in] mp pointer to a @p memory_pool_t structure
101  * @param[in] p pointer to the array first element
102  * @param[in] n number of elements in the array
103  *
104  * @api
105  */
106 void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) {
107 
108  chDbgCheck((mp != NULL) && (n != 0U));
109 
110  while (n != 0U) {
111  chPoolAdd(mp, p);
112  /*lint -save -e9087 [11.3] Safe cast.*/
113  p = (void *)(((uint8_t *)p) + mp->object_size);
114  /*lint -restore*/
115  n--;
116  }
117 }
118 
119 /**
120  * @brief Allocates an object from a memory pool.
121  * @pre The memory pool must already be initialized.
122  *
123  * @param[in] mp pointer to a @p memory_pool_t structure
124  * @return The pointer to the allocated object.
125  * @retval NULL if pool is empty.
126  *
127  * @iclass
128  */
130  void *objp;
131 
133  chDbgCheck(mp != NULL);
134 
135  objp = mp->next;
136  /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
137  if (objp != NULL) {
138  mp->next = mp->next->next;
139  }
140  else if (mp->provider != NULL) {
141  objp = mp->provider(mp->object_size, mp->align);
142 
143  chDbgAssert(MEM_IS_ALIGNED(objp, mp->align),
144  "returned object not aligned");
145  }
146  /*lint -restore*/
147 
148  return objp;
149 }
150 
151 /**
152  * @brief Allocates an object from a memory pool.
153  * @pre The memory pool must already be initialized.
154  *
155  * @param[in] mp pointer to a @p memory_pool_t structure
156  * @return The pointer to the allocated object.
157  * @retval NULL if pool is empty.
158  *
159  * @api
160  */
162  void *objp;
163 
164  chSysLock();
165  objp = chPoolAllocI(mp);
166  chSysUnlock();
167 
168  return objp;
169 }
170 
171 /**
172  * @brief Releases an object into a memory pool.
173  * @pre The memory pool must already be initialized.
174  * @pre The freed object must be of the right size for the specified
175  * memory pool.
176  * @pre The added object must be properly aligned.
177  *
178  * @param[in] mp pointer to a @p memory_pool_t structure
179  * @param[in] objp the pointer to the object to be released
180  *
181  * @iclass
182  */
183 void chPoolFreeI(memory_pool_t *mp, void *objp) {
184  struct pool_header *php = objp;
185 
187  chDbgCheck((mp != NULL) &&
188  (objp != NULL) &&
189  MEM_IS_ALIGNED(objp, mp->align));
190 
191  php->next = mp->next;
192  mp->next = php;
193 }
194 
195 /**
196  * @brief Releases an object into a memory pool.
197  * @pre The memory pool must already be initialized.
198  * @pre The freed object must be of the right size for the specified
199  * memory pool.
200  * @pre The added object must be properly aligned.
201  *
202  * @param[in] mp pointer to a @p memory_pool_t structure
203  * @param[in] objp the pointer to the object to be released
204  *
205  * @api
206  */
207 void chPoolFree(memory_pool_t *mp, void *objp) {
208 
209  chSysLock();
210  chPoolFreeI(mp, objp);
211  chSysUnlock();
212 }
213 
214 #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
215 /**
216  * @brief Initializes an empty guarded memory pool.
217  *
218  * @param[out] gmp pointer to a @p guarded_memory_pool_t structure
219  * @param[in] size the size of the objects contained in this guarded
220  * memory pool, the minimum accepted size is the size
221  * of a pointer to void.
222  * @param[in] align required memory alignment
223  *
224  * @init
225  */
227  size_t size,
228  unsigned align) {
229 
230  chPoolObjectInitAligned(&gmp->pool, size, align, NULL);
231  chSemObjectInit(&gmp->sem, (cnt_t)0);
232 }
233 
234 /**
235  * @brief Loads a guarded memory pool with an array of static objects.
236  * @pre The guarded memory pool must already be initialized.
237  * @pre The array elements must be of the right size for the specified
238  * guarded memory pool.
239  * @post The guarded memory pool contains the elements of the input array.
240  *
241  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
242  * @param[in] p pointer to the array first element
243  * @param[in] n number of elements in the array
244  *
245  * @api
246  */
247 void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n) {
248 
249  chDbgCheck((gmp != NULL) && (n != 0U));
250 
251  while (n != 0U) {
252  chGuardedPoolAdd(gmp, p);
253  /*lint -save -e9087 [11.3] Safe cast.*/
254  p = (void *)(((uint8_t *)p) + gmp->pool.object_size);
255  /*lint -restore*/
256  n--;
257  }
258 }
259 
260 /**
261  * @brief Allocates an object from a guarded memory pool.
262  * @pre The guarded memory pool must already be initialized.
263  *
264  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
265  * @param[in] timeout the number of ticks before the operation timeouts,
266  * the following special values are allowed:
267  * - @a TIME_IMMEDIATE immediate timeout.
268  * - @a TIME_INFINITE no timeout.
269  * .
270  * @return The pointer to the allocated object.
271  * @retval NULL if the operation timed out.
272  *
273  * @sclass
274  */
276  sysinterval_t timeout) {
277  msg_t msg;
278 
279  msg = chSemWaitTimeoutS(&gmp->sem, timeout);
280  if (msg != MSG_OK) {
281  return NULL;
282  }
283 
284  return chPoolAllocI(&gmp->pool);
285 }
286 
287 /**
288  * @brief Allocates an object from a guarded memory pool.
289  * @pre The guarded memory pool must already be initialized.
290  *
291  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
292  * @param[in] timeout the number of ticks before the operation timeouts,
293  * the following special values are allowed:
294  * - @a TIME_IMMEDIATE immediate timeout.
295  * - @a TIME_INFINITE no timeout.
296  * .
297  * @return The pointer to the allocated object.
298  * @retval NULL if the operation timed out.
299  *
300  * @api
301  */
303  sysinterval_t timeout) {
304  void *p;
305 
306  chSysLock();
307  p = chGuardedPoolAllocTimeoutS(gmp, timeout);
308  chSysUnlock();
309 
310  return p;
311 }
312 
313 /**
314  * @brief Releases an object into a guarded memory pool.
315  * @pre The guarded memory pool must already be initialized.
316  * @pre The freed object must be of the right size for the specified
317  * guarded memory pool.
318  * @pre The added object must be properly aligned.
319  *
320  * @param[in] gmp pointer to a @p guarded_memory_pool_t structure
321  * @param[in] objp the pointer to the object to be released
322  *
323  * @api
324  */
325 void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp) {
326 
327  chSysLock();
328  chGuardedPoolFreeI(gmp, objp);
330  chSysUnlock();
331 }
332 #endif
333 
334 #endif /* CH_CFG_USE_MEMPOOLS == TRUE */
335 
336 /** @} */
Memory pool descriptor.
Definition: chmempools.h:64
void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp)
Releases an object into a guarded memory pool.
Definition: chmempools.c:325
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
void chPoolFreeI(memory_pool_t *mp, void *objp)
Releases an object into a memory pool.
Definition: chmempools.c:183
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:353
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:302
memgetfunc_t provider
Memory blocks provider for this pool.
Definition: chmempools.h:69
void chPoolFree(memory_pool_t *mp, void *objp)
Releases an object into a memory pool.
Definition: chmempools.c:207
unsigned align
Required alignment.
Definition: chmempools.h:68
Memory pool free object header.
Definition: chmempools.h:56
memory_pool_t pool
The memory pool itself.
Definition: chmempools.h:80
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:365
#define MEM_IS_VALID_ALIGNMENT(a)
Returns whatever a constant is a valid alignment.
Definition: chalign.h:98
void *(* memgetfunc_t)(size_t size, unsigned align)
Memory get function.
Definition: chmemcore.h:71
#define MEM_IS_ALIGNED(p, a)
Returns whatever a pointer or memory size is aligned.
Definition: chalign.h:90
size_t object_size
Memory pool objects size.
Definition: chmempools.h:66
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition: chschd.c:456
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:101
static void chGuardedPoolAdd(guarded_memory_pool_t *gmp, void *objp)
Adds an object to a guarded memory pool.
Definition: chmempools.h:337
struct pool_header * next
Pointer to the header.
Definition: chmempools.h:65
struct pool_header * next
Pointer to the next pool header in the list.
Definition: chmempools.h:57
void * chPoolAlloc(memory_pool_t *mp)
Allocates an object from a memory pool.
Definition: chmempools.c:161
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
void chSemObjectInit(semaphore_t *sp, cnt_t n)
Initializes a semaphore with the specified counter value.
Definition: chsem.c:97
static void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp)
Releases an object into a guarded memory pool.
Definition: chmempools.h:299
void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n)
Loads a memory pool with an array of static objects.
Definition: chmempools.c:106
semaphore_t sem
Counter semaphore guarding the memory pool.
Definition: chmempools.h:78
void * chPoolAllocI(memory_pool_t *mp)
Allocates an object from a memory pool.
Definition: chmempools.c:129
void * chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, sysinterval_t timeout)
Allocates an object from a guarded memory pool.
Definition: chmempools.c:275
void chDbgCheckClassI(void)
I-class functions context check.
Definition: chdebug.c:233
void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, unsigned align, memgetfunc_t provider)
Initializes an empty memory pool.
Definition: chmempools.c:77
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, size_t size, unsigned align)
Initializes an empty guarded memory pool.
Definition: chmempools.c:226
static void chPoolAdd(memory_pool_t *mp, void *objp)
Adds an object to a memory pool.
Definition: chmempools.h:210
Guarded memory pool descriptor.
Definition: chmempools.h:77
ChibiOS/RT main include file.
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:247