Add vTaskPrioritySetCurrent()

This commit is contained in:
Darian Leung
2020-01-14 04:39:33 +08:00
committed by maojianxin
parent 49cb9972de
commit 1167a5c2f9
3 changed files with 150 additions and 2 deletions

View File

@ -974,6 +974,19 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
*/
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION;
/**
* Set the current priority of any task.
*
* This function sets the current priority of a task, and does not modify the
* base priority at all.
*
* @param xTask Handle to the task for which the priority is being set.
* Passing a NULL handle results in the priority of the calling task being set.
*
* @param uxNewPriority The priority to which the task will be set.
*/
void vTaskPrioritySetCurrent( TaskHandle_t xTask, UBaseType_t uxNewPriority )
/**
* Suspend a task.
*

View File

@ -1770,6 +1770,141 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
taskEXIT_CRITICAL(&xTaskQueueMutex);
}
void vTaskPrioritySetCurrent( TaskHandle_t xTask, UBaseType_t uxNewPriority )
{
TCB_t *pxTCB;
UBaseType_t uxCurrentPriority, uxPriorityUsedOnEntry;
BaseType_t xYieldRequired = pdFALSE;
configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
/* Ensure the new priority is valid. */
if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
{
uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
taskENTER_CRITICAL(&xTaskQueueMutex);
{
/* If null is passed in here then it is the priority of the calling
task that is being changed. */
pxTCB = prvGetTCBFromHandle( xTask );
traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
uxCurrentPriority = pxTCB->uxPriority;
if( uxCurrentPriority != uxNewPriority )
{
/* The priority change may have readied a task of higher
priority than the calling task. */
if( uxNewPriority > uxCurrentPriority )
{
if( pxTCB != pxCurrentTCB[ xPortGetCoreID() ] )
{
/* The priority of a task other than the currently
running task is being raised. Is the priority being
raised above that of the running task? */
if ( tskCAN_RUN_HERE(pxTCB->xCoreID) && uxNewPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
xYieldRequired = pdTRUE;
}
else if ( pxTCB->xCoreID != xPortGetCoreID() )
{
taskYIELD_OTHER_CORE( pxTCB->xCoreID, uxNewPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* The priority of the running task is being raised,
but the running task must already be the highest
priority task able to run so no yield is required. */
}
}
else if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] )
{
/* Setting the priority of the running task down means
there may now be another task of higher priority that
is ready to execute. */
xYieldRequired = pdTRUE;
}
else
{
/* Setting the priority of any other task down does not
require a yield as the running task must be above the
new priority of the task being modified. */
}
/* Remember the ready list the task might be referenced from
before its uxPriority member is changed so the
taskRESET_READY_PRIORITY() macro can function correctly. */
uxPriorityUsedOnEntry = pxTCB->uxPriority;
pxTCB->uxPriority = uxNewPriority;
/* Only reset the event list item value if the value is not
being used for anything else. */
if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
{
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* If the task is in the blocked or suspended list we need do
nothing more than change it's priority variable. However, if
the task is in a ready list it needs to be removed and placed
in the list appropriate to its new priority. */
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* The task is currently in its ready list - remove before adding
it to it's new ready list. As we are in a critical section we
can do this even if the scheduler is suspended. */
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* It is known that the task is in its ready list so
there is no need to check again and the port level
reset macro can be called directly. */
portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
prvReaddTaskToReadyList( pxTCB );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
if( xYieldRequired == pdTRUE )
{
taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Remove compiler warning about unused variables when the port
optimised task selection is not being used. */
( void ) uxPriorityUsedOnEntry;
}
}
taskEXIT_CRITICAL(&xTaskQueueMutex);
}
#endif /* INCLUDE_vTaskPrioritySet */
/*-----------------------------------------------------------*/

View File

@ -113,7 +113,7 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
// Temporarily raise current task priority to prevent a deadlock while
// waiting for IPC task to start on the other CPU
int old_prio = uxTaskPriorityGet(NULL);
vTaskPrioritySet(NULL, configMAX_PRIORITIES - 1);
vTaskPrioritySetCurrent(NULL, configMAX_PRIORITIES - 1);
// Signal to the spi_flash_op_block_task on the other CPU that we need it to
// disable cache there and block other tasks from executing.
s_flash_op_can_start = false;
@ -126,7 +126,7 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
// Disable scheduler on the current CPU
vTaskSuspendAll();
// Can now set the priority back to the normal one
vTaskPrioritySet(NULL, old_prio);
vTaskPrioritySetCurrent(NULL, old_prio);
// This is guaranteed to run on CPU <cpuid> because the other CPU is now
// occupied by highest priority task
assert(xPortGetCoreID() == cpuid);