change(freertos/smp): Update timers.c locking

Updated timers.c to use granular locking

- Added xTaskSpinlock and xISRSpinlock
- Replaced critical section macros with data group critical section macros
such as taskENTER/EXIT_CRITICAL() with tmrENTER/EXIT_CRITICAL().
- Added vTimerEnterCritical() and vTimerExitCritical() to map to the
  data group critical section macros.

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
This commit is contained in:
Darian Leung 2024-06-16 01:13:43 +08:00 committed by Sudeep Mohanty
parent 58a5c84990
commit ee2469eb32

115
timers.c
View file

@ -79,6 +79,17 @@
#define tmrSTATUS_IS_STATICALLY_ALLOCATED ( 0x02U ) #define tmrSTATUS_IS_STATICALLY_ALLOCATED ( 0x02U )
#define tmrSTATUS_IS_AUTORELOAD ( 0x04U ) #define tmrSTATUS_IS_AUTORELOAD ( 0x04U )
/*
* Macros to mark the start and end of a critical code region.
*/
#if ( portUSING_GRANULAR_LOCKS == 1 )
#define tmrENTER_CRITICAL() vTimerEnterCritical()
#define tmrEXIT_CRITICAL() vTimerExitCritical()
#else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
#define tmrENTER_CRITICAL() taskENTER_CRITICAL()
#define tmrEXIT_CRITICAL() taskEXIT_CRITICAL()
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
/* The definition of the timers themselves. */ /* The definition of the timers themselves. */
typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */ typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{ {
@ -149,6 +160,25 @@
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; 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;
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
#if ( portUSING_GRANULAR_LOCKS == 1 )
/*
* Enters a critical section for timers. Disables interrupts and takes
* both task and ISR spinlocks to ensure thread safety.
*/
static void vTimerEnterCritical( void ) PRIVILEGED_FUNCTION;
/*
* Exits a critical section for timers. Releases spinlocks in reverse order
* and conditionally re-enables interrupts and yields if required.
*/
static void vTimerExitCritical( void ) PRIVILEGED_FUNCTION;
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -572,7 +602,7 @@
traceENTER_vTimerSetReloadMode( xTimer, xAutoReload ); traceENTER_vTimerSetReloadMode( xTimer, xAutoReload );
configASSERT( xTimer ); configASSERT( xTimer );
taskENTER_CRITICAL(); tmrENTER_CRITICAL();
{ {
if( xAutoReload != pdFALSE ) if( xAutoReload != pdFALSE )
{ {
@ -583,7 +613,7 @@
pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD ); pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD );
} }
} }
taskEXIT_CRITICAL(); tmrEXIT_CRITICAL();
traceRETURN_vTimerSetReloadMode(); traceRETURN_vTimerSetReloadMode();
} }
@ -597,7 +627,7 @@
traceENTER_xTimerGetReloadMode( xTimer ); traceENTER_xTimerGetReloadMode( xTimer );
configASSERT( xTimer ); configASSERT( xTimer );
portBASE_TYPE_ENTER_CRITICAL(); tmrENTER_CRITICAL();
{ {
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U ) if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U )
{ {
@ -610,7 +640,7 @@
xReturn = pdTRUE; xReturn = pdTRUE;
} }
} }
portBASE_TYPE_EXIT_CRITICAL(); tmrEXIT_CRITICAL();
traceRETURN_xTimerGetReloadMode( xReturn ); traceRETURN_xTimerGetReloadMode( xReturn );
@ -1116,7 +1146,7 @@
/* Check that the list from which active timers are referenced, and the /* Check that the list from which active timers are referenced, and the
* queue used to communicate with the timer service, have been * queue used to communicate with the timer service, have been
* initialised. */ * initialised. */
taskENTER_CRITICAL(); tmrENTER_CRITICAL();
{ {
if( xTimerQueue == NULL ) if( xTimerQueue == NULL )
{ {
@ -1158,7 +1188,7 @@
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
} }
taskEXIT_CRITICAL(); tmrEXIT_CRITICAL();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1172,7 +1202,7 @@
configASSERT( xTimer ); configASSERT( xTimer );
/* Is the timer in the list of active timers? */ /* Is the timer in the list of active timers? */
portBASE_TYPE_ENTER_CRITICAL(); tmrENTER_CRITICAL();
{ {
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U ) if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U )
{ {
@ -1183,7 +1213,7 @@
xReturn = pdTRUE; xReturn = pdTRUE;
} }
} }
portBASE_TYPE_EXIT_CRITICAL(); tmrEXIT_CRITICAL();
traceRETURN_xTimerIsTimerActive( xReturn ); traceRETURN_xTimerIsTimerActive( xReturn );
@ -1200,11 +1230,11 @@
configASSERT( xTimer ); configASSERT( xTimer );
taskENTER_CRITICAL(); tmrENTER_CRITICAL();
{ {
pvReturn = pxTimer->pvTimerID; pvReturn = pxTimer->pvTimerID;
} }
taskEXIT_CRITICAL(); tmrEXIT_CRITICAL();
traceRETURN_pvTimerGetTimerID( pvReturn ); traceRETURN_pvTimerGetTimerID( pvReturn );
@ -1221,11 +1251,11 @@
configASSERT( xTimer ); configASSERT( xTimer );
taskENTER_CRITICAL(); tmrENTER_CRITICAL();
{ {
pxTimer->pvTimerID = pvNewID; pxTimer->pvTimerID = pvNewID;
} }
taskEXIT_CRITICAL(); tmrEXIT_CRITICAL();
traceRETURN_vTimerSetTimerID(); traceRETURN_vTimerSetTimerID();
} }
@ -1337,6 +1367,67 @@
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( portUSING_GRANULAR_LOCKS == 1 )
static void vTimerEnterCritical( void )
{
portDISABLE_INTERRUPTS();
{
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
/* Task spinlock is always taken first */
portGET_SPINLOCK( xCoreID, &xTaskSpinlock );
/* Take the ISR spinlock next */
portGET_SPINLOCK( xCoreID, &xISRSpinlock );
/* Increment the critical nesting count */
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
}
}
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
/*-----------------------------------------------------------*/
#if ( portUSING_GRANULAR_LOCKS == 1 )
static void vTimerExitCritical( void )
{
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U );
/* Get the xYieldPending status inside the critical section. */
BaseType_t xYieldCurrentTask = xTaskUnlockCanYield();
/* Decrement the critical nesting count */
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
/* Release the ISR spinlock */
portRELEASE_SPINLOCK( xCoreID, &xISRSpinlock );
/* Release the task spinlock */
portRELEASE_SPINLOCK( xCoreID, &xTaskSpinlock );
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 )
{
portENABLE_INTERRUPTS();
if( xYieldCurrentTask != pdFALSE )
{
portYIELD();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
/*-----------------------------------------------------------*/
/* This entire source file will be skipped if the application is not configured /* This entire source file will be skipped if the application is not configured
* to include software timer functionality. If you want to include software timer * to include software timer functionality. If you want to include software timer
* functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ * functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */