TNeoKernel  v1.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tn_fmem.h
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * TNeoKernel: real-time kernel initially based on TNKernel
4  *
5  * TNKernel: copyright © 2004, 2013 Yuri Tiomkin.
6  * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen.
7  * TNeoKernel: copyright © 2014 Dmitry Frank.
8  *
9  * TNeoKernel was born as a thorough review and re-implementation of
10  * TNKernel. The new kernel has well-formed code, inherited bugs are fixed
11  * as well as new features being added, and it is tested carefully with
12  * unit-tests.
13  *
14  * API is changed somewhat, so it's not 100% compatible with TNKernel,
15  * hence the new name: TNeoKernel.
16  *
17  * Permission to use, copy, modify, and distribute this software in source
18  * and binary forms and its documentation for any purpose and without fee
19  * is hereby granted, provided that the above copyright notice appear
20  * in all copies and that both that copyright notice and this permission
21  * notice appear in supporting documentation.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  ******************************************************************************/
36 
37 /**
38  * \file
39  *
40  * Fixed memory blocks pool.
41  *
42  * A fixed-sized memory blocks pool is used for managing fixed-sized memory
43  * blocks dynamically. A pool has a memory area where fixed-sized memory blocks
44  * are allocated and the wait queue for acquiring a memory block. If there are
45  * no free memory blocks, a task trying to acquire a memory block will be
46  * placed into the wait queue until a free memory block arrives (another task
47  * returns it to the memory pool).
48  */
49 
50 #ifndef _TN_MEM_H
51 #define _TN_MEM_H
52 
53 /*******************************************************************************
54  * INCLUDED FILES
55  ******************************************************************************/
56 
57 #include "tn_list.h"
58 #include "tn_common.h"
59 
60 
61 
62 #ifdef __cplusplus
63 extern "C" { /*}*/
64 #endif
65 
66 /*******************************************************************************
67  * PUBLIC TYPES
68  ******************************************************************************/
69 
70 /**
71  * Fixed memory blocks pool
72  */
73 struct TN_FMem {
74  ///
75  /// list of tasks waiting for free memory block
76  struct TN_ListItem wait_queue;
77 
78  ///
79  /// block size (in bytes); note that it should be a multiple of
80  /// `sizeof(#TN_UWord})`, use a macro `TN_MAKE_ALIG_SIZE()` for that.
81  ///
82  /// @see `TN_MAKE_ALIG_SIZE()`
83  unsigned int block_size;
84  ///
85  /// capacity (total blocks count)
87  ///
88  /// free blocks count
90  ///
91  /// memory pool start address; note that it should be a multiple of
92  /// `sizeof(#TN_UWord)`.
93  void *start_addr;
94  ///
95  /// ptr to free block list
96  void *free_list;
97  ///
98  /// id for object validity verification
100 };
101 
102 
103 /**
104  * FMem-specific fields related to waiting task,
105  * to be included in struct TN_Task.
106  */
108  /// if task tries to receive data from memory pool,
109  /// and there's no more free blocks in the pool, location to store
110  /// pointer is saved in this field
111  void *data_elem;
112 };
113 
114 
115 /*******************************************************************************
116  * GLOBAL VARIABLES
117  ******************************************************************************/
118 
119 /*******************************************************************************
120  * DEFINITIONS
121  ******************************************************************************/
122 
123 /**
124  * Convenience macro for the definition of buffer for memory pool. See
125  * `tn_fmem_create()` for usage example.
126  *
127  * @param name
128  * C variable name of the buffer array (this name should be given
129  * to the `tn_fmem_create()` function as the `start_addr` argument)
130  * @param item_type
131  * Type of item in the memory pool, like `struct MyMemoryItem`.
132  * @param size
133  * Number of items in the memory pool.
134  */
135 #define TN_FMEM_BUF_DEF(name, item_type, size) \
136  TN_UWord name[ \
137  (size) \
138  * (TN_MAKE_ALIG_SIZE(sizeof(item_type)) / sizeof(TN_UWord)) \
139  ]
140 
141 
142 
143 
144 /*******************************************************************************
145  * PUBLIC FUNCTION PROTOTYPES
146  ******************************************************************************/
147 
148 /**
149  * Construct fixed memory blocks pool. `id_fmp` field should not contain
150  * `#TN_ID_FSMEMORYPOOL`, otherwise, `#TN_RC_WPARAM` is returned.
151  *
152  * Note that `start_addr` and `block_size` should be a multiple of
153  * `sizeof(#TN_UWord)`.
154  *
155  * For the definition of buffer, convenience macro `TN_FMEM_BUF_DEF()` was
156  * invented.
157  *
158  * Typical definition looks as follows:
159  *
160  * \code{.c}
161  * //-- number of blocks in the pool
162  * #define MY_MEMORY_BUF_SIZE 8
163  *
164  * //-- type for memory block
165  * struct MyMemoryItem {
166  * // ... arbitrary fields ...
167  * };
168  *
169  * //-- define buffer for memory pool
170  * TN_FMEM_BUF_DEF(my_fmem_buf, struct MyMemoryItem, MY_MEMORY_BUF_SIZE);
171  *
172  * //-- define memory pool structure
173  * struct TN_FMem my_fmem;
174  * \endcode
175  *
176  * And then, construct your `my_fmem` as follows:
177  *
178  * \code{.c}
179  * enum TN_RCode rc;
180  * rc = tn_fmem_create( &my_fmem,
181  * my_fmem_buf,
182  * TN_MAKE_ALIG_SIZE(sizeof(struct MyMemoryItem)),
183  * MY_MEMORY_BUF_SIZE );
184  * if (rc != TN_RC_OK){
185  * //-- handle error
186  * }
187  * \endcode
188  *
189  * If given `start_addr` and/or `block_size` aren't aligned properly,
190  * `#TN_RC_WPARAM` is returned.
191  *
192  * $(TN_CALL_FROM_TASK)
193  * $(TN_CALL_FROM_ISR)
194  * $(TN_LEGEND_LINK)
195  *
196  * @param fmem pointer to already allocated `struct TN_FMem`.
197  * @param start_addr pointer to start of the array; should be aligned properly,
198  * see example above
199  * @param block_size size of memory block; should be a multiple of
200  * `sizeof(#TN_UWord)`, see example above
201  * @param blocks_cnt capacity (total number of blocks in the memory pool)
202  *
203  * @return
204  * * `#TN_RC_OK` if memory pool was successfully created;
205  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
206  * is available: `#TN_RC_WPARAM`.
207  *
208  * @see TN_MAKE_ALIG_SIZE
209  */
211  struct TN_FMem *fmem,
212  void *start_addr,
213  unsigned int block_size,
214  int blocks_cnt
215  );
216 
217 /**
218  * Destruct fixed memory blocks pool.
219  *
220  * All tasks that wait for free memory block become runnable with
221  * `#TN_RC_DELETED` code returned.
222  *
223  * $(TN_CALL_FROM_TASK)
224  * $(TN_CAN_SWITCH_CONTEXT)
225  * $(TN_LEGEND_LINK)
226  *
227  * @param fmem pointer to memory pool to be deleted
228  *
229  * @return
230  * * `#TN_RC_OK` if memory pool is successfully deleted;
231  * * `#TN_RC_WCONTEXT` if called from wrong context;
232  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
233  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
234  *
235  */
236 enum TN_RCode tn_fmem_delete(struct TN_FMem *fmem);;
237 
238 /**
239  * Get memory block from the pool. Start address of the memory block is returned
240  * through the `p_data` argument. The content of memory block is undefined.
241  * If there is no free block in the pool, behavior depends on `timeout` value:
242  * refer to `#TN_Timeout`.
243  *
244  * $(TN_CALL_FROM_TASK)
245  * $(TN_CAN_SWITCH_CONTEXT)
246  * $(TN_CAN_SLEEP)
247  * $(TN_LEGEND_LINK)
248  *
249  * @param fmem
250  * Pointer to memory pool
251  * @param p_data
252  * Address of the `(void *)` to which received block address will be saved
253  * @param timeout
254  * Refer to `#TN_Timeout`
255  *
256  * @return
257  * * `#TN_RC_OK` if block was successfully returned through `p_data`;
258  * * `#TN_RC_WCONTEXT` if called from wrong context;
259  * * Other possible return codes depend on `timeout` value,
260  * refer to `#TN_Timeout`
261  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
262  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
263  */
264 enum TN_RCode tn_fmem_get(
265  struct TN_FMem *fmem,
266  void **p_data,
267  TN_Timeout timeout
268  );
269 
270 /**
271  * The same as `tn_fmem_get()` with zero timeout
272  *
273  * $(TN_CALL_FROM_TASK)
274  * $(TN_CAN_SWITCH_CONTEXT)
275  * $(TN_LEGEND_LINK)
276  */
277 enum TN_RCode tn_fmem_get_polling(struct TN_FMem *fmem, void **p_data);
278 
279 /**
280  * The same as `tn_fmem_get()` with zero timeout, but for using in the ISR.
281  *
282  * $(TN_CALL_FROM_ISR)
283  * $(TN_CAN_SWITCH_CONTEXT)
284  * $(TN_LEGEND_LINK)
285  */
286 enum TN_RCode tn_fmem_iget_polling(struct TN_FMem *fmem, void **p_data);
287 
288 
289 /**
290  * Release memory block back to the pool. The kernel does not check the
291  * validity of the membership of given block in the memory pool.
292  * If all the memory blocks in the pool are free already, `#TN_RC_OVERFLOW`
293  * is returned.
294  *
295  * $(TN_CALL_FROM_TASK)
296  * $(TN_CAN_SWITCH_CONTEXT)
297  * $(TN_LEGEND_LINK)
298  *
299  * @param fmem
300  * Pointer to memory pool.
301  * @param p_data
302  * Address of the memory block to release.
303  *
304  * @return
305  * * `#TN_RC_OK` on success
306  * * `#TN_RC_WCONTEXT` if called from wrong context;
307  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
308  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
309  */
310 enum TN_RCode tn_fmem_release(struct TN_FMem *fmem, void *p_data);
311 
312 /**
313  * The same as `tn_fmem_get()`, but for using in the ISR.
314  *
315  * $(TN_CALL_FROM_ISR)
316  * $(TN_CAN_SWITCH_CONTEXT)
317  * $(TN_LEGEND_LINK)
318  */
319 enum TN_RCode tn_fmem_irelease(struct TN_FMem *fmem, void *p_data);
320 
321 
322 
323 #ifdef __cplusplus
324 } /* extern "C" */
325 #endif
326 
327 #endif // _TN_MEM_H
328 
329 /*******************************************************************************
330  * end of file
331  ******************************************************************************/
332 
333 
struct TN_ListItem wait_queue
list of tasks waiting for free memory block
Definition: tn_fmem.h:76
enum TN_RCode tn_fmem_release(struct TN_FMem *fmem, void *p_data)
Release memory block back to the pool.
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:99
TN_ObjId
Magic number for object validity verification.
Definition: tn_common.h:87
unsigned long TN_Timeout
The value representing maximum number of system ticks to wait.
Definition: tn_common.h:203
Definitions used through the whole kernel.
int free_blocks_cnt
free blocks count
Definition: tn_fmem.h:89
enum TN_ObjId id_fmp
id for object validity verification
Definition: tn_fmem.h:99
int blocks_cnt
capacity (total blocks count)
Definition: tn_fmem.h:86
Fixed memory blocks pool.
Definition: tn_fmem.h:73
void * free_list
ptr to free block list
Definition: tn_fmem.h:96
enum TN_RCode tn_fmem_iget_polling(struct TN_FMem *fmem, void **p_data)
The same as tn_fmem_get() with zero timeout, but for using in the ISR.
enum TN_RCode tn_fmem_get_polling(struct TN_FMem *fmem, void **p_data)
The same as tn_fmem_get() with zero timeout.
void * start_addr
memory pool start address; note that it should be a multiple of sizeof(TN_UWord). ...
Definition: tn_fmem.h:93
enum TN_RCode tn_fmem_create(struct TN_FMem *fmem, void *start_addr, unsigned int block_size, int blocks_cnt)
Construct fixed memory blocks pool.
enum TN_RCode tn_fmem_irelease(struct TN_FMem *fmem, void *p_data)
The same as tn_fmem_get(), but for using in the ISR.
void * data_elem
if task tries to receive data from memory pool, and there's no more free blocks in the pool...
Definition: tn_fmem.h:111
unsigned int block_size
block size (in bytes); note that it should be a multiple of sizeof(TN_UWord}), use a macro TN_MAKE_AL...
Definition: tn_fmem.h:83
enum TN_RCode tn_fmem_delete(struct TN_FMem *fmem)
Destruct fixed memory blocks pool.
FMem-specific fields related to waiting task, to be included in struct TN_Task.
Definition: tn_fmem.h:107
enum TN_RCode tn_fmem_get(struct TN_FMem *fmem, void **p_data, TN_Timeout timeout)
Get memory block from the pool.