From 35025858cf641b1bd3380da2f5e4b76cadbf8809 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Fri, 15 Aug 2025 17:03:39 +0200 Subject: [PATCH] fix(freertos-smp): Miscellaneous fixes for granular locks --- event_groups.c | 78 +++-------- include/FreeRTOS.h | 4 +- include/task.h | 98 +++++++++---- queue.c | 34 +++-- stream_buffer.c | 59 ++------ tasks.c | 340 ++++++++++++++++++++------------------------- timers.c | 48 +++++-- 7 files changed, 302 insertions(+), 359 deletions(-) diff --git a/event_groups.c b/event_groups.c index c9e20031d..640bf99e6 100644 --- a/event_groups.c +++ b/event_groups.c @@ -87,24 +87,6 @@ #define event_groupsEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxEventBits ) taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ -/* - * Locks an event group for tasks. Prevents other tasks from accessing the event group but allows - * ISRs to pend access to the event group. Caller cannot be preempted by other tasks - * after locking the event group, thus allowing the caller to execute non-deterministic - * operations. - */ - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static void prvLockEventGroupForTasks( EventGroup_t * pxEventBits ) PRIVILEGED_FUNCTION; - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ - -/* - * Unlocks an event group for tasks. Handles all pended access from ISRs, then reenables - * preemption for the caller. - */ - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static BaseType_t prvUnlockEventGroupForTasks( EventGroup_t * pxEventBits ) PRIVILEGED_FUNCTION; - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ - /* * Test the bits set in uxCurrentEventBits to see if the wait condition is met. * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is @@ -129,8 +111,22 @@ * When the task unlocks the event group, all pended access attempts are handled. */ #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - #define event_groupsLOCK( pxEventBits ) prvLockEventGroupForTasks( pxEventBits ) - #define event_groupsUNLOCK( pxEventBits ) prvUnlockEventGroupForTasks( pxEventBits ); + #define event_groupsLOCK( pxEventBits ) taskDATA_GROUP_LOCK( &( ( pxEventBits )->xTaskSpinlock ) ) + #define event_groupsUNLOCK( pxEventBits ) \ + ( { \ + taskDATA_GROUP_UNLOCK( &( ( pxEventBits )->xTaskSpinlock ) ); \ + BaseType_t xAlreadyYielded; \ + if( xTaskUnlockCanYield() == pdTRUE ) \ + { \ + taskYIELD_WITHIN_API(); \ + xAlreadyYielded = pdTRUE; \ + } \ + else \ + { \ + xAlreadyYielded = pdFALSE; \ + } \ + xAlreadyYielded; \ + } ) #else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ #define event_groupsLOCK( pxEventBits ) vTaskSuspendAll() #define event_groupsUNLOCK( pxEventBits ) xTaskResumeAll() @@ -867,48 +863,6 @@ traceRETURN_vEventGroupClearBitsCallback(); } /*-----------------------------------------------------------*/ - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static void prvLockEventGroupForTasks( EventGroup_t * pxEventBits ) - { - /* Disable preemption so that the current task cannot be preempted by another task */ - vTaskPreemptionDisable( NULL ); - - /* Keep holding xTaskSpinlock to prevent tasks on other cores from accessing - * the event group while it is suspended. */ - portGET_SPINLOCK( portGET_CORE_ID(), &( pxEventBits->xTaskSpinlock ) ); - } - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ -/*-----------------------------------------------------------*/ - - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static BaseType_t prvUnlockEventGroupForTasks( EventGroup_t * pxEventBits ) - { - BaseType_t xReturn = pdFALSE; - - /* Release the previously held task spinlock */ - portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxEventBits->xTaskSpinlock ) ); - - /* Re-enable preemption */ - vTaskPreemptionEnable( NULL ); - - /* Yield if preemption was re-enabled*/ - if( xTaskUnlockCanYield() == pdTRUE ) - { - taskYIELD_WITHIN_API(); - - /* Return true as the task was preempted */ - xReturn = pdTRUE; - } - else - { - /* Return false as the task was not preempted */ - xReturn = pdFALSE; - } - - return xReturn; - } - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ -/*-----------------------------------------------------------*/ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 83caf37de..5ea6bd79f 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -2972,8 +2972,8 @@ * portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when * the tick count is returned to the standard critical section macros. */ #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL_DATA_GROUP( &xTaskSpinlock, &xISRSpinlock ) - #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL_DATA_GROUP( &xTaskSpinlock, &xISRSpinlock ) + #define portTICK_TYPE_ENTER_CRITICAL() kernelENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() kernelEXIT_CRITICAL() #else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() diff --git a/include/task.h b/include/task.h index 9dbc8db89..8bdb80c19 100644 --- a/include/task.h +++ b/include/task.h @@ -299,11 +299,11 @@ typedef enum { \ const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \ /* Task spinlock is always taken first */ \ - portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxTaskSpinlock ); \ + portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \ /* Disable interrupts */ \ portDISABLE_INTERRUPTS(); \ /* Take the ISR spinlock next */ \ - portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \ + portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \ /* Increment the critical nesting count */ \ portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ } \ @@ -322,11 +322,13 @@ typedef enum #define taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( pxISRSpinlock, puxSavedInterruptStatus ) \ do { \ *( puxSavedInterruptStatus ) = portSET_INTERRUPT_MASK_FROM_ISR(); \ - const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \ - /* Take the ISR spinlock */ \ - portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \ - /* Increment the critical nesting count */ \ - portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ + { \ + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \ + /* Take the ISR spinlock */ \ + portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \ + /* Increment the critical nesting count */ \ + portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ + } \ } while( 0 ) #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ @@ -339,27 +341,27 @@ typedef enum * \ingroup GranularLocks */ #if ( portUSING_GRANULAR_LOCKS == 1 ) - #define taskDATA_GROUP_EXIT_CRITICAL( pxTaskSpinlock, pxISRSpinlock ) \ - do { \ - const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \ - configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); \ - /* Release the ISR spinlock */ \ - portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \ - /* Release the task spinlock */ \ - portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxTaskSpinlock ); \ - /* Decrement the critical nesting count */ \ - portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ - /* Enable interrupts only if the critical nesting count is 0 */ \ - if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \ - { \ - portENABLE_INTERRUPTS(); \ - } \ - else \ - { \ - mtCOVERAGE_TEST_MARKER(); \ - } \ - /* Re-enable preemption */ \ - vTaskPreemptionEnable( NULL ); \ + #define taskDATA_GROUP_EXIT_CRITICAL( pxTaskSpinlock, pxISRSpinlock ) \ + do { \ + const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \ + configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); \ + /* Release the ISR spinlock */ \ + portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \ + /* Release the task spinlock */ \ + portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \ + /* Decrement the critical nesting count */ \ + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ + /* Enable interrupts only if the critical nesting count is 0 */ \ + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \ + { \ + portENABLE_INTERRUPTS(); \ + } \ + else \ + { \ + mtCOVERAGE_TEST_MARKER(); \ + } \ + /* Re-enable preemption */ \ + vTaskPreemptionEnable( NULL ); \ } while( 0 ) #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ @@ -379,7 +381,7 @@ typedef enum /* Decrement the critical nesting count */ \ portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \ /* Release the ISR spinlock */ \ - portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \ + portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \ if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \ { \ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ @@ -387,6 +389,44 @@ typedef enum } while( 0 ) #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ +/** + * task. h + * + * Macros to lock a data group (task-level lock only). + * + * \defgroup taskDATA_GROUP_LOCK taskDATA_GROUP_LOCK + * \ingroup GranularLocks + */ +#if ( portUSING_GRANULAR_LOCKS == 1 ) + #define taskDATA_GROUP_LOCK( pxTaskSpinlock ) \ + do { \ + /* Disable preemption while holding the task spinlock. */ \ + vTaskPreemptionDisable( NULL ); \ + { \ + portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \ + } \ + } while( 0 ) +#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ + +/** + * task. h + * + * Macros to unlock a data group (task-level lock only). + * + * \defgroup taskDATA_GROUP_UNLOCK taskDATA_GROUP_UNLOCK + * \ingroup GranularLocks + */ +#if ( portUSING_GRANULAR_LOCKS == 1 ) + #define taskDATA_GROUP_UNLOCK( pxTaskSpinlock ) \ + do { \ + { \ + portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \ + } \ + /* Re-enable preemption after releasing the task spinlock. */ \ + vTaskPreemptionEnable( NULL ); \ + } while( 0 ) +#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ + /*----------------------------------------------------------- * TASK CREATION API *----------------------------------------------------------*/ diff --git a/queue.c b/queue.c index 21426d448..4b08327f3 100644 --- a/queue.c +++ b/queue.c @@ -328,25 +328,23 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, * When the tasks unlocks the queue, all pended access attempts are handled. */ #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - #define queueLOCK( pxQueue ) \ - do { \ - vTaskPreemptionDisable( NULL ); \ - prvLockQueue( ( pxQueue ) ); \ - portGET_SPINLOCK( portGET_CORE_ID(), &( pxQueue->xTaskSpinlock ) ); \ + #define queueLOCK( pxQueue ) \ + do { \ + taskDATA_GROUP_LOCK( &( ( pxQueue )->xTaskSpinlock ) ); \ + prvLockQueue( ( pxQueue ) ); \ } while( 0 ) - #define queueUNLOCK( pxQueue, xYieldAPI ) \ - do { \ - prvUnlockQueue( ( pxQueue ) ); \ - portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxQueue->xTaskSpinlock ) ); \ - vTaskPreemptionEnable( NULL ); \ - if( ( xYieldAPI ) == pdTRUE ) \ - { \ - taskYIELD_WITHIN_API(); \ - } \ - else \ - { \ - mtCOVERAGE_TEST_MARKER(); \ - } \ + #define queueUNLOCK( pxQueue, xYieldAPI ) \ + do { \ + prvUnlockQueue( ( pxQueue ) ); \ + taskDATA_GROUP_UNLOCK( &( ( pxQueue )->xTaskSpinlock ) ); \ + if( ( xYieldAPI ) == pdTRUE ) \ + { \ + taskYIELD_WITHIN_API(); \ + } \ + else \ + { \ + mtCOVERAGE_TEST_MARKER(); \ + } \ } while( 0 ) #else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ #define queueLOCK( pxQueue ) \ diff --git a/stream_buffer.c b/stream_buffer.c index 8dd11b8eb..fe52427c6 100644 --- a/stream_buffer.c +++ b/stream_buffer.c @@ -63,10 +63,10 @@ * Macros to mark the start and end of a critical code region. */ #if ( portUSING_GRANULAR_LOCKS == 1 ) - #define sbENTER_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_ENTER_CRITICAL( &pxStreamBuffer->xTaskSpinlock, &pxStreamBuffer->xISRSpinlock ) - #define sbENTER_CRITICAL_FROM_ISR( pxStreamBuffer, puxSavedInterruptStatus ) taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( &pxStreamBuffer->xISRSpinlock, puxSavedInterruptStatus ) - #define sbEXIT_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL( &pxStreamBuffer->xTaskSpinlock, &pxStreamBuffer->xISRSpinlock ) - #define sbEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, &pxStreamBuffer->xISRSpinlock ) + #define sbENTER_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_ENTER_CRITICAL( &( ( pxStreamBuffer )->xTaskSpinlock ), &( ( pxStreamBuffer )->xISRSpinlock ) ) + #define sbENTER_CRITICAL_FROM_ISR( pxStreamBuffer, puxSavedInterruptStatus ) taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( &( ( pxStreamBuffer )->xISRSpinlock ), puxSavedInterruptStatus ) + #define sbEXIT_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL( &( ( pxStreamBuffer )->xTaskSpinlock ), &( ( pxStreamBuffer )->xISRSpinlock ) ) + #define sbEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, &( ( pxStreamBuffer )->xISRSpinlock ) ) #else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ #define sbENTER_CRITICAL( pxStreamBuffer ) taskENTER_CRITICAL(); #define sbENTER_CRITICAL_FROM_ISR( pxStreamBuffer, puxSavedInterruptStatus ) do { *( puxSavedInterruptStatus ) = taskENTER_CRITICAL_FROM_ISR(); } while( 0 ) @@ -84,8 +84,8 @@ * When the task unlocks the stream buffer, all pended access attempts are handled. */ #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - #define sbLOCK( pxStreamBuffer ) prvLockStreamBufferForTasks( pxStreamBuffer ) - #define sbUNLOCK( pxStreamBuffer ) prvUnlockStreamBufferForTasks( pxStreamBuffer ) + #define sbLOCK( pxStreamBuffer ) taskDATA_GROUP_LOCK( &( ( pxStreamBuffer )->xTaskSpinlock ) ) + #define sbUNLOCK( pxStreamBuffer ) taskDATA_GROUP_UNLOCK( &( ( pxStreamBuffer )->xTaskSpinlock ) ) #else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ #define sbLOCK( pxStreamBuffer ) vTaskSuspendAll() #define sbUNLOCK( pxStreamBuffer ) ( void ) xTaskResumeAll() @@ -109,7 +109,7 @@ ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ } \ } \ - ( void ) sbUNLOCK( pxStreamBuffer ); \ + sbUNLOCK( pxStreamBuffer ); \ } while( 0 ) #endif /* sbRECEIVE_COMPLETED */ @@ -189,7 +189,7 @@ ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ } \ } \ - ( void ) sbUNLOCK( pxStreamBuffer ) + sbUNLOCK( pxStreamBuffer ) #endif /* sbSEND_COMPLETED */ /* If user has provided a per-instance send completed callback, then @@ -288,24 +288,6 @@ typedef struct StreamBufferDef_t #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ } StreamBuffer_t; -/* - * Locks a stream buffer for tasks. Prevents other tasks from accessing the stream buffer - * but allows ISRs to pend access to the stream buffer. Caller cannot be preempted - * by other tasks after locking the stream buffer, thus allowing the caller to - * execute non-deterministic operations. - */ - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static void prvLockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION; - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ - -/* - * Unlocks a stream buffer for tasks. Handles all pended access from ISRs, then reenables preemption - * for the caller. - */ - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static void prvUnlockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION; - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ - /* * The number of bytes available to be read from the buffer. */ @@ -381,31 +363,6 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, StreamBufferCallbackFunction_t pxSendCompletedCallback, StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; -/*-----------------------------------------------------------*/ - - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static void prvLockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer ) - { - /* Disable preemption so that the current task cannot be preempted by another task */ - vTaskPreemptionDisable( NULL ); - - /* Keep holding xTaskSpinlock after unlocking the data group to prevent tasks - * on other cores from accessing the stream buffer while it is suspended. */ - portGET_SPINLOCK( portGET_CORE_ID(), &( pxStreamBuffer->xTaskSpinlock ) ); - } - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ -/*-----------------------------------------------------------*/ - - #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - static void prvUnlockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer ) - { - /* Release the previously held task spinlock */ - portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxStreamBuffer->xTaskSpinlock ) ); - - /* Re-enable preemption */ - vTaskPreemptionEnable( NULL ); - } - #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ /*-----------------------------------------------------------*/ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) diff --git a/tasks.c b/tasks.c index 4379a63aa..a093d37bd 100644 --- a/tasks.c +++ b/tasks.c @@ -630,6 +630,7 @@ static BaseType_t prvCreateIdleTasks( void ); #endif /* #if ( configNUMBER_OF_CORES > 1 ) */ #if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 ) + /* * Checks to see if another task moved the current task out of the ready * list while it was waiting to enter a lightweight critical section and yields, if so. @@ -971,7 +972,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; #if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 ) static void prvLightWeightCheckForRunStateChange( void ) { - const TCB_t * pxThisTCB; BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); @@ -1024,8 +1024,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; kernelGET_ISR_LOCK( xCoreID ); portSET_CRITICAL_NESTING_COUNT( xCoreID, uxPrevCriticalNesting ); - }; -} + } + } #endif /* #if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 ) */ /*-----------------------------------------------------------*/ @@ -1096,12 +1096,12 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; xYieldPendings[ xCoreID ] = pdTRUE; } } - #else + #else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ { xLowestPriorityToPreempt = xCurrentCoreTaskPriority; xLowestPriorityCore = xCoreID; } - #endif + #endif /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ } } else @@ -1413,12 +1413,12 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; xYieldPendings[ uxCore ] = pdTRUE; } } - #else + #else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ { xLowestPriority = xTaskPriority; xLowestPriorityCore = ( BaseType_t ) uxCore; } - #endif + #endif /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ } } } @@ -2840,7 +2840,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, traceENTER_uxTaskPriorityGet( xTask ); - kernelENTER_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + kernelENTER_CRITICAL(); + } + #else + { + portBASE_TYPE_ENTER_CRITICAL(); + } + #endif { /* If null is passed in here then it is the priority of the task * that called uxTaskPriorityGet() that is being queried. */ @@ -2849,7 +2857,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, uxReturn = pxTCB->uxPriority; } - kernelEXIT_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + kernelEXIT_CRITICAL(); + } + #else + { + portBASE_TYPE_EXIT_CRITICAL(); + } + #endif traceRETURN_uxTaskPriorityGet( uxReturn ); @@ -2918,7 +2934,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, traceENTER_uxTaskBasePriorityGet( xTask ); - kernelENTER_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + kernelENTER_CRITICAL(); + } + #else + { + portBASE_TYPE_ENTER_CRITICAL(); + } + #endif { /* If null is passed in here then it is the base priority of the task * that called uxTaskBasePriorityGet() that is being queried. */ @@ -2927,7 +2951,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, uxReturn = pxTCB->uxBasePriority; } - kernelEXIT_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + kernelEXIT_CRITICAL(); + } + #else + { + portBASE_TYPE_EXIT_CRITICAL(); + } + #endif traceRETURN_uxTaskBasePriorityGet( uxReturn ); @@ -3262,14 +3294,30 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, traceENTER_vTaskCoreAffinityGet( xTask ); - kernelENTER_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + kernelENTER_CRITICAL(); + } + #else + { + portBASE_TYPE_ENTER_CRITICAL(); + } + #endif { pxTCB = prvGetTCBFromHandle( xTask ); configASSERT( pxTCB != NULL ); uxCoreAffinityMask = pxTCB->uxCoreAffinityMask; } - kernelEXIT_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + kernelEXIT_CRITICAL(); + } + #else + { + portBASE_TYPE_EXIT_CRITICAL(); + } + #endif traceRETURN_vTaskCoreAffinityGet( uxCoreAffinityMask ); @@ -3351,7 +3399,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, } else { - if( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) ) + if( ( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) ) { prvYieldCore( pxTCB->xTaskRunState ); } @@ -4443,11 +4491,7 @@ BaseType_t xTaskResumeAll( void ) } } - if( xYieldPendings[ xCoreID ] != pdFALSE - #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - && ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U ) - #endif - ) + if( xYieldPendings[ xCoreID ] != pdFALSE ) { #if ( configUSE_PREEMPTION != 0 ) { @@ -5052,10 +5096,14 @@ BaseType_t xTaskIncrementTick( void ) TickType_t xItemValue; BaseType_t xSwitchRequired = pdFALSE; + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + UBaseType_t uxSavedInterruptStatus; + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + traceENTER_xTaskIncrementTick(); #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - UBaseType_t uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR(); + uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR(); #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ /* Called by the portable layer each time a tick interrupt occurs. @@ -5191,32 +5239,14 @@ BaseType_t xTaskIncrementTick( void ) { #if ( configNUMBER_OF_CORES == 1 ) { - #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - if( pxCurrentTCB->uxPreemptionDisable != 0U ) - { - mtCOVERAGE_TEST_MARKER(); - } - else - { - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #else /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - #endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } #else /* #if ( configNUMBER_OF_CORES == 1 ) */ { @@ -5789,6 +5819,10 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) TCB_t * pxUnblockedTCB; BaseType_t xReturn; + #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) + UBaseType_t uxSavedInterruptStatus; + #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ + traceENTER_xTaskRemoveFromEventList( pxEventList ); #if ( !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) ) @@ -5797,8 +5831,6 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) * called from a critical section within an ISR. */ #else /* #if ( ! ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) ) */ /* Lock the kernel data group as we are about to access its members */ - UBaseType_t uxSavedInterruptStatus; - if( portCHECK_IF_IN_ISR() == pdTRUE ) { uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR(); @@ -7098,9 +7130,7 @@ static void prvResetNextTaskUnblockTime( void ) traceENTER_xTaskPriorityInherit( pxMutexHolder ); - #if ( portUSING_GRANULAR_LOCKS == 1 ) - kernelENTER_CRITICAL(); - #endif + kernelENTER_CRITICAL(); { /* If the mutex is taken by an interrupt, the mutex holder is NULL. Priority * inheritance is not applied in this scenario. */ @@ -7188,9 +7218,7 @@ static void prvResetNextTaskUnblockTime( void ) mtCOVERAGE_TEST_MARKER(); } } - #if ( portUSING_GRANULAR_LOCKS == 1 ) - kernelEXIT_CRITICAL(); - #endif + kernelEXIT_CRITICAL(); traceRETURN_xTaskPriorityInherit( xReturn ); @@ -7499,7 +7527,7 @@ static void prvResetNextTaskUnblockTime( void ) #endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */ /*-----------------------------------------------------------*/ -#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) ) +#if ( configNUMBER_OF_CORES > 1 ) void vTaskEnterCritical( void ) { @@ -7511,11 +7539,24 @@ static void prvResetNextTaskUnblockTime( void ) if( xSchedulerRunning != pdFALSE ) { - if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U ) + /* When using granular locks, the critical section nesting count + * might have already been incremented if this call is a nested + * call from a data group critical section. Hence, we have to + * acquire the kernel task and ISR locks unconditionally. */ + #if ( portUSING_GRANULAR_LOCKS == 1 ) { kernelGET_TASK_LOCK( xCoreID ); kernelGET_ISR_LOCK( xCoreID ); } + #else /* portUSING_GRANULAR_LOCKS */ + { + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U ) + { + kernelGET_TASK_LOCK( xCoreID ); + kernelGET_ISR_LOCK( xCoreID ); + } + } + #endif /* portUSING_GRANULAR_LOCKS */ portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); @@ -7548,56 +7589,7 @@ static void prvResetNextTaskUnblockTime( void ) traceRETURN_vTaskEnterCritical(); } -#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) ) */ -/*-----------------------------------------------------------*/ - -#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) ) - - void vTaskEnterCritical( void ) - { - traceENTER_vTaskEnterCritical(); - - portDISABLE_INTERRUPTS(); - { - const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); - - if( xSchedulerRunning != pdFALSE ) - { - kernelGET_TASK_LOCK( xCoreID ); - kernelGET_ISR_LOCK( xCoreID ); - - portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); - - /* This is not the interrupt safe version of the enter critical - * function so assert() if it is being called from an interrupt - * context. Only API functions that end in "FromISR" can be used in an - * interrupt. Only assert if the critical nesting count is 1 to - * protect against recursive calls if the assert function also uses a - * critical section. */ - if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 1U ) - { - portASSERT_IF_IN_ISR(); - - if( uxSchedulerSuspended == 0U ) - { - /* The only time there would be a problem is if this is called - * before a context switch and vTaskExitCritical() is called - * after pxCurrentTCB changes. Therefore this should not be - * used within vTaskSwitchContext(). */ - prvCheckForRunStateChange(); - } - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - traceRETURN_vTaskEnterCritical(); - } - -#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) ) */ +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /*-----------------------------------------------------------*/ #if ( configNUMBER_OF_CORES > 1 ) @@ -7678,7 +7670,7 @@ static void prvResetNextTaskUnblockTime( void ) #endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */ /*-----------------------------------------------------------*/ -#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) ) +#if ( configNUMBER_OF_CORES > 1 ) void vTaskExitCritical( void ) { @@ -7698,97 +7690,67 @@ static void prvResetNextTaskUnblockTime( void ) if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ) { - portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); - - if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U ) - { - BaseType_t xYieldCurrentTask; - - /* Get the xYieldPending stats inside the critical section. */ - xYieldCurrentTask = xYieldPendings[ xCoreID ]; - - kernelRELEASE_ISR_LOCK( xCoreID ); - kernelRELEASE_TASK_LOCK( xCoreID ); - portENABLE_INTERRUPTS(); - - /* When a task yields in a critical section it just sets - * xYieldPending to true. So now that we have exited the - * critical section check if xYieldPending is true, and - * if so yield. */ - if( xYieldCurrentTask != pdFALSE ) - { - portYIELD(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - traceRETURN_vTaskExitCritical(); - } - -#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) ) */ -/*-----------------------------------------------------------*/ - -#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) ) - - void vTaskExitCritical( void ) - { - const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); - - traceENTER_vTaskExitCritical(); - - if( xSchedulerRunning != pdFALSE ) - { - /* If critical nesting count is zero then this function - * does not match a previous call to vTaskEnterCritical(). */ - configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); - - /* This function should not be called in ISR. Use vTaskExitCriticalFromISR - * to exit critical section from ISR. */ - portASSERT_IF_IN_ISR(); - - if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ) - { - /* Release the ISR and task locks */ - kernelRELEASE_ISR_LOCK( xCoreID ); - kernelRELEASE_TASK_LOCK( xCoreID ); - portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); - - /* If the critical nesting count is 0, enable interrupts */ - if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U ) + #if ( portUSING_GRANULAR_LOCKS == 1 ) { BaseType_t xYieldCurrentTask; /* Get the xYieldPending stats inside the critical section. */ xYieldCurrentTask = xTaskUnlockCanYield(); - portENABLE_INTERRUPTS(); + /* Release the ISR and task locks first when using granular locks. */ + kernelRELEASE_ISR_LOCK( xCoreID ); + kernelRELEASE_TASK_LOCK( xCoreID ); + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); - /* When a task yields in a critical section it just sets - * xYieldPending to true. So now that we have exited the - * critical section check if xYieldPending is true, and - * if so yield. */ - if( xYieldCurrentTask != pdFALSE ) + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U ) { - portYIELD(); + portENABLE_INTERRUPTS(); + + /* When a task yields in a critical section it just sets + * xYieldPending to true. So now that we have exited the + * critical section check if xYieldPending is true, and + * if so yield. */ + if( xYieldCurrentTask != pdFALSE ) + { + portYIELD(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); } } - else + #else /* portUSING_GRANULAR_LOCKS */ { - mtCOVERAGE_TEST_MARKER(); + /* Decrement first; release locks and enable interrupts when count reaches zero. */ + portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); + + if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U ) + { + BaseType_t xYieldCurrentTask; + + /* Get the xYieldPending stats inside the critical section. */ + xYieldCurrentTask = xYieldPendings[ xCoreID ]; + + kernelRELEASE_ISR_LOCK( xCoreID ); + kernelRELEASE_TASK_LOCK( xCoreID ); + portENABLE_INTERRUPTS(); + + /* When a task yields in a critical section it just sets + * xYieldPending to true. So now that we have exited the + * critical section check if xYieldPending is true, and + * if so yield. */ + if( xYieldCurrentTask != pdFALSE ) + { + portYIELD(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } + #endif /* portUSING_GRANULAR_LOCKS */ } else { @@ -7803,7 +7765,7 @@ static void prvResetNextTaskUnblockTime( void ) traceRETURN_vTaskExitCritical(); } -#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) ) */ +#endif /* #if ( configNUMBER_OF_CORES > 1 ) */ /*-----------------------------------------------------------*/ #if ( configNUMBER_OF_CORES > 1 ) @@ -7923,8 +7885,8 @@ static void prvResetNextTaskUnblockTime( void ) if( ( xYieldPendings[ xCoreID ] == pdTRUE ) && ( uxSchedulerSuspended == pdFALSE ) #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) - && ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U ) - && ( pxCurrentTCBs[ xCoreID ]->uxDeferredStateChange == 0U ) + && ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U ) && + ( pxCurrentTCBs[ xCoreID ]->uxDeferredStateChange == 0U ) #endif /* ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ ) { diff --git a/timers.c b/timers.c index 6408b6516..ed5d70982 100644 --- a/timers.c +++ b/timers.c @@ -83,8 +83,8 @@ * Macros to mark the start and end of a critical code region. */ #if ( portUSING_GRANULAR_LOCKS == 1 ) - #define tmrENTER_CRITICAL() taskDATA_GROUP_ENTER_CRITICAL( &xTaskSpinlock, &xISRSpinlock ) - #define tmrEXIT_CRITICAL() taskDATA_GROUP_EXIT_CRITICAL( &xTaskSpinlock, &xISRSpinlock ) + #define tmrENTER_CRITICAL() taskDATA_GROUP_ENTER_CRITICAL( &xTimerTaskSpinlock, &xTimerISRSpinlock ) + #define tmrEXIT_CRITICAL() taskDATA_GROUP_EXIT_CRITICAL( &xTimerTaskSpinlock, &xTimerISRSpinlock ) #else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ #define tmrENTER_CRITICAL() taskENTER_CRITICAL() #define tmrEXIT_CRITICAL() taskEXIT_CRITICAL() @@ -161,8 +161,8 @@ PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) - PRIVILEGED_DATA static portSPINLOCK_TYPE xTaskSpinlock = portINIT_SPINLOCK_STATIC; - PRIVILEGED_DATA static portSPINLOCK_TYPE xISRSpinlock = portINIT_SPINLOCK_STATIC; + PRIVILEGED_DATA static portSPINLOCK_TYPE xTimerTaskSpinlock = portINIT_SPINLOCK_STATIC; + PRIVILEGED_DATA static portSPINLOCK_TYPE xTimerISRSpinlock = portINIT_SPINLOCK_STATIC; #endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */ /*-----------------------------------------------------------*/ @@ -613,7 +613,15 @@ traceENTER_xTimerGetReloadMode( xTimer ); configASSERT( xTimer ); - tmrENTER_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + tmrENTER_CRITICAL(); + } + #else + { + portBASE_TYPE_ENTER_CRITICAL(); + } + #endif { if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U ) { @@ -626,7 +634,15 @@ xReturn = pdTRUE; } } - tmrEXIT_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + tmrEXIT_CRITICAL(); + } + #else + { + portBASE_TYPE_EXIT_CRITICAL(); + } + #endif traceRETURN_xTimerGetReloadMode( xReturn ); @@ -1188,7 +1204,15 @@ configASSERT( xTimer ); /* Is the timer in the list of active timers? */ - tmrENTER_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + tmrENTER_CRITICAL(); + } + #else + { + portBASE_TYPE_ENTER_CRITICAL(); + } + #endif { if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U ) { @@ -1199,7 +1223,15 @@ xReturn = pdTRUE; } } - tmrEXIT_CRITICAL(); + #if ( ( configNUMBER_OF_CORES > 1 ) ) + { + tmrEXIT_CRITICAL(); + } + #else + { + portBASE_TYPE_EXIT_CRITICAL(); + } + #endif traceRETURN_xTimerIsTimerActive( xReturn );