mutex是怎么实现优先级继承的,列出freertos里的具体代码说明
时间: 2024-03-09 20:44:14 浏览: 16
在 FreeRTOS 中,互斥量的实现是通过任务的优先级继承实现的。当一个任务获得了一个互斥量时,如果有其他任务试图获得该互斥量但其优先级比当前任务高,那么当前任务的优先级就会被提升到最高优先级,直到它释放互斥量为止。这样就可以避免优先级反转问题。
下面是 FreeRTOS 中任务优先级继承的具体实现代码:
1. 首先,FreeRTOS 定义了一个名为 `pxMutexHolder` 的指针变量,用于指向当前持有互斥量的任务。
```
static TaskHandle_t pxMutexHolder = NULL;
```
2. 当一个任务获得互斥量时,它会调用 `xQueueGenericSend()` 函数来将自己的任务句柄放入互斥量的等待队列中。如果当前互斥量已经被其他任务持有,那么当前任务的优先级会被提升到最高优先级。
```
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait )
{
BaseType_t xYieldRequired = pdFALSE;
Semaphore_t *pxSemaphore = ( Semaphore_t * ) xSemaphore;
configASSERT( pxSemaphore );
/* Attempt to obtain the semaphore. */
taskENTER_CRITICAL();
{
if( pxSemaphore->xSemaphoreCount > 0 )
{
--pxSemaphore->xSemaphoreCount;
xYieldRequired = pdFALSE;
}
else
{
if ( xTaskGetCurrentTaskHandle() == pxMutexHolder )
{
++pxSemaphore->uxRecursiveCallCount;
xYieldRequired = pdFALSE;
}
else
{
xYieldRequired = xQueueGenericSend( pxSemaphore->xSemaphoreQueue,
&xTaskGetCurrentTaskHandle(),
xTicksToWait,
queueSEND_TO_BACK );
}
}
}
taskEXIT_CRITICAL();
/* If obtaining the semaphore caused a task to unblock, and the
unblocked task has a higher priority than the current task, then a
context switch should be performed. */
if( xYieldRequired == pdTRUE )
{
portYIELD_WITHIN_API();
}
return ( xYieldRequired == pdPASS );
}
```
3. 当持有互斥量的任务释放互斥量时,如果有其他任务在等待该互斥量,那么会从等待队列中选择一个优先级最高的任务来获得互斥量。同时,如果该任务的优先级比当前任务高,那么当前任务的优先级会被提升到该任务的优先级。
```
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore )
{
BaseType_t xYieldRequired = pdFALSE;
Semaphore_t *pxSemaphore = ( Semaphore_t * ) xSemaphore;
configASSERT( pxSemaphore );
taskENTER_CRITICAL();
{
/* Is there a task waiting for the semaphore? */
if( uxQueueMessagesWaiting( pxSemaphore->xSemaphoreQueue ) == ( UBaseType_t ) 0U )
{
/* The semaphore is not being waited for. */
++pxSemaphore->xSemaphoreCount;
xYieldRequired = pdFALSE;
}
else
{
/* The semaphore is being waited for by one or more tasks. */
if( pxSemaphore->uxRecursiveCallCount > ( UBaseType_t ) 0U )
{
/* The semaphore is already held by the calling task. */
--pxSemaphore->uxRecursiveCallCount;
xYieldRequired = pdFALSE;
}
else
{
TaskHandle_t xTask;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Obtain the task handle of the highest priority task that
is waiting for the semaphore. */
xQueueReceiveFromISR( pxSemaphore->xSemaphoreQueue,
&xTask,
&xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken == pdTRUE )
{
portYIELD_WITHIN_API();
}
/* If the task waiting for the semaphore has a higher priority
than the current task then a context switch is required. */
if( xTask != NULL )
{
if( xTask != pxMutexHolder )
{
vTaskPriorityInherit( xTask );
}
xYieldRequired = xTaskResumeAll();
pxMutexHolder = xTask;
}
else
{
/* The semaphore was not obtained. */
xYieldRequired = pdFALSE;
}
}
}
}
taskEXIT_CRITICAL();
if( xYieldRequired != pdFALSE )
{
portYIELD_WITHIN_API();
}
return xYieldRequired;
}
```
在以上代码中,`vTaskPriorityInherit()` 函数就是用来实现任务优先级继承的。当一个任务获得互斥量时,如果有其他任务试图获得该互斥量但其优先级比当前任务高,那么当前任务的优先级就会被提升到最高优先级,直到它释放互斥量为止。