]> begriffs open source - freertos/blob - include/list.h
Add support for privileged heap to ARMV8-M ports (#85)
[freertos] / include / list.h
1 /*\r
2  * FreeRTOS Kernel V10.3.1\r
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*\r
29  * This is the list implementation used by the scheduler.  While it is tailored\r
30  * heavily for the schedulers needs, it is also available for use by\r
31  * application code.\r
32  *\r
33  * list_ts can only store pointers to list_item_ts.  Each ListItem_t contains a\r
34  * numeric value (xItemValue).  Most of the time the lists are sorted in\r
35  * descending item value order.\r
36  *\r
37  * Lists are created already containing one list item.  The value of this\r
38  * item is the maximum possible that can be stored, it is therefore always at\r
39  * the end of the list and acts as a marker.  The list member pxHead always\r
40  * points to this marker - even though it is at the tail of the list.  This\r
41  * is because the tail contains a wrap back pointer to the true head of\r
42  * the list.\r
43  *\r
44  * In addition to it's value, each list item contains a pointer to the next\r
45  * item in the list (pxNext), a pointer to the list it is in (pxContainer)\r
46  * and a pointer to back to the object that contains it.  These later two\r
47  * pointers are included for efficiency of list manipulation.  There is\r
48  * effectively a two way link between the object containing the list item and\r
49  * the list item itself.\r
50  *\r
51  *\r
52  * \page ListIntroduction List Implementation\r
53  * \ingroup FreeRTOSIntro\r
54  */\r
55 \r
56 #ifndef INC_FREERTOS_H\r
57     #error FreeRTOS.h must be included before list.h\r
58 #endif\r
59 \r
60 #ifndef LIST_H\r
61     #define LIST_H\r
62 \r
63 /*\r
64  * The list structure members are modified from within interrupts, and therefore\r
65  * by rights should be declared volatile.  However, they are only modified in a\r
66  * functionally atomic way (within critical sections of with the scheduler\r
67  * suspended) and are either passed by reference into a function or indexed via\r
68  * a volatile variable.  Therefore, in all use cases tested so far, the volatile\r
69  * qualifier can be omitted in order to provide a moderate performance\r
70  * improvement without adversely affecting functional behaviour.  The assembly\r
71  * instructions generated by the IAR, ARM and GCC compilers when the respective\r
72  * compiler's options were set for maximum optimisation has been inspected and\r
73  * deemed to be as intended.  That said, as compiler technology advances, and\r
74  * especially if aggressive cross module optimisation is used (a use case that\r
75  * has not been exercised to any great extend) then it is feasible that the\r
76  * volatile qualifier will be needed for correct optimisation.  It is expected\r
77  * that a compiler removing essential code because, without the volatile\r
78  * qualifier on the list structure members and with aggressive cross module\r
79  * optimisation, the compiler deemed the code unnecessary will result in\r
80  * complete and obvious failure of the scheduler.  If this is ever experienced\r
81  * then the volatile qualifier can be inserted in the relevant places within the\r
82  * list structures by simply defining configLIST_VOLATILE to volatile in\r
83  * FreeRTOSConfig.h (as per the example at the bottom of this comment block).\r
84  * If configLIST_VOLATILE is not defined then the preprocessor directives below\r
85  * will simply #define configLIST_VOLATILE away completely.\r
86  *\r
87  * To use volatile list structure members then add the following line to\r
88  * FreeRTOSConfig.h (without the quotes):\r
89  * "#define configLIST_VOLATILE volatile"\r
90  */\r
91     #ifndef configLIST_VOLATILE\r
92         #define configLIST_VOLATILE\r
93     #endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */\r
94 \r
95     #ifdef __cplusplus\r
96         extern "C" {\r
97     #endif\r
98 \r
99 /* Macros that can be used to place known values within the list structures,\r
100  * then check that the known values do not get corrupted during the execution of\r
101  * the application.   These may catch the list data structures being overwritten in\r
102  * memory.  They will not catch data errors caused by incorrect configuration or\r
103  * use of FreeRTOS.*/\r
104     #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )\r
105         /* Define the macros to do nothing. */\r
106         #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE\r
107         #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE\r
108         #define listFIRST_LIST_INTEGRITY_CHECK_VALUE\r
109         #define listSECOND_LIST_INTEGRITY_CHECK_VALUE\r
110         #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )\r
111         #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )\r
112         #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )\r
113         #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )\r
114         #define listTEST_LIST_ITEM_INTEGRITY( pxItem )\r
115         #define listTEST_LIST_INTEGRITY( pxList )\r
116     #else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */\r
117         /* Define macros that add new members into the list structures. */\r
118         #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE     TickType_t xListItemIntegrityValue1;\r
119         #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE    TickType_t xListItemIntegrityValue2;\r
120         #define listFIRST_LIST_INTEGRITY_CHECK_VALUE          TickType_t xListIntegrityValue1;\r
121         #define listSECOND_LIST_INTEGRITY_CHECK_VALUE         TickType_t xListIntegrityValue2;\r
122 \r
123 /* Define macros that set the new structure members to known values. */\r
124         #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )     ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE\r
125         #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )    ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE\r
126         #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )              ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE\r
127         #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )              ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE\r
128 \r
129 /* Define macros that will assert if one of the structure members does not\r
130  * contain its expected value. */\r
131         #define listTEST_LIST_ITEM_INTEGRITY( pxItem )                      configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )\r
132         #define listTEST_LIST_INTEGRITY( pxList )                           configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )\r
133     #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */\r
134 \r
135 \r
136 /*\r
137  * Definition of the only type of object that a list can contain.\r
138  */\r
139     struct xLIST;\r
140     struct xLIST_ITEM\r
141     {\r
142         listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE           /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
143         configLIST_VOLATILE TickType_t xItemValue;          /*< The value being listed.  In most cases this is used to sort the list in descending order. */\r
144         struct xLIST_ITEM * configLIST_VOLATILE pxNext;     /*< Pointer to the next ListItem_t in the list. */\r
145         struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */\r
146         void * pvOwner;                                     /*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */\r
147         struct xLIST * configLIST_VOLATILE pxContainer;     /*< Pointer to the list in which this list item is placed (if any). */\r
148         listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE          /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
149     };\r
150     typedef struct xLIST_ITEM ListItem_t;                   /* For some reason lint wants this as two separate definitions. */\r
151 \r
152     struct xMINI_LIST_ITEM\r
153     {\r
154         listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
155         configLIST_VOLATILE TickType_t xItemValue;\r
156         struct xLIST_ITEM * configLIST_VOLATILE pxNext;\r
157         struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;\r
158     };\r
159     typedef struct xMINI_LIST_ITEM MiniListItem_t;\r
160 \r
161 /*\r
162  * Definition of the type of queue used by the scheduler.\r
163  */\r
164     typedef struct xLIST\r
165     {\r
166         listFIRST_LIST_INTEGRITY_CHECK_VALUE      /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
167         volatile UBaseType_t uxNumberOfItems;\r
168         ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list.  Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */\r
169         MiniListItem_t xListEnd;                  /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */\r
170         listSECOND_LIST_INTEGRITY_CHECK_VALUE     /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
171     } List_t;\r
172 \r
173 /*\r
174  * Access macro to set the owner of a list item.  The owner of a list item\r
175  * is the object (usually a TCB) that contains the list item.\r
176  *\r
177  * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER\r
178  * \ingroup LinkedList\r
179  */\r
180     #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )    ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )\r
181 \r
182 /*\r
183  * Access macro to get the owner of a list item.  The owner of a list item\r
184  * is the object (usually a TCB) that contains the list item.\r
185  *\r
186  * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER\r
187  * \ingroup LinkedList\r
188  */\r
189     #define listGET_LIST_ITEM_OWNER( pxListItem )             ( ( pxListItem )->pvOwner )\r
190 \r
191 /*\r
192  * Access macro to set the value of the list item.  In most cases the value is\r
193  * used to sort the list in descending order.\r
194  *\r
195  * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE\r
196  * \ingroup LinkedList\r
197  */\r
198     #define listSET_LIST_ITEM_VALUE( pxListItem, xValue )     ( ( pxListItem )->xItemValue = ( xValue ) )\r
199 \r
200 /*\r
201  * Access macro to retrieve the value of the list item.  The value can\r
202  * represent anything - for example the priority of a task, or the time at\r
203  * which a task should be unblocked.\r
204  *\r
205  * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE\r
206  * \ingroup LinkedList\r
207  */\r
208     #define listGET_LIST_ITEM_VALUE( pxListItem )             ( ( pxListItem )->xItemValue )\r
209 \r
210 /*\r
211  * Access macro to retrieve the value of the list item at the head of a given\r
212  * list.\r
213  *\r
214  * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE\r
215  * \ingroup LinkedList\r
216  */\r
217     #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )        ( ( ( pxList )->xListEnd ).pxNext->xItemValue )\r
218 \r
219 /*\r
220  * Return the list item at the head of the list.\r
221  *\r
222  * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY\r
223  * \ingroup LinkedList\r
224  */\r
225     #define listGET_HEAD_ENTRY( pxList )                      ( ( ( pxList )->xListEnd ).pxNext )\r
226 \r
227 /*\r
228  * Return the next list item.\r
229  *\r
230  * \page listGET_NEXT listGET_NEXT\r
231  * \ingroup LinkedList\r
232  */\r
233     #define listGET_NEXT( pxListItem )                        ( ( pxListItem )->pxNext )\r
234 \r
235 /*\r
236  * Return the list item that marks the end of the list\r
237  *\r
238  * \page listGET_END_MARKER listGET_END_MARKER\r
239  * \ingroup LinkedList\r
240  */\r
241     #define listGET_END_MARKER( pxList )                      ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )\r
242 \r
243 /*\r
244  * Access macro to determine if a list contains any items.  The macro will\r
245  * only have the value true if the list is empty.\r
246  *\r
247  * \page listLIST_IS_EMPTY listLIST_IS_EMPTY\r
248  * \ingroup LinkedList\r
249  */\r
250     #define listLIST_IS_EMPTY( pxList )                       ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )\r
251 \r
252 /*\r
253  * Access macro to return the number of items in the list.\r
254  */\r
255     #define listCURRENT_LIST_LENGTH( pxList )                 ( ( pxList )->uxNumberOfItems )\r
256 \r
257 /*\r
258  * Access function to obtain the owner of the next entry in a list.\r
259  *\r
260  * The list member pxIndex is used to walk through a list.  Calling\r
261  * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list\r
262  * and returns that entry's pxOwner parameter.  Using multiple calls to this\r
263  * function it is therefore possible to move through every item contained in\r
264  * a list.\r
265  *\r
266  * The pxOwner parameter of a list item is a pointer to the object that owns\r
267  * the list item.  In the scheduler this is normally a task control block.\r
268  * The pxOwner parameter effectively creates a two way link between the list\r
269  * item and its owner.\r
270  *\r
271  * @param pxTCB pxTCB is set to the address of the owner of the next list item.\r
272  * @param pxList The list from which the next item owner is to be returned.\r
273  *\r
274  * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY\r
275  * \ingroup LinkedList\r
276  */\r
277     #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )                                       \\r
278     {                                                                                          \\r
279         List_t * const pxConstList = ( pxList );                                               \\r
280         /* Increment the index to the next item and return the item, ensuring */               \\r
281         /* we don't return the marker used at the end of the list.  */                         \\r
282         ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                           \\r
283         if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \\r
284         {                                                                                      \\r
285             ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                       \\r
286         }                                                                                      \\r
287         ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                         \\r
288     }\r
289 \r
290 \r
291 /*\r
292  * Access function to obtain the owner of the first entry in a list.  Lists\r
293  * are normally sorted in ascending item value order.\r
294  *\r
295  * This function returns the pxOwner member of the first item in the list.\r
296  * The pxOwner parameter of a list item is a pointer to the object that owns\r
297  * the list item.  In the scheduler this is normally a task control block.\r
298  * The pxOwner parameter effectively creates a two way link between the list\r
299  * item and its owner.\r
300  *\r
301  * @param pxList The list from which the owner of the head item is to be\r
302  * returned.\r
303  *\r
304  * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY\r
305  * \ingroup LinkedList\r
306  */\r
307     #define listGET_OWNER_OF_HEAD_ENTRY( pxList )            ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )\r
308 \r
309 /*\r
310  * Check to see if a list item is within a list.  The list item maintains a\r
311  * "container" pointer that points to the list it is in.  All this macro does\r
312  * is check to see if the container and the list match.\r
313  *\r
314  * @param pxList The list we want to know if the list item is within.\r
315  * @param pxListItem The list item we want to know if is in the list.\r
316  * @return pdTRUE if the list item is in the list, otherwise pdFALSE.\r
317  */\r
318     #define listIS_CONTAINED_WITHIN( pxList, pxListItem )    ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )\r
319 \r
320 /*\r
321  * Return the list a list item is contained within (referenced from).\r
322  *\r
323  * @param pxListItem The list item being queried.\r
324  * @return A pointer to the List_t object that references the pxListItem\r
325  */\r
326     #define listLIST_ITEM_CONTAINER( pxListItem )            ( ( pxListItem )->pxContainer )\r
327 \r
328 /*\r
329  * This provides a crude means of knowing if a list has been initialised, as\r
330  * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()\r
331  * function.\r
332  */\r
333     #define listLIST_IS_INITIALISED( pxList )                ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )\r
334 \r
335 /*\r
336  * Must be called before a list is used!  This initialises all the members\r
337  * of the list structure and inserts the xListEnd item into the list as a\r
338  * marker to the back of the list.\r
339  *\r
340  * @param pxList Pointer to the list being initialised.\r
341  *\r
342  * \page vListInitialise vListInitialise\r
343  * \ingroup LinkedList\r
344  */\r
345     void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;\r
346 \r
347 /*\r
348  * Must be called before a list item is used.  This sets the list container to\r
349  * null so the item does not think that it is already contained in a list.\r
350  *\r
351  * @param pxItem Pointer to the list item being initialised.\r
352  *\r
353  * \page vListInitialiseItem vListInitialiseItem\r
354  * \ingroup LinkedList\r
355  */\r
356     void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;\r
357 \r
358 /*\r
359  * Insert a list item into a list.  The item will be inserted into the list in\r
360  * a position determined by its item value (descending item value order).\r
361  *\r
362  * @param pxList The list into which the item is to be inserted.\r
363  *\r
364  * @param pxNewListItem The item that is to be placed in the list.\r
365  *\r
366  * \page vListInsert vListInsert\r
367  * \ingroup LinkedList\r
368  */\r
369     void vListInsert( List_t * const pxList,\r
370                       ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;\r
371 \r
372 /*\r
373  * Insert a list item into a list.  The item will be inserted in a position\r
374  * such that it will be the last item within the list returned by multiple\r
375  * calls to listGET_OWNER_OF_NEXT_ENTRY.\r
376  *\r
377  * The list member pxIndex is used to walk through a list.  Calling\r
378  * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.\r
379  * Placing an item in a list using vListInsertEnd effectively places the item\r
380  * in the list position pointed to by pxIndex.  This means that every other\r
381  * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before\r
382  * the pxIndex parameter again points to the item being inserted.\r
383  *\r
384  * @param pxList The list into which the item is to be inserted.\r
385  *\r
386  * @param pxNewListItem The list item to be inserted into the list.\r
387  *\r
388  * \page vListInsertEnd vListInsertEnd\r
389  * \ingroup LinkedList\r
390  */\r
391     void vListInsertEnd( List_t * const pxList,\r
392                          ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;\r
393 \r
394 /*\r
395  * Remove an item from a list.  The list item has a pointer to the list that\r
396  * it is in, so only the list item need be passed into the function.\r
397  *\r
398  * @param uxListRemove The item to be removed.  The item will remove itself from\r
399  * the list pointed to by it's pxContainer parameter.\r
400  *\r
401  * @return The number of items that remain in the list after the list item has\r
402  * been removed.\r
403  *\r
404  * \page uxListRemove uxListRemove\r
405  * \ingroup LinkedList\r
406  */\r
407     UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;\r
408 \r
409     #ifdef __cplusplus\r
410         }\r
411     #endif\r
412 \r
413 #endif /* ifndef LIST_H */\r