内核中有很多双向列表,这些列表可以挂接很多列表项,每条列表都有一个确定的尾节点、列表当前指针、列表项个数
/* 列表结构体 */
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE
configLIST_VOLATILE UBaseType_t uxNumberOfItems; /* 列表项个数 */
ListItem_t *configLIST_VOLATILE pxIndex; /* 当前列表项指针 */
MiniListItem_t xListEnd; /* 列表的尾节点 */
listSECOND_LIST_INTEGRITY_CHECK_VALUE
}List_t;
列表尾节点中的有效信息包括:列表项的值、next指针、previous指针
/* 迷你列表项结构体 */
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
configLIST_VOLATILE TickType_t xItemValue; /* 列表项的值 */
struct xLIST_ITEM *configLIST_VOLATILE pxNext; /* next指针指向后一个列表项 */
struct xLIST_ITEM *configLIST_VOLATILE pxPrevious; /* previous指针指向前一个列表项 */
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;
列表项的内容包括:列表项的值、next指针、previous指针、所属TCB指针、正在挂接的列表指针
/* 列表项结构体 */
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
configLIST_VOLATILE TickType_t xItemValue; /* 列表项的值 */
struct xLIST_ITEM *configLIST_VOLATILE pxNext; /* next指针指向后一个列表项 */
struct xLIST_ITEM *configLIST_VOLATILE pxPrevious; /* previous指针指向前一个列表项 */
void *pvOwner; /* 该指针指向所属TCB */
void *configLIST_VOLATILE pvContainer; /* 指向包含该列表项的列表 */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;
列表会挂接很多列表项,如图所示:
列表初始化时不包含任何列表项
/* 功能:初始化列表
pxList:列表指针 */
void vListInitialise(List_t *const pxList)
{
/* 列表初始化时只有尾节点,因此将当前指针指向尾节点 */
pxList->pxIndex = (ListItem_t *)&(pxList->xListEnd);
/* 尾节点的值初始化为0xffffffff */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* 列表初始化时只有尾节点,且列表是双向环形链表 */
pxList->xListEnd.pxNext = (ListItem_t *)&(pxList->xListEnd);
pxList->xListEnd.pxPrevious = (ListItem_t *)&(pxList->xListEnd);
/* 列表项的个数初始化为0 */
pxList->uxNumberOfItems = (UBaseType_t)0U;
listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList);
listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList);
}
初始化完成后,如图所示:
列表项初始化时不属于任何列表
/* 功能:初始化列表项
pxItem:列表项指针 */
void vListInitialiseItem(ListItem_t *const pxItem)
{
/* 将列表项所属列表指针初始化为不指向任何列表 */
pxItem->pvContainer = NULL;
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem);
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem);
}
列表初始化后,如图所示:
列表项插入列表的方式有两种,一种是直接插入当前指针指向的位置,另一种是按照列表项值从小到大插入
/* 功能:将列表项插入列表
pxList:列表指针
pxNewListItem:列表项指针 */
void vListInsertEnd(List_t *const pxList, ListItem_t *const pxNewListItem)
{
/* 当前列表项指针 */
ListItem_t *const pxIndex = pxList->pxIndex;
listTEST_LIST_INTEGRITY(pxList);
listTEST_LIST_ITEM_INTEGRITY(pxNewListItem);
/* 将列表项插入列表 */
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* 将列表项所属列表指针指向列表 */
pxNewListItem->pvContainer = (void *)pxList;
/* 列表中列表项个数加一 */
(pxList->uxNumberOfItems)++;
}
/* 功能:将列表项按列表值从小到大插入列表中
pxList:列表指针
pxNewListItem:列表项指针 */
void vListInsert(List_t *const pxList, ListItem_t *const pxNewListItem)
{
ListItem_t *pxIterator;
/* 列表项值 */
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
listTEST_LIST_INTEGRITY(pxList);
listTEST_LIST_ITEM_INTEGRITY(pxNewListItem);
/* 如果列表项值最大,则直接插入列表尾部 */
if(xValueOfInsertion == portMAX_DELAY)
{
pxIterator = pxList->xListEnd.pxPrevious;
}
/* 按列表项值从小到大查找 */
else
{
for(pxIterator = (ListItem_t *)&(pxList->xListEnd); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext)
{
}
}
/* 将列表项插入列表 */
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
/* 将列表项所属列表指针指向列表 */
pxNewListItem->pvContainer = (void *)pxList;
/* 列表中列表项个数加一 */
(pxList->uxNumberOfItems)++;
}
从列表中移除列表项
/* 功能:将列表项从当前所在的列表中移除
pxItemToRemove:列表项
返回值:移除该列表项后所在列表中列表项的个数 */
UBaseType_t uxListRemove(ListItem_t *const pxItemToRemove)
{
/* 列表项所在列表指针 */
List_t *const pxList = (List_t *)pxItemToRemove->pvContainer;
/* 将列表项从列表中移除 */
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
mtCOVERAGE_TEST_DELAY();
/* 列表当前指针指向该列表项,则将列表当前指针改为指向前一个列表项 */
if(pxList->pxIndex == pxItemToRemove)
{
pxList->pxIndex = pxItemToRemove->pxPrevious;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* 该列表项不属于任何列表 */
pxItemToRemove->pvContainer = NULL;
/* 列表中列表项个数减一 */
(pxList->uxNumberOfItems)--;
/* 返回列表项个数 */
return pxList->uxNumberOfItems;
}
列表还提供了一些其他的接口
/* 设置列表项所属TCB */
#define listSET_LIST_ITEM_OWNER(pxListItem, pxOwner) ((pxListItem)->pvOwner = (void *)(pxOwner))
/* 获取列表项所属TCB */
#define listGET_LIST_ITEM_OWNER(pxListItem) ((pxListItem)->pvOwner)
/* 设置列表项值 */
#define listSET_LIST_ITEM_VALUE(pxListItem, xValue) ((pxListItem)->xItemValue = (xValue))
/* 获取列表项值 */
#define listGET_LIST_ITEM_VALUE(pxListItem) ((pxListItem)->xItemValue)
/* 获取列表头部列表项的值 */
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxList) (((pxList)->xListEnd).pxNext->xItemValue)
/* 获取列表头部列表项 */
#define listGET_HEAD_ENTRY(pxList) (((pxList)->xListEnd).pxNext)
/* 获取下一个列表项 */
#define listGET_NEXT(pxListItem) ((pxListItem)->pxNext)
/* 获取列表尾节点 */
#define listGET_END_MARKER(pxList) ((ListItem_t const *)(&((pxList)->xListEnd)))
/* 判断列表是否为空 */
#define listLIST_IS_EMPTY(pxList) ((BaseType_t)((pxList)->uxNumberOfItems == (UBaseType_t)0))
/* 获取列表中当前列表项的个数 */
#define listCURRENT_LIST_LENGTH(pxList) ((pxList)->uxNumberOfItems)
/* 将当前列表项指针指向下一个列表项,返回所属TCB */
#define listGET_OWNER_OF_NEXT_ENTRY(pxTCB, pxList) \
{ \
List_t *const pxConstList = (pxList); \
(pxConstList)->pxIndex = (pxConstList)->pxIndex->pxNext; \
if((void *)(pxConstList)->pxIndex == (void *)&((pxConstList)->xListEnd)) \
{ \
(pxConstList)->pxIndex = (pxConstList)->pxIndex->pxNext; \
} \
(pxTCB) = (pxConstList)->pxIndex->pvOwner; \
}
/* 获取列表首节点所属TCB */
#define listGET_OWNER_OF_HEAD_ENTRY(pxList) ((&((pxList)->xListEnd))->pxNext->pvOwner)
/* 判断列表项是否属于指定列表 */
#define listIS_CONTAINED_WITHIN(pxList, pxListItem) ((BaseType_t)((pxListItem)->pvContainer == (void *)(pxList)))
/* 获取列表项所在列表 */
#define listLIST_ITEM_CONTAINER(pxListItem) ((pxListItem)->pvContainer)
/* 判断列表是否已经初始化(尾节点列表项值为最大可能值0xffffffff) */
#define listLIST_IS_INITIALISED(pxList) ((pxList)->xListEnd.xItemValue == portMAX_DELAY)