aboutsummaryrefslogtreecommitdiffstats
path: root/os/kernel/src/chmempools.c
blob: 6d1f7e86611290b90e7b9bce9dbe162820c93018 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * @file    chmempools.c
 * @brief   Memory Pools code.
 *
 * @addtogroup pools
 * @details Memory Pools related APIs and services.
 *          <h2>Operation mode</h2>
 *          The Memory Pools APIs allow to allocate/free fixed size objects in
 *          <b>constant time</b> and reliably without memory fragmentation
 *          problems.
 * @pre     In order to use the memory pools APIs the @p CH_USE_MEMPOOLS option
 *          must be enabled in @p chconf.h.
 * @{
 */

#include "ch.h"

#if CH_USE_MEMPOOLS || defined(__DOXYGEN__)
/**
 * @brief   Initializes an empty memory pool.
 * @note    The size is internally aligned to be a multiple of the
 *          @p stkalign_t type size.
 *
 * @param[out] mp       pointer to a @p MemoryPool structure
 * @param[in] size      the size of the objects contained in this memory pool,
 *                      the minimum accepted size is the size of a pointer to
 *                      void.
 * @param[in] provider  memory provider function for the memory pool or
 *                      @p NULL if the pool is not allowed to grow
 *                      automatically
 *
 * @init
 */
void chPoolInit(MemoryPool *mp, size_t size, memgetfunc_t provider) {

  chDbgCheck((mp != NULL) && (size >= sizeof(void *)), "chPoolInit");

  mp->mp_next = NULL;
  mp->mp_object_size = MEM_ALIGN_NEXT(size);
  mp->mp_provider = provider;
}

/**
 * @brief   Allocates an object from a memory pool.
 *
 * @param[in] mp        pointer to a @p MemoryPool structure
 * @return              The pointer to the allocated object.
 * @retval NULL         if pool is empty.
 *
 * @iclass
 */
void *chPoolAllocI(MemoryPool *mp) {
  void *objp;

  chDbgCheckClassI();
  chDbgCheck(mp != NULL, "chPoolAllocI");

  if ((objp = mp->mp_next) != NULL)
    mp->mp_next = mp->mp_next->ph_next;
  else if (mp->mp_provider != NULL)
    objp = mp->mp_provider(mp->mp_object_size);
  return objp;
}

/**
 * @brief   Allocates an object from a memory pool.
 *
 * @param[in] mp        pointer to a @p MemoryPool structure
 * @return              The pointer to the allocated object.
 * @retval NULL         if pool is empty.
 *
 * @api
 */
void *chPoolAlloc(MemoryPool *mp) {
  void *objp;

  chSysLock();
  objp = chPoolAllocI(mp);
  chSysUnlock();
  return objp;
}

/**
 * @brief   Releases (or adds) an object into (to) a memory pool.
 * @pre     The freed object must be of the right size for the specified
 *          memory pool.
 * @pre     The freed object must be memory aligned to the size of
 *          @p stkalign_t type.
 *
 * @param[in] mp        pointer to a @p MemoryPool structure
 * @param[in] objp      the pointer to the object to be released or added
 *
 * @iclass
 */
void chPoolFreeI(MemoryPool *mp, void *objp) {
  struct pool_header *php = objp;

  chDbgCheckClassI();
  chDbgCheck((mp != NULL) && (objp != NULL) && MEM_IS_ALIGNED(objp),
             "chPoolFreeI");

  php->ph_next = mp->mp_next;
  mp->mp_next = php;
}

/**
 * @brief   Releases (or adds) an object into (to) a memory pool.
 * @pre     The freed object must be of the right size for the specified
 *          memory pool.
 * @pre     The freed object must be memory aligned to the size of
 *          @p stkalign_t type.
 *
 * @param[in] mp        pointer to a @p MemoryPool structure
 * @param[in] objp      the pointer to the object to be released or added
 *
 * @api
 */
void chPoolFree(MemoryPool *mp, void *objp) {

  chSysLock();
  chPoolFreeI(mp, objp);
  chSysUnlock();
}
#endif /* CH_USE_MEMPOOLS */

/** @} */