仅为个人理解,个人笔记
两个函数
xTaskPriorityInherit和xTaskPriorityDisinherit
xTaskPriorityInherit:
例:若任务A的优先级大于任务B(假设任务A优先级为2,任务B优先级为1),但是同一互斥量被任务B先获取,在任务B获取该互斥量后运行的过程中任务A恢复运行抢占任务B,且任务A尝试获取该互斥量并且设置了最长等待时间,在任务A因获取不到该互斥量而进入阻塞之前会先判断任务B是否应该继承任务A的优先级
BaseType_t xTaskPriorityInherit(TaskHandle_t const pxMutexHolder)
{
// pxMutexHolderTCB为已经获取到该互斥量的任务TCB,在例中为任务B
TCB_t *const pxMutexHolderTCB = (TCB_t *)pxMutexHolder;
// 该函数的返回值,若任务B继承了任务A的优先级或者任务B已经继承了其他任务的优先级(特殊情况),返回pdTRUE,否则返回pdFALSE
BaseType_t xReturn = pdFALSE;
// 在该互斥量已经被获取的情况下,pxMutexHolder指向任务B的TCB
if (pxMutexHolder != NULL)
{
// 当已经获取该互斥量的任务的优先级小于当前尝试获取该互斥量的任务的优先级时,发生优先级继承.在例中为任务B的优先级小于任务A的优先级
if (pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority)
{
// 这一步没看懂
if ((listGET_LIST_ITEM_VALUE(&(pxMutexHolderTCB->xEventListItem)) & taskEVENT_LIST_ITEM_VALUE_IN_USE) == 0UL)
{
// 将要继承优先级的任务TCB的事件列表项的value设置好
listSET_LIST_ITEM_VALUE(&(pxMutexHolderTCB->xEventListItem), (TickType_t)configMAX_PRIORITIES - (TickType_t)pxCurrentTCB->uxPriority); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
// 若已经获取该互斥量的任务是被尝试获取该互斥量的任务抢占运行,在例中任务B还在就绪列表中
if (listIS_CONTAINED_WITHIN(&(pxReadyTasksLists[pxMutexHolderTCB->uxPriority]), &(pxMutexHolderTCB->xStateListItem)) != pdFALSE)
{
// 将已经获取该互斥量的任务TCB的状态列表项从旧优先级的就绪列表上卸载,在例中将任务B的TCB的状态列表项从优先级为1的就绪列表上卸载
if (uxListRemove(&(pxMutexHolderTCB->xStateListItem)) == (UBaseType_t)0)
{
// 使用优化的硬件调度方法,在例中不使用该方法,该宏为空
taskRESET_READY_PRIORITY(pxMutexHolderTCB->uxPriority);
}
// 不适用优化的硬件调度方法
else
{
mtCOVERAGE_TEST_MARKER();
}
// 将任务B的优先级设置为任务A的优先级,并且将任务B的TCB的状态列表项挂载到相应优先级的就绪列表上
pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
prvAddTaskToReadyList(pxMutexHolderTCB);
}
// 如果已经获取该互斥量的任务不是被尝试获取该互斥量的任务抢占运行,在该例中不为这样的情况
else
{
pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
}
// 调试信息
traceTASK_PRIORITY_INHERIT(pxMutexHolderTCB, pxCurrentTCB->uxPriority);
// 任务B已经继承了任务A的优先级,记录函数的返回值
xReturn = pdTRUE;
}
else
{
// 任务B已经继承了其他任务的优先级,即任务B现在的优先级大于任务A,在例中不为这样的情况,不讨论
if (pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority)
{
xReturn = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
return xReturn;
}
xTaskPriorityDisinherit:
在已获取互斥量的任务释放互斥量时会用到,该函数主要判断释放互斥量的任务是否继承了优先级以及是否取消优先级继承
BaseType_t xTaskPriorityDisinherit(TaskHandle_t const pxMutexHolder)
{
// pxTCB指向获取该互斥量的任务TCB,xReturn为返回值,若取消了该任务的优先级继承返回pdTRUE,否则返回pdFALSE
TCB_t *const pxTCB = (TCB_t *)pxMutexHolder;
BaseType_t xReturn = pdFALSE;
if (pxMutexHolder != NULL)
{
// 断言,调用该函数的任务必须是当前正在运行的任务,调用该函数的任务必须已经获取至少一个互斥量
configASSERT(pxTCB == pxCurrentTCB);
configASSERT(pxTCB->uxMutexesHeld);
// 使该任务TCB的uxMutexesHeld字段减一,表示该任务即将释放一个已经获取到的互斥量
(pxTCB->uxMutexesHeld)--;
// 如果该任务继承了别的任务的优先级
if (pxTCB->uxPriority != pxTCB->uxBasePriority)
{
// 仅当该任务获取到的互斥量在调用该函数时仅有一个的情况下,才取消优先级继承,恢复原来的优先级
if (pxTCB->uxMutexesHeld == (UBaseType_t)0)
{
// 将该任务TCB的状态列表项从原来的就绪列表(继承的优先级对应的就绪列表)中卸载
if (uxListRemove(&(pxTCB->xStateListItem)) == (UBaseType_t)0)
{
// 使用优化的硬件调度方法,如果有的话
taskRESET_READY_PRIORITY(pxTCB->uxPriority);
}
else
{
mtCOVERAGE_TEST_MARKER();
}
// 调试信息
traceTASK_PRIORITY_DISINHERIT(pxTCB, pxTCB->uxBasePriority);
// 恢复该任务的基础优先级
pxTCB->uxPriority = pxTCB->uxBasePriority;
// 重置该任务TCB的事件列表项
listSET_LIST_ITEM_VALUE(&(pxTCB->xEventListItem), (TickType_t)configMAX_PRIORITIES - (TickType_t)pxTCB->uxPriority);
// 将该任务TCB的状态列表项挂载到基础优先级对应的就绪列表上
prvAddTaskToReadyList(pxTCB);
// 记录返回值
xReturn = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
return xReturn;
}
这篇个人学习笔记详细探讨了FreeRTOS中的优先级继承机制,重点解析了`xTaskPriorityInherit`和`xTaskPriorityDisinherit`两个关键函数。当高优先级任务尝试获取已被低优先级任务持有的互斥量时,如何处理优先级继承以及在释放互斥量时如何取消继承。
2770





