Compare commits

..

11 commits

Author SHA1 Message Date
Sudeep Mohanty 7b73d35554
Merge da5dccf641 into 2615dcde13 2025-05-23 08:08:58 +00:00
Darian Leung da5dccf641 feat(freertos/smp): Add Granular Locking V4 proposal documents
Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 10:08:42 +02:00
Darian Leung cb637b9318 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>
2025-05-23 10:08:42 +02:00
Darian Leung e7773dc7be change(freertos/smp): Update stream_buffer.c locking
Updated stream_buffer.c to use granular locking

- Added xTaskSpinlock and xISRSpinlock
- Replaced critical section macros with data group critical section macros
such as taskENTER/EXIT_CRITICAL/_FROM_ISR() with sbENTER/EXIT_CRITICAL_FROM_ISR().
- Added vStreambuffersEnterCritical/FromISR() and
  vStreambuffersExitCritical/FromISR() to map to the data group critical
section macros.
- Added prvLockStreamBufferForTasks() and prvUnlockStreamBufferForTasks() to suspend the stream
buffer when executing non-deterministic code.

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 10:08:42 +02:00
Darian Leung 030afa1318 change(freertos/smp): Update event_groups.c locking
Updated event_groups.c to use granular locking

- Added xTaskSpinlock and xISRSpinlock
- Replaced critical section macros with data group critical section macros
such as taskENTER/EXIT_CRITICAL/_FROM_ISR() with event_groupsENTER/EXIT_CRITICAL/_FROM_ISR().
- Added vEventGroupsEnterCritical/FromISR() and
  vEventGroupsExitCriti/FromISR() functions that map to the data group
critical section macros.
- Added prvLockEventGroupForTasks() and prvUnlockEventGroupForTasks() to suspend the event
group when executing non-deterministic code.
- xEventGroupSetBits() and vEventGroupDelete() accesses the kernel data group
directly. Thus, added vTaskSuspendAll()/xTaskResumeAll() to these fucntions.

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 10:08:42 +02:00
Darian Leung e87034f74a change(freertos/smp): Update queue.c locking
Updated queue.c to use granular locking

- Added xTaskSpinlock and xISRSpinlock
- Replaced  critical section macros with data group critical section macros
such as taskENTER/EXIT_CRITICAL/_FROM_ISR() with queueENTER/EXIT_CRITICAL_FROM_ISR().
- Added vQueueEnterCritical/FromISR() and vQueueExitCritical/FromISR()
  which map to the data group critical section macros.
- Added prvLockQueueForTasks() and prvUnlockQueueForTasks() as the granular locking equivalents
to prvLockQueue() and prvUnlockQueue() respectively

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 10:08:42 +02:00
Darian Leung bb6b05497f change(freertos/smp): Update tasks.c locking
Updated critical section macros with granular locks.

Some tasks.c API relied on their callers to enter critical sections. This
assumption no longer works under granular locking. Critical sections added to
the following functions:

- `vTaskInternalSetTimeOutState()`
- `xTaskIncrementTick()`
- `vTaskSwitchContext()`
- `xTaskRemoveFromEventList()`
- `vTaskInternalSetTimeOutState()`
- `eTaskConfirmSleepModeStatus()`
- `xTaskPriorityDisinherit()`
- `pvTaskIncrementMutexHeldCount()`

Added missing suspensions to the following functions:

- `vTaskPlaceOnEventList()`
- `vTaskPlaceOnUnorderedEventList()`
- `vTaskPlaceOnEventListRestricted()`

Fixed the locking in vTaskSwitchContext()

vTaskSwitchContext() must aquire both kernel locks, viz., task lock and
ISR lock. This is because, vTaskSwitchContext() can be called from
either task context or ISR context. Also, vTaskSwitchContext() must not
alter the interrupt state prematurely.

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 10:08:42 +02:00
Darian Leung eb7d86f0c3 feat(granular_locks): Add granular locking functions
- Updated prvCheckForRunStateChange() for granular locks
- Updated vTaskSuspendAll() and xTaskResumeAll()
    - Now holds the xTaskSpinlock during kernel suspension
    - Increments/decrements xPreemptionDisable. Only yields when 0, thus allowing
    for nested suspensions across different data groups

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 10:08:35 +02:00
Darian Leung 308d050178 feat(freertos/smp): Add granular locking port macros checks
Adds the required checks for granular locking port macros.

Port Config:

- portUSING_GRANULAR_LOCKS to enable granular locks
- portCRITICAL_NESTING_IN_TCB should be disabled

Granular Locking Port Macros:

- Spinlocks
        - portSPINLOCK_TYPE
        - portINIT_SPINLOCK( pxSpinlock )
        - portINIT_SPINLOCK_STATIC
- Locking
        - portGET_SPINLOCK()
        - portRELEASE_SPINLOCK()

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 08:49:51 +02:00
Darian Leung 94c320c9e2 feat(freertos/smp): Allow vTaskPreemptionEnable() to be nested
Changed xPreemptionDisable to be a count rather than a pdTRUE/pdFALSE. This
allows nested calls to vTaskPreemptionEnable(), where a yield only occurs when
xPreemptionDisable is 0.

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 08:49:51 +02:00
Darian Leung f836da4a8f refactor(freertos/smp): Move critical sections inside xTaskPriorityInherit()
xTaskPriorityInherit() is called inside a critical section from queue.c. This
commit moves the critical section into xTaskPriorityInherit().

Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-05-23 08:49:51 +02:00
3 changed files with 21 additions and 7 deletions

View file

@ -333,6 +333,7 @@ typedef enum
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( ( pxDataGroup )->xISRSpinlock ) ); \
/* Increment the critical nesting count */ \
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
/* Return the previous interrupt status */ \
uxSavedInterruptStatus; \
} )
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
@ -350,6 +351,7 @@ typedef enum
do { \
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); \
/* Decrement the critical nesting count */ \
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \
{ \
@ -382,7 +384,9 @@ typedef enum
do { \
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); \
/* Decrement the critical nesting count */ \
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
/* Release the ISR spinlock */ \
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxDataGroup->xISRSpinlock ) ); \
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \
{ \

View file

@ -339,6 +339,14 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
prvUnlockQueue( ( pxQueue ) ); \
portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxQueue->xTaskSpinlock ) ); \
vTaskPreemptionEnable( NULL ); \
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 ) \

12
tasks.c
View file

@ -5406,11 +5406,13 @@ BaseType_t xTaskIncrementTick( void )
* SMP port. */
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 );
if( uxSchedulerSuspended != ( UBaseType_t ) 0U
/* vTaskSwitchContext() must not be called with a task that has
* preemption disabled. */
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|| ( ( taskTASK_IS_RUNNING( pxCurrentTCBs[ xCoreID ] ) ) && ( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable > 0U ) )
configASSERT( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == 0U );
#endif
)
if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
{
/* The scheduler is currently suspended or the task
* has requested to not be preempted - do not allow
@ -7498,11 +7500,11 @@ static void prvResetNextTaskUnblockTime( void )
BaseType_t xYieldCurrentTask;
/* Get the xYieldPending stats inside the critical section. */
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
#if ( portUSING_GRANULAR_LOCKS == 1 )
xYieldCurrentTask = xTaskUnlockCanYield();
#else
xYieldCurrentTask = xYieldPendings[ xCoreID ];
#endif /* configUSE_TASK_PREEMPTION_DISABLE */
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
kernelRELEASE_ISR_LOCK( xCoreID );
kernelRELEASE_TASK_LOCK( xCoreID );