Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 45 additions & 49 deletions tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,62 +693,58 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
UBaseType_t uxPrevCriticalNesting;
const TCB_t * pxThisTCB;

/* This should be skipped if called from an ISR. If the task on the current
* core is no longer running, then vTaskSwitchContext() probably should
* be run before returning, but we don't have a way to force that to happen
* from here. */
if( portCHECK_IF_IN_ISR() == pdFALSE )
{
/* This function is always called with interrupts disabled
* so this is safe. */
pxThisTCB = pxCurrentTCBs[ portGET_CORE_ID() ];

while( pxThisTCB->xTaskRunState == taskTASK_YIELDING )
{
/* We are only here if we just entered a critical section
* or if we just suspended the scheduler, and another task
* has requested that we yield.
*
* This is slightly complicated since we need to save and restore
* the suspension and critical nesting counts, as well as release
* and reacquire the correct locks. And then, do it all over again
* if our state changed again during the reacquisition. */
uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT();

if( uxPrevCriticalNesting > 0U )
{
portSET_CRITICAL_NESTING_COUNT( 0U );
portRELEASE_ISR_LOCK();
}
else
{
/* The scheduler is suspended. uxSchedulerSuspended is updated
* only when the task is not requested to yield. */
mtCOVERAGE_TEST_MARKER();
}
/* This must only be called from within a task. */
portASSERT_IF_IN_ISR();

portRELEASE_TASK_LOCK();
/* This function is always called with interrupts disabled
* so this is safe. */
pxThisTCB = pxCurrentTCBs[ portGET_CORE_ID() ];

portMEMORY_BARRIER();
configASSERT( pxThisTCB->xTaskRunState == taskTASK_YIELDING );
while( pxThisTCB->xTaskRunState == taskTASK_YIELDING )
{
/* We are only here if we just entered a critical section
* or if we just suspended the scheduler, and another task
* has requested that we yield.
*
* This is slightly complicated since we need to save and restore
* the suspension and critical nesting counts, as well as release
* and reacquire the correct locks. And then, do it all over again
* if our state changed again during the reacquisition. */
uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT();

portENABLE_INTERRUPTS();
if( uxPrevCriticalNesting > 0U )
{
portSET_CRITICAL_NESTING_COUNT( 0U );
portRELEASE_ISR_LOCK();
}
else
{
/* The scheduler is suspended. uxSchedulerSuspended is updated
* only when the task is not requested to yield. */
mtCOVERAGE_TEST_MARKER();
}

/* Enabling interrupts should cause this core to immediately
* service the pending interrupt and yield. If the run state is still
* yielding here then that is a problem. */
configASSERT( pxThisTCB->xTaskRunState != taskTASK_YIELDING );
portRELEASE_TASK_LOCK();

portDISABLE_INTERRUPTS();
portGET_TASK_LOCK();
portGET_ISR_LOCK();
portMEMORY_BARRIER();
configASSERT( pxThisTCB->xTaskRunState == taskTASK_YIELDING );

portSET_CRITICAL_NESTING_COUNT( uxPrevCriticalNesting );
portENABLE_INTERRUPTS();

if( uxPrevCriticalNesting == 0U )
{
portRELEASE_ISR_LOCK();
}
/* Enabling interrupts should cause this core to immediately
* service the pending interrupt and yield. If the run state is still
* yielding here then that is a problem. */
configASSERT( pxThisTCB->xTaskRunState != taskTASK_YIELDING );

portDISABLE_INTERRUPTS();
portGET_TASK_LOCK();
portGET_ISR_LOCK();

portSET_CRITICAL_NESTING_COUNT( uxPrevCriticalNesting );

if( uxPrevCriticalNesting == 0U )
{
portRELEASE_ISR_LOCK();
}
}
}
Expand Down