FreeRTOS源代码分析 - List部分
list为链表,在FreeRTOS中被广泛的使用,其中包括:list.c主文件和list.h头文件
在list.h头文件中定义的内容如下:
/*
-
定义的宏
*/
List.h中首先可以设置configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES进行相应的列表完整性检查:
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES解释:
a. 宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE用于检查列表项数据是否完整,在projdefs.h中进行修改定义,如果将宏configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES设置为1,则使能列表项数据完整性检查,则宏listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE和listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE会被两个已知的数值代替
b.如果打开了完整性检查的开关(configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES),每个链表和链表项结构都会定义listFIRST_LIST_INTEGRITY_CHECK_VALUE和listSECOND_LIST_INTEGRITY_CHECK_VALUE(mini链表项没有定义这个),该定义是一个16位或32位的整形数,在链表或链表项初始化的时候会将该变量初始化为0x5a5a或0x5a5a5a5a(32bit情况下,在projdef中定义),在检查的时候如果这两个变量都没有改变则通过完整性检查,否则认为链表被破坏
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
/* Define the macros to do nothing. */
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
#define listTEST_LIST_INTEGRITY( pxList )
#else
/* Define macros that add new members into the list structures. */
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
/* Define macros that set the new structure members to known values. */
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
/* Define macros that will assert if one of the structure members does not
contain its expected value. */
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
/*
-
结构体的定义
*/
/*
* Definition of the only type of object that a list can contain.
*/
struct xLIST;
struct xLIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*如果List_DATA_INTEGRITY_CHECK_BYTES值设置为1,则设置为一个已知的值. */
configLIST_VOLATILE TickType_t xItemValue; /*排列值,在大部分的情况下用来将序列按一个降序进行排列 */
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*指针指向链表中的下一个List_Item链表节点 */
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*指针指向链表中的上一个List_Item链表节点*/
void * pvOwner; /*指向TCB的指针 */
struct xLIST * configLIST_VOLATILE pxContainer; /*指针指向包含这个链表节点的链表 */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*如果List_DATA_INTEGRITY_CHECK_BYTES值设置为1,则设置为一个已知的值. */
};
typedef struct xLIST_ITEM ListItem_t;
struct xMINI_LIST_ITEM
{
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*如果List_DATA_INTEGRITY_CHECK_BYTES值设置为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;
/*
* Definition of the type of queue used by the scheduler.
*/
typedef struct xLIST
{
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*如果List_DATA_INTEGRITY_CHECK_BYTES值设置为1,则设置为一个已知的值. */
volatile UBaseType_t uxNumberOfItems;
ListItem_t * configLIST_VOLATILE pxIndex; /*用于遍寻整个链表,指向 listGET_OWNER_OF_NEXT_ENTRY ()得到的最后一个链表节点*/
MiniListItem_t xListEnd; /*由于链表节点包含可能的最大值意味着此链表节点永远在链表的最后,因此也被用于作为一个标志值*/
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*如果List_DATA_INTEGRITY_CHECK_BYTES值设置为1,则设置为一个已知的值 */
} List_t;
/*
-
节点带参宏小函数
*/
/*
* 用来设置链表节点拥有者的访问宏,链表节点拥有者通常是一个包含此链表节点的一个TCB
*/
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
/*
* 用来获得链表节点拥有者的访问宏,链表节点拥有者通常是一个包含此链表节点的一个TCB
*/
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
/*
用来设置链表节点ITEMVALUE的宏,在大部分情况下,这个值是用来进行列排序的降排序
*/
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
/*
用来获取LISTITEM的值,这个值可以表示很多值,例如,任务的优先度,或任务被解决阻塞的时间点
*/
#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 ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
/*
获取链表的节点数
*/
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
/*
获取链表第一个节点的OWNER,即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; \
} \
/* 获取节点的OWNER,即TCB */
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}
/*
*访问功能可获取列表中第一个条目的所有者。 清单通常按项目值升序排序。
*
*此函数返回列表中第一项的pxOwner成员。
*列表项的pxOwner参数是指向拥有的对象的指针列表项。 在调度程序中,这通常是任务控制块。
*/
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
/*
*检查列表项是否在列表中。 列表项保持一个指向其所在列表的“容器”指针。
* @param pxList我们想知道列表项是否在列表中。
* @param pxListItem我们想知道列表项是否在列表中。
* @return pdTRUE(如果列表项在列表中),否则为pdFALSE。
*/
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) )
/*
*返回列表,返回包含列表项的链表(从中引用)。
* @param pxListItem正在查询的列表项。
* @return指向引用pxListItem的List_t对象的指针
*/
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer )
/*
此处提供了一种粗略的方法来知道列表是否已初始化,例如
pxList-> xListEnd.xItemValue通过vListInitialise()设置为portMAX_DELAY功能。
*/
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
/*
-
函数声明部分
*/
```c
/*
*必须在使用列表之前调用用来初始化所有成员列表结构,并将xListEnd项作为列表插入标记在列表的后面。
* @param pxList指向正在初始化的列表的指针。
*/
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
/*
*必须在使用列表项之前调用。 这也会将列表容器设置为null,因为该项目不认为它已经包含在列表中。
* @param pxItem指向正在初始化的列表项的指针。
*/
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
/ *
*将列表项插入到目标列表中,该列表项插入到列表中的位置由其列表值(链表Itemvalue值降序)确定的位置。
* @param pxList目标列表。
* @param pxNewListItem要放置在列表中的项目。
* /
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/ *
*将列表项插入到列表。 该列表项将插入到一个位置这样它将成为由多个返回的列表中的最后一项
*调用listGET_OWNER_OF_NEXT_ENTRY。
*
*列表成员pxIndex用于遍历列表。 用listGET_OWNER_OF_NEXT_ENTRY将pxIndex递增到列表中的下一项。
*使用vListInsertEnd将项目放置在列表中可以有效地放置项目
*在pxIndex指向的列表位置。 这意味着彼此列表中的项目将由listGET_OWNER_OF_NEXT_ENTRY返回,之前
* pxIndex参数再次指向要插入的项目。
* @param pxList要将项目插入其中的列表。
* @param pxNewListItem要插入到列表中的列表项。
* /
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
/*
从列表中删除一个列表项。 该列表项有指向该列表的指针。因此仅列表项需要传递到函数中。
*/
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;