freeRTOS源码解析2--链表管理

源码目录:\FreeRTOS\list.c、\FreeRTOS\list.h

代码比较简单就不举具体的例子了,直接分析源码。

数据结构:

1、链表项

struct xLIST_ITEM
{
configLIST_VOLATILE TickType_t xItemValue;                   /* 项值,链表中升序排序 */
struct xLIST_ITEM * configLIST_VOLATILE pxNext;          /* 下一个链表项 */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;    /* 上一个链表项 */
void * pvOwner;                                                            /* 指向该项的持有者(通常为TCB)。 因此在包含链表项的链表和链表项本身之间存在双向链接。 */
struct xLIST * configLIST_VOLATILE pxContainer;            /* 指向该链表项所在链表(如果有的话)。 */
};
typedef struct xLIST_ITEM ListItem_t;

struct xMINI_LIST_ITEM
{
configLIST_VOLATILE TickType_t xItemValue;
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

 

 

2、链表

typedef struct xLIST
{
volatile UBaseType_t uxNumberOfItems;
ListItem_t * configLIST_VOLATILE pxIndex;    /* 用于遍历链表。指向listGET_OWNER_OF_NEXT_ENTRY()返回的最后一项。 */
MiniListItem_t xListEnd;                                   /* 包含最大可能项值的列表项,这意味着它总是在列表的末尾,因此可用作标记。 */
} List_t;

 

 

初始化链表

void vListInitialise( List_t * const pxList ):

 1 void vListInitialise( List_t * const pxList )
 2 {
 3     /* The list structure contains a list item which is used to mark the
 4      * end of the list.  To initialise the list the list end is inserted
 5      * as the only list entry. */
 6     /* 链表结构包含一个用于标记尾部的链表项。为了初始化链表,
 7      * 将xListEnd作为唯一的链表项插入。 */
 8     pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
 9 
10     /* The list end value is the highest possible value in the list to
11      * ensure it remains at the end of the list. */
12     /* xListEnd的项值应为链表中所有项的最大值,以确保它始终处于尾部。 */
13     pxList->xListEnd.xItemValue = portMAX_DELAY;
14 
15     /* The list end next and previous pointers point to itself so we know
16      * when the list is empty. */
17     /* xListEnd的下一个和上一个均指向自己,那么就可知该链表为空。 */
18     pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
19     pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
20 
21     pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
22 }
vListInitialise

 

 

初始化链表项

void vListInitialiseItem( ListItem_t * const pxItem ):

1 void vListInitialiseItem( ListItem_t * const pxItem )
2 {
3     /* Make sure the list item is not recorded as being on a list. */
4     /* 确保链表项没有被记录为在链表中。 */
5     pxItem->pxContainer = NULL;
6 }
vListInitialiseItem

 

将pxNewListItem链表项插入pxList链表尾部

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ):

 1 void vListInsertEnd( List_t * const pxList,
 2                      ListItem_t * const pxNewListItem )
 3 {
 4     ListItem_t * const pxIndex = pxList->pxIndex;
 5 
 6     /* Insert a new list item into pxList, but rather than sort the list,
 7      * makes the new list item the last item to be removed by a call to
 8      * listGET_OWNER_OF_NEXT_ENTRY(). */
 9     /* 向pxList中插入一个新的链表项,但不是对链表进行排序,
10      * 而是通过调用listGET_OWNER_OF_NEXT_ENTRY()将新链表项作为最后一个要删除的项。 */
11     pxNewListItem->pxNext = pxIndex;
12     pxNewListItem->pxPrevious = pxIndex->pxPrevious;
13 
14     pxIndex->pxPrevious->pxNext = pxNewListItem;
15     pxIndex->pxPrevious = pxNewListItem;
16 
17     /* Remember which list the item is in. */
18     /* 记录链表项所在链表*/
19     pxNewListItem->pxContainer = pxList;
20 
21     ( pxList->uxNumberOfItems )++;
22 }
vListInsertEnd

 

 

 

 

按pxNewListItem链表项的元素大小,从小到大插入到链表pxList适当位置

void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ):

 1 void vListInsert( List_t * const pxList,
 2                   ListItem_t * const pxNewListItem )
 3 {
 4     ListItem_t * pxIterator;
 5     const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
 6 
 7     /* Insert the new list item into the list, sorted in xItemValue order.
 8      *
 9      * If the list already contains a list item with the same item value then the
10      * new list item should be placed after it.  This ensures that TCBs which are
11      * stored in ready lists (all of which have the same xItemValue value) get a
12      * share of the CPU.  However, if the xItemValue is the same as the back marker
13      * the iteration loop below will not end.  Therefore the value is checked
14      * first, and the algorithm slightly modified if necessary. */
15     /* 将新的链表项插入到链表中,按xItemValue大小排序。 
16      * 如果链表中已经包含了具有相同项值的链表项,那么新的链表项应该放在它的后面。
17      * 这确保存储在就绪链表中的TCB(它们都具有相同的xItemValue值)都能获得CPU的份额。
18      * 但是,如果xItemValue与List中的xListEnd的值相同,则下面的迭代循环将不会结束。
19      * 因此,首先检查该值,然后在必要时稍微修改算法。 */
20     if( xValueOfInsertion == portMAX_DELAY )
21     {
22         pxIterator = pxList->xListEnd.pxPrevious;
23     }
24     else
25     {
26         for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM.  This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
27         {
28             /* There is nothing to do here, just iterating to the wanted
29              * insertion position. */
30             /* 什么都不做,只遍历到所需的位置。 */
31         }
32     }
33 
34     pxNewListItem->pxNext = pxIterator->pxNext;
35     pxNewListItem->pxNext->pxPrevious = pxNewListItem;
36     pxNewListItem->pxPrevious = pxIterator;
37     pxIterator->pxNext = pxNewListItem;
38 
39     /* Remember which list the item is in.  This allows fast removal of the
40      * item later. */
41     /* 记录链表项所在链表。这样能快速得将项移出链表。 */
42     pxNewListItem->pxContainer = pxList;
43 
44     ( pxList->uxNumberOfItems )++;
45 }
vListInsert

当插入的链表项的值等于portMAX_DELAY(0xFFFFFFFF)或者是该链表的所有项中的最大值,则其效果与vListInsertEnd相同。

 

 

 

 

将pxItemToRemove链表项移出链表

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ):

 1 UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
 2 {
 3     /* The list item knows which list it is in.  Obtain the list from the list
 4      * item. */
 5     /* 链表项知道它在哪个链表中。从链表项中获取链表。 */
 6     List_t * const pxList = pxItemToRemove->pxContainer;
 7 
 8     pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
 9     pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
10 
11     /* Make sure the index is left pointing to a valid item. */
12     /* 确保索引指向一个有效的项。 */
13     if( pxList->pxIndex == pxItemToRemove )
14     {
15         pxList->pxIndex = pxItemToRemove->pxPrevious;
16     }
17     else
18     {
19         mtCOVERAGE_TEST_MARKER();
20     }
21 
22     pxItemToRemove->pxContainer = NULL;
23     ( pxList->uxNumberOfItems )--;
24 
25     return pxList->uxNumberOfItems;
26 }
uxListRemove

移出很简单,就是普通的链表操作,就不画出示意图了。

 

 

freeRTOS的链表操作就解析完成了,下次开始解析任务切换、上下文切换、保存现场相关的代码。

posted @ 2022-09-29 15:16  freeManX1807  阅读(315)  评论(0编辑  收藏  举报