Skip to content

Commit a196372

Browse files
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 <[email protected]>
1 parent 32d8176 commit a196372

File tree

1 file changed

+103
-12
lines changed

1 file changed

+103
-12
lines changed

timers.c

+103-12
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@
7979
#define tmrSTATUS_IS_STATICALLY_ALLOCATED ( 0x02U )
8080
#define tmrSTATUS_IS_AUTORELOAD ( 0x04U )
8181

82+
/*
83+
* Macros to mark the start and end of a critical code region.
84+
*/
85+
#if ( portUSING_GRANULAR_LOCKS == 1 )
86+
#define tmrENTER_CRITICAL() vTimerEnterCritical()
87+
#define tmrEXIT_CRITICAL() vTimerExitCritical()
88+
#else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
89+
#define tmrENTER_CRITICAL() taskENTER_CRITICAL()
90+
#define tmrEXIT_CRITICAL() taskEXIT_CRITICAL()
91+
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
92+
8293
/* The definition of the timers themselves. */
8394
typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */
8495
{
@@ -149,6 +160,25 @@
149160
PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
150161
PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
151162

163+
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
164+
PRIVILEGED_DATA static portSPINLOCK_TYPE xTaskSpinlock = portINIT_SPINLOCK_STATIC;
165+
PRIVILEGED_DATA static portSPINLOCK_TYPE xISRSpinlock = portINIT_SPINLOCK_STATIC;
166+
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
167+
168+
#if ( portUSING_GRANULAR_LOCKS == 1 )
169+
170+
/*
171+
* Enters a critical section for timers. Disables interrupts and takes
172+
* both task and ISR spinlocks to ensure thread safety.
173+
*/
174+
static void vTimerEnterCritical( void ) PRIVILEGED_FUNCTION;
175+
176+
/*
177+
* Exits a critical section for timers. Releases spinlocks in reverse order
178+
* and conditionally re-enables interrupts and yields if required.
179+
*/
180+
static void vTimerExitCritical( void ) PRIVILEGED_FUNCTION;
181+
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
152182
/*-----------------------------------------------------------*/
153183

154184
/*
@@ -576,7 +606,7 @@
576606
traceENTER_vTimerSetReloadMode( xTimer, xAutoReload );
577607

578608
configASSERT( xTimer );
579-
taskENTER_CRITICAL();
609+
tmrENTER_CRITICAL();
580610
{
581611
if( xAutoReload != pdFALSE )
582612
{
@@ -587,7 +617,7 @@
587617
pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD );
588618
}
589619
}
590-
taskEXIT_CRITICAL();
620+
tmrEXIT_CRITICAL();
591621

592622
traceRETURN_vTimerSetReloadMode();
593623
}
@@ -601,7 +631,7 @@
601631
traceENTER_xTimerGetReloadMode( xTimer );
602632

603633
configASSERT( xTimer );
604-
portBASE_TYPE_ENTER_CRITICAL();
634+
tmrENTER_CRITICAL();
605635
{
606636
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U )
607637
{
@@ -614,7 +644,7 @@
614644
xReturn = pdTRUE;
615645
}
616646
}
617-
portBASE_TYPE_EXIT_CRITICAL();
647+
tmrEXIT_CRITICAL();
618648

619649
traceRETURN_xTimerGetReloadMode( xReturn );
620650

@@ -1113,7 +1143,7 @@
11131143
/* Check that the list from which active timers are referenced, and the
11141144
* queue used to communicate with the timer service, have been
11151145
* initialised. */
1116-
taskENTER_CRITICAL();
1146+
tmrENTER_CRITICAL();
11171147
{
11181148
if( xTimerQueue == NULL )
11191149
{
@@ -1155,7 +1185,7 @@
11551185
mtCOVERAGE_TEST_MARKER();
11561186
}
11571187
}
1158-
taskEXIT_CRITICAL();
1188+
tmrEXIT_CRITICAL();
11591189
}
11601190
/*-----------------------------------------------------------*/
11611191

