1.链表节点
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE TickType_t xItemValue; /*< 辅助值,用于帮助节点做顺序排列. */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< 指向链表下一个节点. */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< 指向链表前一个节点. */
void * pvOwner; /*< 指向拥有该节点的内核对象,通常是 TCB. */
void * configLIST_VOLATILE pvContainer; /*<指向该节点所在的链表 */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t; /*节点重命名 */
// 最小节点
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
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.链表
/*
* Definition of the type of queue used by the scheduler.
*/
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
configLIST_VOLATILE UBaseType_t uxNumberOfItems; /* 链表节点计数器 */
ListItem_t * configLIST_VOLATILE pxIndex; /*< 链表节点索引指针 指向调用listGET_OWNER_OF_NEXT_ENTRY()返回的最后一个项目。 */
MiniListItem_t xListEnd; /*< 链表最后一个节点 */
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
} List_t;
3.链表初始化
void vListInitialise( List_t * const pxList )
{
/* The list structure contains a list item which is used to mark the
end of the list. To initialise the list the list end is inserted
as the only list entry. */
/* 将链表索引指针指向最后一个节点 */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
/* The list end value is the highest possible value in the list to
ensure it remains at the end of the list. */
/* 将链表最后一个节点的辅助排序的值设置为最大 */
pxList->xListEnd.xItemValue = portMAX_DELAY;
/* The list end next and previous pointers point to itself so we know
when the list is empty. */
/* 将最后一个节点的 pxNext 和 pxPrevious 指针均指向节点自身,表示链表为空 */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
/* 计数器的值为 0,表示链表为空 */
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* Write known values into the list if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}
4.链表节点初始化
void vListInitialiseItem( ListItem_t * const pxItem )
{
/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表. */
pxItem->pvContainer = NULL;
/* Write known values into the list item if
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
}
5. 将节点插入到链表尾部
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t * const pxIndex = pxList->pxIndex;
/* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert a new list item into pxList, but rather than sort the list,
makes the new list item the last item to be removed by a call to
listGET_OWNER_OF_NEXT_ENTRY(). */
/*在pxList中插入一个新的列表项,插入在pxInde的前一个位置*/
pxNewListItem->pxNext = pxIndex;
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
pxIndex->pxPrevious->pxNext = pxNewListItem;
pxIndex->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */
/* 记住该节点所在的链表 */
pxNewListItem->pvContainer = ( void * ) pxList;
/* 链表节点计数器++ */
( pxList->uxNumberOfItems )++;
}
6. 节点按照升序插入到链表
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
ListItem_t *pxIterator;
/* 获取节点的排序辅助值 */
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
/* Only effective when configASSERT() is also defined, these tests may catch
the list data structures being overwritten in memory. They will not catch
data errors caused by incorrect configuration or use of FreeRTOS. */
listTEST_LIST_INTEGRITY( pxList );
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
/* Insert the new list item into the list, sorted in xItemValue order.*/
/* 将新的列表项插入列表,按xItemValue顺序排序 */
if( xValueOfInsertion == portMAX_DELAY ) //判断辅助值
{
pxIterator = pxList->xListEnd.pxPrevious;
}
else
{
/* 按照升序,找到要插入的位置 */
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
{
/* There is nothing to do here, just iterating to the wanted
insertion position. */
}
}
/* 插入节点 */
pxNewListItem->pxNext = pxIterator->pxNext;
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
pxNewListItem->pxPrevious = pxIterator;
pxIterator->pxNext = pxNewListItem;
/* Remember which list the item is in. This allows fast removal of the
item later. */
/* 记住该节点所在的链表 */
pxNewListItem->pvContainer = ( void * ) pxList;
/* 链表节点计数器++ */
( pxList->uxNumberOfItems )++;
}
7.将节点从链表中删除
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
/* The list item knows which list it is in. Obtain the list from the list
item. */
/*链表节点知道它在哪个链表中。从链表中获取链表节点*/
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
/* Only used during decision coverage testing. */
mtCOVERAGE_TEST_DELAY();
/* Make sure the index is left pointing to a valid item. */
/* 调整链表的节点索引指针 */
if( pxList->pxIndex == pxItemToRemove ) //如果指针索引指向的是要删除的节点
{
pxList->pxIndex = pxItemToRemove->pxPrevious; //让指针索引指向前一个节点
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* 初始化该节点所在的链表为空,表示节点还没有插入任何链表 */
pxItemToRemove->pvContainer = NULL;
( pxList->uxNumberOfItems )--; /* 链表节点计数器-- */
return pxList->uxNumberOfItems; /* 返回链表中剩余节点的个数 */
}