Compare commits

..

7 commits

Author SHA1 Message Date
Sudeep Mohanty c3c32afa7a
Merge fb77de7c81 into 0ae0715ac9 2025-06-23 08:29:25 +00:00
Darian Leung fb77de7c81 feat(freertos/smp): Add Granular Locking V4 proposal documents
Co-authored-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>
2025-06-23 10:29:15 +02:00
Darian Leung b8611c970d 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-06-23 10:29:15 +02:00
Darian Leung ca6db799b1 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-06-23 10:29:15 +02:00
Darian Leung a03ce9c287 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-06-23 10:29:15 +02:00
Darian Leung e67f1668e0 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-06-23 10:29:15 +02:00
Darian Leung 21f42e62a5 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-06-23 10:29:07 +02:00

66
tasks.c
View file

@ -461,7 +461,7 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to
#endif
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
BaseType_t xDeferredStateChange; /**< Used to indicate if the task's state change is deferred. */
UBaseType_t uxDeferredStateChange; /**< Used to indicate if the task's state change is deferred. */
#endif
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
@ -2309,7 +2309,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
* task enables preemption. The deletion will be performed in vTaskPreemptionEnable(). */
if( pxTCB->uxPreemptionDisable > 0U )
{
pxTCB->xDeferredStateChange |= tskDEFERRED_DELETION;
pxTCB->uxDeferredStateChange |= tskDEFERRED_DELETION;
xDeferredDeletion = pdTRUE;
}
else
@ -3243,13 +3243,13 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
{
/* Process deferred state changes which were inflicted while
* preemption was disabled. */
if( pxTCB->xDeferredStateChange != 0U )
if( pxTCB->uxDeferredStateChange != 0U )
{
if( pxTCB->xDeferredStateChange & tskDEFERRED_DELETION )
if( pxTCB->uxDeferredStateChange & tskDEFERRED_DELETION )
{
vTaskDelete( xTask );
}
else if( pxTCB->xDeferredStateChange & tskDEFERRED_SUSPENSION )
else if( pxTCB->uxDeferredStateChange & tskDEFERRED_SUSPENSION )
{
vTaskSuspend( xTask );
}
@ -3258,7 +3258,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
mtCOVERAGE_TEST_MARKER();
}
pxTCB->xDeferredStateChange = 0U;
pxTCB->uxDeferredStateChange = 0U;
}
else
{
@ -3315,7 +3315,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
* task enables preemption. The suspension will be performed in vTaskPreemptionEnable(). */
if( pxTCB->uxPreemptionDisable > 0U )
{
pxTCB->xDeferredStateChange |= tskDEFERRED_SUSPENSION;
pxTCB->uxDeferredStateChange |= tskDEFERRED_SUSPENSION;
xDeferredSuspension = pdTRUE;
}
else
@ -3558,6 +3558,10 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
{
TCB_t * const pxTCB = xTaskToResume;
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
BaseType_t xTaskResumed = pdFALSE;
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
traceENTER_vTaskResume( xTaskToResume );
/* It does not make sense to resume the calling task. */
@ -3580,23 +3584,43 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
{
kernelENTER_CRITICAL();
{
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
{
traceTASK_RESUME( pxTCB );
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
/* The ready list can be accessed even if the scheduler is
* suspended because this is inside a critical section. */
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
/* If the task being resumed is in a deferred suspension state,
* we simply clear the deferred suspension state and return. */
if( pxTCB->uxDeferredStateChange & tskDEFERRED_SUSPENSION )
{
pxTCB->uxDeferredStateChange &= ~tskDEFERRED_SUSPENSION;
xTaskResumed = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
#endif /* configUSE_TASK_PREEMPTION_DISABLE */
/* This yield may not cause the task just resumed to run,
* but will leave the lists in the correct state for the
* next yield. */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
}
else
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
if( xTaskResumed == pdFALSE )
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
{
mtCOVERAGE_TEST_MARKER();
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
{
traceTASK_RESUME( pxTCB );
/* The ready list can be accessed even if the scheduler is
* suspended because this is inside a critical section. */
( void ) uxListRemove( &( pxTCB->xStateListItem ) );
prvAddTaskToReadyList( pxTCB );
/* This yield may not cause the task just resumed to run,
* but will leave the lists in the correct state for the
* next yield. */
taskYIELD_ANY_CORE_IF_USING_PREEMPTION( pxTCB );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
kernelEXIT_CRITICAL();