@@ -1169,7 +1199,7 @@
11691199
configASSERT( xTimer );
11701200

11711201
/* Is the timer in the list of active timers? */
1172-
portBASE_TYPE_ENTER_CRITICAL();
1202+
tmrENTER_CRITICAL();
11731203
{
11741204
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U )
11751205
{
@@ -1180,7 +1210,7 @@
11801210
xReturn = pdTRUE;
11811211
}
11821212
}
1183-
portBASE_TYPE_EXIT_CRITICAL();
1213+
tmrEXIT_CRITICAL();
11841214

11851215
traceRETURN_xTimerIsTimerActive( xReturn );
11861216

@@ -1197,11 +1227,11 @@
11971227

11981228
configASSERT( xTimer );
11991229

1200-
taskENTER_CRITICAL();
1230+
tmrENTER_CRITICAL();
12011231
{
12021232
pvReturn = pxTimer->pvTimerID;
12031233
}
1204-
taskEXIT_CRITICAL();
1234+
tmrEXIT_CRITICAL();
12051235

12061236
traceRETURN_pvTimerGetTimerID( pvReturn );
12071237

@@ -1218,11 +1248,11 @@
12181248

12191249
configASSERT( xTimer );
12201250

1221-
taskENTER_CRITICAL();
1251+
tmrENTER_CRITICAL();
12221252
{
12231253
pxTimer->pvTimerID = pvNewID;
12241254
}
1225-
taskEXIT_CRITICAL();
1255+
tmrEXIT_CRITICAL();
12261256

12271257
traceRETURN_vTimerSetTimerID();
12281258
}
@@ -1334,6 +1364,67 @@
13341364
}
13351365
/*-----------------------------------------------------------*/
13361366

1367+
#if ( portUSING_GRANULAR_LOCKS == 1 )
1368+
static void vTimerEnterCritical( void )
1369+
{
1370+
portDISABLE_INTERRUPTS();
1371+
{
1372+
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
1373+
1374+
/* Task spinlock is always taken first */
1375+
portGET_SPINLOCK( xCoreID, &xTaskSpinlock );
1376+
1377+
/* Take the ISR spinlock next */
1378+
portGET_SPINLOCK( xCoreID, &xISRSpinlock );
1379+
1380+
/* Increment the critical nesting count */
1381+
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
1382+
}
1383+
}
1384+
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
1385+
1386+
/*-----------------------------------------------------------*/
1387+
1388+
#if ( portUSING_GRANULAR_LOCKS == 1 )
1389+
static void vTimerExitCritical( void )
1390+
{
1391+
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
1392+
1393+
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U );
1394+
1395+
/* Get the xYieldPending status inside the critical section. */
1396+
BaseType_t xYieldCurrentTask = xTaskUnlockCanYield();
1397+
1398+
/* Decrement the critical nesting count */
1399+
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
1400+
1401+
/* Release the ISR spinlock */
1402+
portRELEASE_SPINLOCK( xCoreID, &xISRSpinlock );
1403+
1404+
/* Release the task spinlock */
1405+
portRELEASE_SPINLOCK( xCoreID, &xTaskSpinlock );
1406+
1407+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 )
1408+
{
1409+
portENABLE_INTERRUPTS();
1410+
1411+
if( xYieldCurrentTask != pdFALSE )
1412+
{
1413+
portYIELD();
1414+
}
1415+
else
1416+
{
1417+
mtCOVERAGE_TEST_MARKER();
1418+
}
1419+
}
1420+
else
1421+
{
1422+
mtCOVERAGE_TEST_MARKER();
1423+
}
1424+
}
1425+
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
1426+
/*-----------------------------------------------------------*/
1427+
13371428
/* This entire source file will be skipped if the application is not configured
13381429
* to include software timer functionality. If you want to include software timer
13391430
* functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */

0 commit comments

Comments
 (0)