list.h 19 KB

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