Skip to content

Commit f935874

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 68ace34 commit f935874

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
/*
@@ -572,7 +602,7 @@
572602
traceENTER_vTimerSetReloadMode( xTimer, xAutoReload );
573603

574604
configASSERT( xTimer );
575-
taskENTER_CRITICAL();
605+
tmrENTER_CRITICAL();
576606
{
577607
if( xAutoReload != pdFALSE )
578608
{
@@ -583,7 +613,7 @@
583613
pxTimer->ucStatus &= ( ( uint8_t ) ~tmrSTATUS_IS_AUTORELOAD );
584614
}
585615
}
586-
taskEXIT_CRITICAL();
616+
tmrEXIT_CRITICAL();
587617

588618
traceRETURN_vTimerSetReloadMode();
589619
}
@@ -597,7 +627,7 @@
597627
traceENTER_xTimerGetReloadMode( xTimer );
598628

599629
configASSERT( xTimer );
600-
portBASE_TYPE_ENTER_CRITICAL();
630+
tmrENTER_CRITICAL();
601631
{
602632
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U )
603633
{
@@ -610,7 +640,7 @@
610640
xReturn = pdTRUE;
611641
}
612642
}
613-
portBASE_TYPE_EXIT_CRITICAL();
643+
tmrEXIT_CRITICAL();
614644

615645
traceRETURN_xTimerGetReloadMode( xReturn );
616646

@@ -1116,7 +1146,7 @@
11161146
/* Check that the list from which active timers are referenced, and the
11171147
* queue used to communicate with the timer service, have been
11181148
* initialised. */
1119-
taskENTER_CRITICAL();
1149+
tmrENTER_CRITICAL();
11201150
{
11211151
if( xTimerQueue == NULL )
11221152
{
@@ -1158,7 +1188,7 @@
11581188
mtCOVERAGE_TEST_MARKER();
11591189
}
11601190
}
1161-
taskEXIT_CRITICAL();
1191+
tmrEXIT_CRITICAL();
11621192
}
11631193
/*-----------------------------------------------------------*/
11641194

@@ -1172,7 +1202,7 @@
11721202
configASSERT( xTimer );
11731203

11741204
/* Is the timer in the list of active timers? */
1175-
portBASE_TYPE_ENTER_CRITICAL();
1205+
tmrENTER_CRITICAL();
11761206
{
11771207
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U )
11781208
{
@@ -1183,7 +1213,7 @@
11831213
xReturn = pdTRUE;
11841214
}
11851215
}
1186-
portBASE_TYPE_EXIT_CRITICAL();
1216+
tmrEXIT_CRITICAL();
11871217

11881218
traceRETURN_xTimerIsTimerActive( xReturn );
11891219

@@ -1200,11 +1230,11 @@
12001230

12011231
configASSERT( xTimer );
12021232

1203-
taskENTER_CRITICAL();
1233+
tmrENTER_CRITICAL();
12041234
{
12051235
pvReturn = pxTimer->pvTimerID;
12061236
}
1207-
taskEXIT_CRITICAL();
1237+
tmrEXIT_CRITICAL();
12081238

12091239
traceRETURN_pvTimerGetTimerID( pvReturn );
12101240

@@ -1221,11 +1251,11 @@
12211251

12221252
configASSERT( xTimer );
12231253

1224-
taskENTER_CRITICAL();
1254+
tmrENTER_CRITICAL();
12251255
{
12261256
pxTimer->pvTimerID = pvNewID;
12271257
}
1228-
taskEXIT_CRITICAL();
1258+
tmrEXIT_CRITICAL();
12291259

12301260
traceRETURN_vTimerSetTimerID();
12311261
}
@@ -1337,6 +1367,67 @@
13371367
}
13381368
/*-----------------------------------------------------------*/
13391369

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

0 commit comments

Comments
 (0)