Compare commits

..

17 commits

Author SHA1 Message Date
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
Simon Brizard 2615dcde13
fix[IAR/RL78 Port] Compilation fails on portasm.s file (#1278)
The indentation on ASM macro is not authorized by IAR compiler
2025-05-12 21:20:46 +05:30
Archit Gupta 03dc002c9b
Remove formatting bot workflow (#1274) 2025-05-09 14:09:08 -07:00
Gaurav-Aggarwal-AWS e3a0e3e86a
Revert "FreeRTOS SMP: direct access to current TCB inside stack macros (#1270)" (#1272)
This reverts commit 4162ca49d6.
2025-05-05 15:45:15 +05:30
Matth9814 4162ca49d6
FreeRTOS SMP: direct access to current TCB inside stack macros (#1270)
FreeRTOS SMP: direct access to current TCB inside stack macros
2025-04-30 13:12:08 +05:30
Florian La Roche d03233f209
fix warnings from "gcc -Wconversion" (#1271)
fix warnings from "gcc -Wconversion"

Signed-off-by: Florian La Roche <Florian.LaRoche@gmail.com>
2025-04-28 09:51:58 +05:30
Mario Luzeiro 4ee6a1f22f
MPLAB PIC32MZ-EF - Adds an assert to catch register overflow (#1265) (#1267)
Add an assert to catch register overflow (#1265)
2025-04-25 17:05:15 +05:30
arctic-alpaca 03db672b8f
Fix race in POSIX port vPortEndScheduler (#1262)
* Fix race in POSIX port `vPortEndScheduler`

The `vPortEndScheduler` checks whether it's a FreeRTOS thread after signalling the scheduler thread to stop. This creates a race between the check and the destruction of the thread key. By moving the signal to the scheduler thread after the check, the race is prevented.

* Code review suggestions

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>

---------

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
2025-04-03 14:32:44 +05:30
13 changed files with 48 additions and 42 deletions

View file

@ -7,7 +7,7 @@ on:
workflow_dispatch:
jobs:
formatting:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.1
- name: Check Formatting of FreeRTOS-Kernel Files

View file

@ -1,25 +0,0 @@
name: Format Pull Request Files
on:
issue_comment:
types: [created]
env:
bashPass: \033[32;1mPASSED -
bashInfo: \033[33;1mINFO -
bashFail: \033[31;1mFAILED -
bashEnd: \033[0m
jobs:
Formatting:
name: Run Formatting Check
if: ${{ github.event.issue.pull_request &&
( ( github.event.comment.body == '/bot run uncrustify' ) ||
( github.event.comment.body == '/bot run formatting' ) ) }}
runs-on: ubuntu-20.04
steps:
- name: Apply Formatting Fix
id: check-formatting
uses: FreeRTOS/CI-CD-Github-Actions/formatting-bot@main
with:
exclude-dirs: portable

View file

@ -5,7 +5,7 @@ on: [push, pull_request]
jobs:
kernel-checker:
name: FreeRTOS Kernel Header Checks
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
# Install python 3
- name: Tool Setup

View file

@ -3,7 +3,7 @@ on: [push, pull_request]
jobs:
run:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout Parent Repository
uses: actions/checkout@v4.1.1

View file

@ -415,6 +415,8 @@
* number of the failing assert (for example, "vAssertCalled( __FILE__, __LINE__
* )" or it can simple disable interrupts and sit in a loop to halt all
* execution on the failing line for viewing in a debugger. */
/* *INDENT-OFF* */
#define configASSERT( x ) \
if( ( x ) == 0 ) \
{ \
@ -422,6 +424,7 @@
for( ; ; ) \
; \
}
/* *INDENT-ON* */
/******************************************************************************/
/* FreeRTOS MPU specific definitions. *****************************************/

View file

@ -246,7 +246,10 @@ void vCoRoutineSchedule( void );
* \defgroup crSTART crSTART
* \ingroup Tasks
*/
/* *INDENT-OFF* */
#define crEND() }
/* *INDENT-ON* */
/*
* These macros are intended for internal use by the co-routine implementation

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

@ -1059,8 +1059,8 @@
configRUN_TIME_COUNTER_TYPE * pulTotalRunTime ) /* PRIVILEGED_FUNCTION */
{
UBaseType_t uxReturn = 0;
UBaseType_t xIsTaskStatusArrayWriteable = pdFALSE;
UBaseType_t xIsTotalRunTimeWriteable = pdFALSE;
BaseType_t xIsTaskStatusArrayWriteable = pdFALSE;
BaseType_t xIsTotalRunTimeWriteable = pdFALSE;
uint32_t ulArraySize = ( uint32_t ) uxArraySize;
uint32_t ulTaskStatusSize = ( uint32_t ) sizeof( TaskStatus_t );

View file

@ -187,7 +187,7 @@
* ; * memory mode) registers the _usCriticalNesting value and the Stack Pointer
* ; * of the active Task onto the task stack.
* ; *---------------------------------------------------------------------------*/
portSAVE_CONTEXT MACRO
portSAVE_CONTEXT MACRO
PUSH AX; /* Save AX Register to stack. */
PUSH HL
#if __CODE_MODEL__ == __CODE_MODEL_FAR__
@ -217,7 +217,7 @@
* ; * general purpose registers and the CS and ES (only in __far memory mode)
* ; * of the selected task from the task stack.
* ; *---------------------------------------------------------------------------*/
portRESTORE_CONTEXT MACRO
portRESTORE_CONTEXT MACRO
MOVW AX, _pxCurrentTCB; /* Restore the Task stack pointer. */
MOVW HL, AX
MOVW AX, [ HL ]

View file

@ -234,6 +234,11 @@ __attribute__(( weak )) void vApplicationSetupTickTimerInterrupt( void )
{
const uint32_t ulCompareMatch = ( (configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE) / configTICK_RATE_HZ ) - 1UL;
/* PR1 is 16-bit. Ensure that the configPERIPHERAL_CLOCK_HZ and
* configTICK_RATE_HZ are defined such that ulCompareMatch value would fit
* in 16-bits. */
configASSERT( ( ulCompareMatch & 0xFFFF0000 ) == 0 );
T1CON = 0x0000;
T1CONbits.TCKPS = portPRESCALE_BITS;
PR1 = ulCompareMatch;

View file

@ -324,17 +324,23 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
Thread_t * pxCurrentThread;
BaseType_t xIsFreeRTOSThread;
/* Stop the timer tick thread. */
xTimerTickThreadShouldRun = false;
pthread_join( hTimerTickThread, NULL );
/* Check whether the current thread is a FreeRTOS thread.
* This has to happen before the scheduler is signaled to exit
* its loop to prevent data races on the thread key. */
xIsFreeRTOSThread = prvIsFreeRTOSThread();
/* Signal the scheduler to exit its loop. */
xSchedulerEnd = pdTRUE;
( void ) pthread_kill( hMainThread, SIG_RESUME );
/* Waiting to be deleted here. */
if( prvIsFreeRTOSThread() == pdTRUE )
if( xIsFreeRTOSThread == pdTRUE )
{
pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
event_wait( pxCurrentThread->ev );

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 );