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