目录:
一:列表、列表项、迷你列表项结构
二:列表和列表项的初始化
三:列表项插入
四:列表项遍历
五:列表项末尾插入
六:列表项删除
一:列表、列表项、迷你列表项结构
//列表
166 typedef struct xLIST
167 {
168 listFIRST_LIST_INTEGRITY_CHECK_VALUE //检查列表完整性
169 volatile UBaseType_t uxNumberOfItems; //列表项数量
170 ListItem_t * configLIST_VOLATILE pxIndex; //遍历列表时当前列表项的指针
171 MiniListItem_t xListEnd; /*< 包含最大可能项值的列表项,这意味着它始终位于列表的末尾,因此用作标记。 */
172 listSECOND_LIST_INTEGRITY_CHECK_VALUE //检查列表完整性
173 } List_t;
列表示意图
//列表项
142 struct xLIST_ITEM
143 {
144 listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
145 configLIST_VOLATILE TickType_t xItemValue; /*列表项值 */
146 struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*指向下一个列表项的指针 */
147 struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /* 指向上一个列表项的指针*/
148 void * pvOwner; /*所属任务 */
149 struct xLIST * configLIST_VOLATILE pxContainer; /*所属列表 */
150 listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
151 };
152 typedef struct xLIST_ITEM ListItem_t;
列表项示意图
//迷你列表项
154 struct xMINI_LIST_ITEM
155 {
156 listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
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;
二:列表和列表项的初始化
//列表初始化
48 void vListInitialise( List_t * const pxList )
49 {
53 pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*将列表项索引指向迷你列表项 */
54
55 /* 列表结尾值是列表中可能的最高值,以确保它保持在列表的末尾。*/
57 pxList->xListEnd.xItemValue = portMAX_DELAY;
58
59 /* 当列表为空时,迷你列表项的pxNext、pxPrevious指针指向自己*/
61 pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
62 pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
63
64 pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
65
68 listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
69 listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
70 }
列表初始化
//列表项初始化
73 void vListInitialiseItem( ListItem_t * const pxItem )
74 {
75 /* 确保列表项没有被记录在列表中 */
76 pxItem->pxContainer = NULL;
77
80 listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
81 listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
82 }
列表项初始化
三:列表项插入
//
115 void vListInsert( List_t * const pxList,
116 ListItem_t * const pxNewListItem )
117 {
118 ListItem_t * pxIterator;
119 const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
120
121 /*检查列表和列表项数据的完整性,仅当configASSERT()定义时有效。*/
124 listTEST_LIST_INTEGRITY( pxList );
125 listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
126
127 /*将新的列表项插入到列表,根据xItemValue的值升序插入列表*/
135 if( xValueOfInsertion == portMAX_DELAY )
136 { //若值等于最大值,将其之间插入到末尾
137 pxIterator = pxList->xListEnd.pxPrevious;
138 }
139 else
140 { //若值不等于最大值,寻找插入位置
163 for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*将待插入列表项的值依次(按从前往后的顺序)与已插入的列表项的值作比较,当比较时待插入列表项的值较小时,插入位置确定 */
164 {
165 /*空 */
167 }
168 }
169
170 pxNewListItem->pxNext = pxIterator->pxNext;
171 pxNewListItem->pxNext->pxPrevious = pxNewListItem;
172 pxNewListItem->pxPrevious = pxIterator;
173 pxIterator->pxNext = pxNewListItem;
174
175 /*记录列表项所属列表*/
177 pxNewListItem->pxContainer = pxList;
178
179 ( pxList->uxNumberOfItems )++;
180 }
11.jpg
for循环结束时pxIterator指向职位50的列表项,此时执行170-173行代码,确定值为60的列表项在列表中的顺序。
四:列表项遍历
279 #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
280 {
281 List_t * const pxConstList = ( pxList ); // pxList 表示要遍历的列表
282
284 ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; //将pxIndex指向下一个列表项
285 if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )
286 { //因为xListEnd不是列表项,若pxIndex指向xListEnd,则将其重新指向处于列表头的列表项
287 ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;
288 }
289 ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;
290 }
此函数用于从多个同优先级的就绪任务中查找下一个要运行的任务。
五:列表项末尾插入
85 void vListInsertEnd( List_t * const pxList,
86 ListItem_t * const pxNewListItem )
87 {
88 ListItem_t * const pxIndex = pxList->pxIndex;
89
90 /*完成对列表和列表项的完整性检查*/
93 listTEST_LIST_INTEGRITY( pxList );
94 listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
95
96 /* 这里所谓的末尾要根据列表的成员变量pxIndex 来确定的! 前面说了列表中的 pxIndex 成员变量是用来遍历列表的, pxIndex 所指向的列表项就是要遍历的开始列表项,也就是说 pxIndex 所指向的列表项就代表列表头! 由于是个环形列表,所以新的列表项就应该插入到 pxIndex 所指向的列表项的前面。 */
99 pxNewListItem->pxNext = pxIndex;
100 pxNewListItem->pxPrevious = pxIndex->pxPrevious;
101
102 /* Only used during decision coverage testing. */
103 mtCOVERAGE_TEST_DELAY();
104
105 pxIndex->pxPrevious->pxNext = pxNewListItem;
106 pxIndex->pxPrevious = pxNewListItem;
107
108 /* Remember which list the item is in. */
109 pxNewListItem->pxContainer = pxList;
110
111 ( pxList->uxNumberOfItems )++;
112 }
插入到 pxIndex 所指向的列表项的前面
六:列表项删除
183 UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
184 {
185 /* The list item knows which list it is in. Obtain the list from the list
186 * item. */
187 List_t * const pxList = pxItemToRemove->pxContainer;
188
189 pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
190 pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
191
192 /* Only used during decision coverage testing. */
193 mtCOVERAGE_TEST_DELAY();
194
195 /* Make sure the index is left pointing to a valid item. */
196 if( pxList->pxIndex == pxItemToRemove )
197 {
198 pxList->pxIndex = pxItemToRemove->pxPrevious;
199 }
200 else
201 {
202 mtCOVERAGE_TEST_MARKER();
203 }
204
205 pxItemToRemove->pxContainer = NULL;
206 ( pxList->uxNumberOfItems )--;
207
208 return pxList->uxNumberOfItems;
209 }