列表及列表项实现原理
![](https://img-blog.csdnimg.cn/direct/280f5ffed3e94c88a4fbab7f238f1736.png)
![](https://img-blog.csdnimg.cn/direct/619f699de8e246ad81e7173610e8c4dd.png)
![](https://img-blog.csdnimg.cn/direct/c817b3c5fb6446419647f0e9cac28722.png)
列表及列表项插入
![](https://img-blog.csdnimg.cn/direct/458411d997d24dbd9fd75dd123caec7c.png)
![](https://img-blog.csdnimg.cn/direct/0170a05303a349fd93c0f00566227cc4.png)
列表及列表项删除
![](https://img-blog.csdnimg.cn/direct/929d914b4fdd4e848869931c7a35ee25.png)
![](https://img-blog.csdnimg.cn/direct/b8afc9780aa4488e9c2dacd2595fff8b.png)
idleTask
void vTaskStartScheduler( void )
xReturn = xTaskCreate( prvIdleTask,
"IDLE", configMINIMAL_STACK_SIZE,
( void * ) NULL,
( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
}
/*任务删除自身*/
static void prvCheckTasksWaitingTermination( void )
{
/** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
#if ( INCLUDE_vTaskDelete == 1 )
{
BaseType_t xListIsEmpty;
/*
遍历将要删除的任务
uxDeletedTasksWaitingCleanUp 在vTaskDelete进行加1处理
*/
while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
{
//挂起了调度器
vTaskSuspendAll();
{
//读取删除任务自身列表里任务状态是否为空
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
}
//开启调度器
( void ) xTaskResumeAll();
if( xListIsEmpty == pdFALSE )
{
//删除任务
TCB_t *pxTCB;
//进入临界段
taskENTER_CRITICAL();
{
/*
1、获取任务控制块
2、从任务列表项移除任务
3、任务总计数减一
4、等待删除计数减一
*/
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
--uxCurrentNumberOfTasks;
--uxDeletedTasksWaitingCleanUp;
}
//退出临界段
taskEXIT_CRITICAL();
//释放了任务控制块
prvDeleteTCB( pxTCB );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
#endif /* INCLUDE_vTaskDelete */
}
/*
获取最小系统时间片
*/
static TickType_t prvGetExpectedIdleTime( void )
{
TickType_t xReturn;
UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
/* */
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
{
//就绪态的任务优先级高于空闲
if( uxTopReadyPriority > tskIDLE_PRIORITY )
{
uxHigherPriorityReadyTasks = pdTRUE;
}
}
#else
{
const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
/* 就绪态的任务优先级高于空闲 */
if( uxTopReadyPriority > uxLeastSignificantBit )
{
uxHigherPriorityReadyTasks = pdTRUE;
}
}
#endif
//当前任务优先级高于空闲任务
if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
{
xReturn = 0;
}
//与空闲任务优先级相同的其他任务处于就绪态
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
{
xReturn = 0;
}
//高优先级任务处于就绪态
else if( uxHigherPriorityReadyTasks != pdFALSE )
{
/* There are tasks in the Ready state that have a priority above the
idle priority. This path can only be reached if
configUSE_PREEMPTION is 0. */
xReturn = 0;
}
else
{
//系统解锁时间-系统tick计数值== 就是当前系统的最小时间片
xReturn = xNextTaskUnblockTime - xTickCount;
}
return xReturn;
}
/*
空闲任务
*/
static portTASK_FUNCTION( prvIdleTask, pvParameters )
{
/* Stop warnings. */
( void ) pvParameters;
/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
SCHEDULER IS STARTED. **/
for( ;; )
{
/*检查任务删除自身处理 */
prvCheckTasksWaitingTermination();
/*判断调度器工作模式是否开启了优先级抢占模式*/
#if ( configUSE_PREEMPTION == 0 )
{
/*
1、触发了上下文切换
2、让调度器判断是否有其他任务,处于了就绪态,然后进行调度
*/
taskYIELD();
}
#endif /* configUSE_PREEMPTION */
//调度器使能抢占式
#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
{
/*
1、和空闲任务处于同一优先级的任务,处于就绪态
2、进行上下文切换
3、高于空闲任务优先级的任务,有调度器进行处理
*/
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
{
taskYIELD();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
/*
钩子函数,主要让用户自己填充代码
*/
#if ( configUSE_IDLE_HOOK == 1 )
{
extern void vApplicationIdleHook( void );
/* 用户自己实现,比如检测外部信息 */
vApplicationIdleHook();
}
#endif /* configUSE_IDLE_HOOK */
/* 低功耗处理功能 */
#if ( configUSE_TICKLESS_IDLE != 0 )
{
TickType_t xExpectedIdleTime;
/* 获取系统的最小时间片 */
xExpectedIdleTime = prvGetExpectedIdleTime();
//判断是否大于休眠空闲处理的最小间隔=2tick
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
//挂起调度器
vTaskSuspendAll();
{
/* 又一次获取获取系统的最小时间片*/
xExpectedIdleTime = prvGetExpectedIdleTime();
//再次判断
if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
//进入了休眠处理,传入系统的最小时间片
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
//恢复调度器
( void ) xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_TICKLESS_IDLE */
}
}
TaskList
//添加任务到就绪列表
/*
1、任务创建时的状态为就绪态
2、需要让任务能够调度
3、把任务所关联的列表项,按照尾部插入的方式,插入到当前有限级下的列表当中
*/
#define prvAddTaskToReadyList( pxTCB )
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ \
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
/*
这个是在添加任务到就绪列表中使用
主要实现:
判断当前添加任务的优先级是否为系统的最大值
是则更新一个全局优先级变量值,之后用于调度使用
*/
#define taskRECORD_READY_PRIORITY( uxPriority ) \
{ \
if( ( uxPriority ) > uxTopReadyPriority ) \
{ \
uxTopReadyPriority = ( uxPriority ); \
} \
} /* taskRECORD_READY_PRIORITY */
//选择优先级高的任务进行赋值调度
/*
1、获取当前处于就绪态比较高的优先级数
2、进行遍历,判断当前优先级下是否有处于就绪态的任务
3、之后进行减减遍历,因为优先级数越高,优先级越大
4、这个时候,我们找到是肯定是优先级最高的任务
5、获取当前优先级列表中的最新的列表项的所有者,其实就是任务控制块
6、之后更新任务控制,给内核进行调度
*/
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
UBaseType_t uxTopPriority = uxTopReadyPriority; \
\
/* Find the highest priority queue that contains ready tasks. */ \
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
{ \
configASSERT( uxTopPriority ); \
--uxTopPriority; \
} \
\ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
uxTopReadyPriority = uxTopPriority; \
} /* taskSELECT_HIGHEST_PRIORITY_TASK */