]> begriffs open source - freertos/blob - include/list.h
Update History.txt (#160)
[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  * https://www.FreeRTOS.org\r
23  * https://github.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 \r
56 #ifndef LIST_H\r
57 #define LIST_H\r
58 \r
59 #ifndef INC_FREERTOS_H\r
60     #error "FreeRTOS.h must be included before list.h"\r
61 #endif\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 /* *INDENT-OFF* */\r
96 #ifdef __cplusplus\r
97     extern "C" {\r
98 #endif\r
99 /* *INDENT-ON* */\r
100 \r
101 /* Macros that can be used to place known values within the list structures,\r
102  * then check that the known values do not get corrupted during the execution of\r
103  * the application.   These may catch the list data structures being overwritten in\r
104  * memory.  They will not catch data errors caused by incorrect configuration or\r
105  * use of FreeRTOS.*/\r
106 #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )\r
107     /* Define the macros to do nothing. */\r
108     #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE\r
109     #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE\r
110     #define listFIRST_LIST_INTEGRITY_CHECK_VALUE\r
111     #define listSECOND_LIST_INTEGRITY_CHECK_VALUE\r
112     #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )\r
113     #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )\r
114     #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )\r
115     #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )\r
116     #define listTEST_LIST_ITEM_INTEGRITY( pxItem )\r
117     #define listTEST_LIST_INTEGRITY( pxList )\r
118 #else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */\r
119     /* Define macros that add new members into the list structures. */\r
120     #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE     TickType_t xListItemIntegrityValue1;\r
121     #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE    TickType_t xListItemIntegrityValue2;\r
122     #define listFIRST_LIST_INTEGRITY_CHECK_VALUE          TickType_t xListIntegrityValue1;\r
123     #define listSECOND_LIST_INTEGRITY_CHECK_VALUE         TickType_t xListIntegrityValue2;\r
124 \r
125 /* Define macros that set the new structure members to known values. */\r
126     #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )     ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE\r
127     #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )    ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE\r
128     #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )              ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE\r
129     #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )              ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE\r
130 \r
131 /* Define macros that will assert if one of the structure members does not\r
132  * contain its expected value. */\r
133     #define listTEST_LIST_ITEM_INTEGRITY( pxItem )                      configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )\r
134     #define listTEST_LIST_INTEGRITY( pxList )                           configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )\r
135 #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */\r
136 \r
137 \r
138 /*\r
139  * Definition of the only type of object that a list can contain.\r
140  */\r
141 struct xLIST;\r
142 struct xLIST_ITEM\r
143 {\r
144     listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE               /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
145     configLIST_VOLATILE TickType_t xItemValue;              /*< The value being listed.  In most cases this is used to sort the list in descending order. */\r
146     struct xLIST_ITEM * configLIST_VOLATILE pxNext;         /*< Pointer to the next ListItem_t in the list. */\r
147     struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;     /*< Pointer to the previous ListItem_t in the list. */\r
148     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
149     struct xLIST * configLIST_VOLATILE pxContainer;         /*< Pointer to the list in which this list item is placed (if any). */\r
150     listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE              /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
151 };\r
152 typedef struct xLIST_ITEM ListItem_t;                       /* For some reason lint wants this as two separate definitions. */\r
153 \r
154 struct xMINI_LIST_ITEM\r
155 {\r
156     listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE     /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
157     configLIST_VOLATILE TickType_t xItemValue;\r
158     struct xLIST_ITEM * configLIST_VOLATILE pxNext;\r
159     struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;\r
160 };\r
161 typedef struct xMINI_LIST_ITEM MiniListItem_t;\r
162 \r
163 /*\r
164  * Definition of the type of queue used by the scheduler.\r
165  */\r
166 typedef struct xLIST\r
167 {\r
168     listFIRST_LIST_INTEGRITY_CHECK_VALUE          /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
169     volatile UBaseType_t uxNumberOfItems;\r
170     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
171     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
172     listSECOND_LIST_INTEGRITY_CHECK_VALUE         /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */\r
173 } List_t;\r
174 \r
175 /*\r
176  * Access macro to set the owner of a list item.  The owner of a list item\r
177  * is the object (usually a TCB) that contains the list item.\r
178  *\r
179  * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER\r
180  * \ingroup LinkedList\r
181  */\r
182 #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )    ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )\r
183 \r
184 /*\r
185  * Access macro to get the owner of a list item.  The owner of a list item\r
186  * is the object (usually a TCB) that contains the list item.\r
187  *\r
188  * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER\r
189  * \ingroup LinkedList\r
190  */\r
191 #define listGET_LIST_ITEM_OWNER( pxListItem )             ( ( pxListItem )->pvOwner )\r
192 \r
193 /*\r
194  * Access macro to set the value of the list item.  In most cases the value is\r
195  * used to sort the list in descending order.\r
196  *\r
197  * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE\r
198  * \ingroup LinkedList\r
199  */\r
200 #define listSET_LIST_ITEM_VALUE( pxListItem, xValue )     ( ( pxListItem )->xItemValue = ( xValue ) )\r
201 \r
202 /*\r
203  * Access macro to retrieve the value of the list item.  The value can\r
204  * represent anything - for example the priority of a task, or the time at\r
205  * which a task should be unblocked.\r
206  *\r
207  * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE\r
208  * \ingroup LinkedList\r
209  */\r
210 #define listGET_LIST_ITEM_VALUE( pxListItem )             ( ( pxListItem )->xItemValue )\r
211 \r
212 /*\r
213  * Access macro to retrieve the value of the list item at the head of a given\r
214  * list.\r
215  *\r
216  * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE\r
217  * \ingroup LinkedList\r
218  */\r
219 #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )        ( ( ( pxList )->xListEnd ).pxNext->xItemValue )\r
220 \r
221 /*\r
222  * Return the list item at the head of the list.\r
223  *\r
224  * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY\r
225  * \ingroup LinkedList\r
226  */\r
227 #define listGET_HEAD_ENTRY( pxList )                      ( ( ( pxList )->xListEnd ).pxNext )\r
228 \r
229 /*\r
230  * Return the next list item.\r
231  *\r
232  * \page listGET_NEXT listGET_NEXT\r
233  * \ingroup LinkedList\r
234  */\r
235 #define listGET_NEXT( pxListItem )                        ( ( pxListItem )->pxNext )\r
236 \r
237 /*\r
238  * Return the list item that marks the end of the list\r
239  *\r
240  * \page listGET_END_MARKER listGET_END_MARKER\r
241  * \ingroup LinkedList\r
242  */\r
243 #define listGET_END_MARKER( pxList )                      ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )\r
244 \r
245 /*\r
246  * Access macro to determine if a list contains any items.  The macro will\r
247  * only have the value true if the list is empty.\r
248  *\r
249  * \page listLIST_IS_EMPTY listLIST_IS_EMPTY\r
250  * \ingroup LinkedList\r
251  */\r
252 #define listLIST_IS_EMPTY( pxList )                       ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )\r
253 \r
254 /*\r
255  * Access macro to return the number of items in the list.\r
256  */\r
257 #define listCURRENT_LIST_LENGTH( pxList )                 ( ( pxList )->uxNumberOfItems )\r
258 \r
259 /*\r
260  * Access function to obtain the owner of the next entry in a list.\r
261  *\r
262  * The list member pxIndex is used to walk through a list.  Calling\r
263  * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list\r
264  * and returns that entry's pxOwner parameter.  Using multiple calls to this\r
265  * function it is therefore possible to move through every item contained in\r
266  * a list.\r
267  *\r
268  * The pxOwner parameter of a list item is a pointer to the object that owns\r
269  * the list item.  In the scheduler this is normally a task control block.\r
270  * The pxOwner parameter effectively creates a two way link between the list\r
271  * item and its owner.\r
272  *\r
273  * @param pxTCB pxTCB is set to the address of the owner of the next list item.\r
274  * @param pxList The list from which the next item owner is to be returned.\r
275  *\r
276  * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY\r
277  * \ingroup LinkedList\r
278  */\r
279 #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )                                           \\r
280     {                                                                                          \\r
281         List_t * const pxConstList = ( pxList );                                               \\r
282         /* Increment the index to the next item and return the item, ensuring */               \\r
283         /* we don't return the marker used at the end of the list.  */                         \\r
284         ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                           \\r
285         if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \\r
286         {                                                                                      \\r
287             ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                       \\r
288         }                                                                                      \\r
289         ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                         \\r
290     }\r
291 \r
292 \r
293 /*\r
294  * Access function to obtain the owner of the first entry in a list.  Lists\r
295  * are normally sorted in ascending item value order.\r
296  *\r
297  * This function returns the pxOwner member of the first item in the list.\r
298  * The pxOwner parameter of a list item is a pointer to the object that owns\r
299  * the list item.  In the scheduler this is normally a task control block.\r
300  * The pxOwner parameter effectively creates a two way link between the list\r
301  * item and its owner.\r
302  *\r
303  * @param pxList The list from which the owner of the head item is to be\r
304  * returned.\r
305  *\r
306  * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY\r
307  * \ingroup LinkedList\r
308  */\r
309 #define listGET_OWNER_OF_HEAD_ENTRY( pxList )            ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner )\r
310 \r
311 /*\r
312  * Check to see if a list item is within a list.  The list item maintains a\r
313  * "container" pointer that points to the list it is in.  All this macro does\r
314  * is check to see if the container and the list match.\r
315  *\r
316  * @param pxList The list we want to know if the list item is within.\r
317  * @param pxListItem The list item we want to know if is in the list.\r
318  * @return pdTRUE if the list item is in the list, otherwise pdFALSE.\r
319  */\r
320 #define listIS_CONTAINED_WITHIN( pxList, pxListItem )    ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )\r
321 \r
322 /*\r
323  * Return the list a list item is contained within (referenced from).\r
324  *\r
325  * @param pxListItem The list item being queried.\r
326  * @return A pointer to the List_t object that references the pxListItem\r
327  */\r
328 #define listLIST_ITEM_CONTAINER( pxListItem )            ( ( pxListItem )->pxContainer )\r
329 \r
330 /*\r
331  * This provides a crude means of knowing if a list has been initialised, as\r
332  * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()\r
333  * function.\r
334  */\r
335 #define listLIST_IS_INITIALISED( pxList )                ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )\r
336 \r
337 /*\r
338  * Must be called before a list is used!  This initialises all the members\r
339  * of the list structure and inserts the xListEnd item into the list as a\r
340  * marker to the back of the list.\r
341  *\r
342  * @param pxList Pointer to the list being initialised.\r
343  *\r
344  * \page vListInitialise vListInitialise\r
345  * \ingroup LinkedList\r
346  */\r
347 void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;\r
348 \r
349 /*\r
350  * Must be called before a list item is used.  This sets the list container to\r
351  * null so the item does not think that it is already contained in a list.\r
352  *\r
353  * @param pxItem Pointer to the list item being initialised.\r
354  *\r
355  * \page vListInitialiseItem vListInitialiseItem\r
356  * \ingroup LinkedList\r
357  */\r
358 void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;\r
359 \r
360 /*\r
361  * Insert a list item into a list.  The item will be inserted into the list in\r
362  * a position determined by its item value (descending item value order).\r
363  *\r
364  * @param pxList The list into which the item is to be inserted.\r
365  *\r
366  * @param pxNewListItem The item that is to be placed in the list.\r
367  *\r
368  * \page vListInsert vListInsert\r
369  * \ingroup LinkedList\r
370  */\r
371 void vListInsert( List_t * const pxList,\r
372                   ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;\r
373 \r
374 /*\r
375  * Insert a list item into a list.  The item will be inserted in a position\r
376  * such that it will be the last item within the list returned by multiple\r
377  * calls to listGET_OWNER_OF_NEXT_ENTRY.\r
378  *\r
379  * The list member pxIndex is used to walk through a list.  Calling\r
380  * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.\r
381  * Placing an item in a list using vListInsertEnd effectively places the item\r
382  * in the list position pointed to by pxIndex.  This means that every other\r
383  * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before\r
384  * the pxIndex parameter again points to the item being inserted.\r
385  *\r
386  * @param pxList The list into which the item is to be inserted.\r
387  *\r
388  * @param pxNewListItem The list item to be inserted into the list.\r
389  *\r
390  * \page vListInsertEnd vListInsertEnd\r
391  * \ingroup LinkedList\r
392  */\r
393 void vListInsertEnd( List_t * const pxList,\r
394                      ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;\r
395 \r
396 /*\r
397  * Remove an item from a list.  The list item has a pointer to the list that\r
398  * it is in, so only the list item need be passed into the function.\r
399  *\r
400  * @param uxListRemove The item to be removed.  The item will remove itself from\r
401  * the list pointed to by it's pxContainer parameter.\r
402  *\r
403  * @return The number of items that remain in the list after the list item has\r
404  * been removed.\r
405  *\r
406  * \page uxListRemove uxListRemove\r
407  * \ingroup LinkedList\r
408  */\r
409 UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;\r
410 \r
411 /* *INDENT-OFF* */\r
412 #ifdef __cplusplus\r
413     }\r
414 #endif\r
415 /* *INDENT-ON* */\r
416 \r
417 #endif /* ifndef LIST_H */\r