From 53229b15378b7464c0011961a72c6dfd1d9f01a2 Mon Sep 17 00:00:00 2001 From: chinglee-iot <61685396+chinglee-iot@users.noreply.github.com> Date: Wed, 6 Sep 2023 17:47:41 +0800 Subject: [PATCH] Assert if prvCheckForRunStateChange is called in ISR (#779) * Assert if prvCheckForRunStateChange is called in ISR --- tasks.c | 94 +++++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/tasks.c b/tasks.c index a0651b1b6..7eaef888b 100644 --- a/tasks.c +++ b/tasks.c @@ -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(); } } }