优先级继承原理
//持有者记录增加
#if ( configUSE_MUTEXES == 1 )
void *pvTaskIncrementMutexHeldCount( void )
{
/* If xSemaphoreCreateMutex() is called before any tasks have been created
then pxCurrentTCB will be NULL. */
if( pxCurrentTCB != NULL )
{
//持有者任务控制块里 持有记录加一
( pxCurrentTCB->uxMutexesHeld )++;
}
//返回当前任务控制块
return pxCurrentTCB;
}
#endif /* configUSE_MUTEXES */
//优先级继承
//参数:持有互斥信号量的任务控制块
#if ( configUSE_MUTEXES == 1 )
void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
{
TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
//1、任务控制块不为空
if( pxMutexHolder != NULL )
{
//2、优先级小于当前获取信号量的有限,才会去处理继承
if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
{
/* */
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
{
//3、修改持有者事件列表中,列表项的属性值 为当前任务优先级
listSET_LIST_ITEM_VALUE( &( pxTCB->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();
}
/*
4、判断持有者任务是否在就绪列表中
4.1、移除
4.2、修改任务优先级,这个修改是任务控制块里的信息
4.3、添加到新的就绪列表中
*/
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
{
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Inherit the priority before being moved into the new list. */
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
prvAddTaskToReadyList( pxTCB );
}
else
{
/* Just inherit the priority. */
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
}
traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_MUTEXES */
//优先级恢复
/*
1、
*/
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
{
TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
BaseType_t xReturn = pdFALSE;
if( pxMutexHolder != NULL )
{
//1、持有者任务持有记录减一
( pxTCB->uxMutexesHeld )--;
/* Has the holder of the mutex inherited the priority of another
task? */
//2、优先级是否修改过
if( pxTCB->uxPriority != pxTCB->uxBasePriority )
{
//3、递归记录为0的时候
/* Only disinherit if no other mutexes are held. */
if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
{
/* 4、从当前就绪列表中移除*/
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* 5、恢复任务优先级 */
traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
pxTCB->uxPriority = pxTCB->uxBasePriority;
/*6、已经不是持有者,把任务添加到新的就绪列表中去*/
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
prvAddTaskToReadyList( pxTCB );
/* 触发上下文切换,释放CPU使用权 */
xReturn = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
return xReturn;
}
互斥信号量初始化创建Mutexinit
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutex()
xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
||||
#endif
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
{
Queue_t *pxNewQueue;
const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
//创建消息队列
/*
队列长度:1
队列大小:0
队列类型:queueQUEUE_TYPE_MUTEX
*/
pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
//初始化互斥信号量->其实就是初始化消息队列的控制块
prvInitialiseMutex( pxNewQueue );
return pxNewQueue;
}
static void prvInitialiseMutex( Queue_t *pxNewQueue )
{
if( pxNewQueue != NULL )
{
/*
1、信号的持有者为空
2、消息队列的类型为互斥信号量
3、递归记录初始为0
4、往消息队列发送一个消息->其实赋值互斥信号量为1
*/
pxNewQueue->pxMutexHolder = NULL;
pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
/* In case this is a recursive mutex. */
pxNewQueue->u.uxRecursiveCallCount = 0;
traceCREATE_MUTEX( pxNewQueue );
/* Start with the semaphore in the expected state. */
( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
}
else
{
traceCREATE_MUTEX_FAILED();
}
}
互斥信号量释放MutexGive
#define xSemaphoreGive( xSemaphore )
xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
//互斥信号量处理在数据拷贝接口中
xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/*
1、判断是否为互斥信号量
2、恢复任务优先级
3、信号持有者赋值为空,也就是说其他任务可以获取了
*/
#if ( configUSE_MUTEXES == 1 )
{
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
/* The mutex is no longer being held. */
xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
pxQueue->pxMutexHolder = NULL;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_MUTEXES */
互斥信号量获取MutexTake
#define xSemaphoreTake( xSemaphore, xBlockTime )
xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE )
/*
队列不为空处理
1、判断是否为互斥信号量
2、记录当前任务为信号持有者
*/
#if ( configUSE_MUTEXES == 1 )
{
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
/* Record the information required to implement
priority inheritance should it become necessary. */
pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/*
队列为空处理
1、判断是否为互斥信号量
2、进入临界段
3、优先级继承
*/
#if ( configUSE_MUTEXES == 1 )
{
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
taskENTER_CRITICAL();
{
vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
}
taskEXIT_CRITICAL();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif
递归互斥信号量释放RecursiveMutexGive
#define xSemaphoreGiveRecursive( xMutex )
xQueueGiveMutexRecursive( ( xMutex ) )
/*
参数:
信号量句柄
步骤:
1、判断当前任务是否为持有者
1.1、递归记录减一
1.2、判断记录是否为0
1.3、发送一个消息
2、不为持有者返回错误
*/
BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
{
BaseType_t xReturn;
Queue_t * const pxMutex = ( Queue_t * ) xMutex;
if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */
{
( pxMutex->u.uxRecursiveCallCount )--;
if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 )
{
( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
递归互斥信号量获取RecursiveMutexTake
#if( configUSE_RECURSIVE_MUTEXES == 1 )
#define xSemaphoreTakeRecursive( xMutex, xBlockTime )
xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
#endif
/*
参数:互斥信号句柄,超时等待时间
步骤:
1、判断是否为持有者
1.1、递归记录加一
1.2、返回成功
2、不为持有者
2.1、接收消息---获取信号量
2.2、获取成功----递归记录加一
2.3、获取失败---- 返回失败
*/
BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait )
{
BaseType_t xReturn;
Queue_t * const pxMutex = ( Queue_t * ) xMutex;
if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
{
( pxMutex->u.uxRecursiveCallCount )++;
xReturn = pdPASS;
}
else
{
xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE );
/* pdPASS will only be returned if the mutex was successfully
obtained. The calling task may have entered the Blocked state
before reaching here. */
if( xReturn != pdFAIL )
{
( pxMutex->u.uxRecursiveCallCount )++;
}
else
{
traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
}
}
return xReturn;
}