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