mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
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:
parent
58a5c84990
commit
ee2469eb32
115
timers.c
115
timers.c
|
@ -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. */
|
||||||
|
|
Loading…
Reference in a new issue