Skip to content

Commit f46aaa7

Browse files
feat(freertos-smp): Reintroduce Light Weight Critical Sections
1 parent fbd37a2 commit f46aaa7

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

include/FreeRTOS.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2966,6 +2966,10 @@
29662966
#error configUSE_PORT_OPTIMISED_TASK_SELECTION is not supported in SMP FreeRTOS
29672967
#endif
29682968

2969+
#ifndef configLIGHTWEIGHT_CRITICAL_SECTION
2970+
#define configLIGHTWEIGHT_CRITICAL_SECTION 0
2971+
#endif
2972+
29692973
#ifndef configINITIAL_TICK_COUNT
29702974
#define configINITIAL_TICK_COUNT 0
29712975
#endif

include/task.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3933,6 +3933,22 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
39333933
void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
39343934
#endif
39353935

3936+
/*
3937+
* This function is only intended for use when disabling or enabling preemption of a task.
3938+
* This function takes only the kernel ISR lock, not the task lock.
3939+
*/
3940+
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
3941+
void vKernelLightWeightEnterCritical( void );
3942+
#endif
3943+
3944+
/*
3945+
* This function is only intended for use when disabling or enabling preemption of a task.
3946+
* This function releases only the kernel ISR lock, not the task lock.
3947+
*/
3948+
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
3949+
void vKernelLightWeightExitCritical( void );
3950+
#endif
3951+
39363952
#if ( portUSING_MPU_WRAPPERS == 1 )
39373953

39383954
/*

tasks.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,14 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
854854
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
855855
#endif /* #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
856856

857+
/* Lightweight critical section helpers (re-introduced) */
858+
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
859+
860+
/* Checks to see if another task moved the current task out of the ready
861+
* list while it was waiting to enter a lightweight critical section and yields, if so. */
862+
static void prvLightWeightCheckForRunStateChange( void );
863+
#endif
864+
857865
/*
858866
* Helper function to enable preemption for a task.
859867
*/
@@ -7779,6 +7787,112 @@ static void prvResetNextTaskUnblockTime( void )
77797787
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
77807788
/*-----------------------------------------------------------*/
77817789

7790+
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
7791+
7792+
static void prvLightWeightCheckForRunStateChange( void )
7793+
{
7794+
const TCB_t * pxThisTCB;
7795+
BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
7796+
7797+
/* Must not be called from ISR context. */
7798+
portASSERT_IF_IN_ISR();
7799+
7800+
/* Called with interrupts disabled. Safe to read pxCurrentTCBs. */
7801+
pxThisTCB = pxCurrentTCBs[ xCoreID ];
7802+
7803+
while( pxThisTCB->xTaskRunState == taskTASK_SCHEDULED_TO_YIELD )
7804+
{
7805+
UBaseType_t uxPrevCriticalNesting;
7806+
7807+
/* Save nesting and temporarily release ISR lock if needed to service pending IPI. */
7808+
uxPrevCriticalNesting = portGET_CRITICAL_NESTING_COUNT( xCoreID );
7809+
7810+
if( uxPrevCriticalNesting > 0U )
7811+
{
7812+
portSET_CRITICAL_NESTING_COUNT( xCoreID, 0U );
7813+
kernelRELEASE_ISR_LOCK( xCoreID );
7814+
}
7815+
7816+
portMEMORY_BARRIER();
7817+
7818+
/* Allow the core to service pending yield interrupt. */
7819+
portENABLE_INTERRUPTS();
7820+
portDISABLE_INTERRUPTS();
7821+
7822+
/* Reacquire ISR lock and restore nesting; re-evaluate run state. */
7823+
xCoreID = ( BaseType_t ) portGET_CORE_ID();
7824+
kernelGET_ISR_LOCK( xCoreID );
7825+
portSET_CRITICAL_NESTING_COUNT( xCoreID, uxPrevCriticalNesting );
7826+
pxThisTCB = pxCurrentTCBs[ xCoreID ];
7827+
}
7828+
}
7829+
7830+
void vKernelLightWeightEnterCritical( void )
7831+
{
7832+
if( xSchedulerRunning != pdFALSE )
7833+
{
7834+
portDISABLE_INTERRUPTS();
7835+
{
7836+
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
7837+
7838+
/* Take only the ISR lock, not the task lock. */
7839+
kernelGET_ISR_LOCK( xCoreID );
7840+
7841+
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
7842+
7843+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 1U )
7844+
{
7845+
prvLightWeightCheckForRunStateChange();
7846+
}
7847+
}
7848+
}
7849+
}
7850+
7851+
void vKernelLightWeightExitCritical( void )
7852+
{
7853+
if( xSchedulerRunning != pdFALSE )
7854+
{
7855+
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
7856+
7857+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U )
7858+
{
7859+
BaseType_t xYieldCurrentTask;
7860+
7861+
if( ( xYieldPendings[ xCoreID ] == pdTRUE ) && ( uxSchedulerSuspended == pdFALSE )
7862+
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
7863+
&& ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U ) &&
7864+
( pxCurrentTCBs[ xCoreID ]->uxDeferredStateChange == 0U )
7865+
#endif
7866+
)
7867+
{
7868+
xYieldCurrentTask = pdTRUE;
7869+
}
7870+
else
7871+
{
7872+
xYieldCurrentTask = pdFALSE;
7873+
}
7874+
7875+
/* Release only the ISR lock. */
7876+
kernelRELEASE_ISR_LOCK( xCoreID );
7877+
7878+
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
7879+
7880+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
7881+
{
7882+
portENABLE_INTERRUPTS();
7883+
7884+
if( xYieldCurrentTask != pdFALSE )
7885+
{
7886+
portYIELD();
7887+
}
7888+
}
7889+
}
7890+
}
7891+
}
7892+
7893+
#endif /* configLIGHTWEIGHT_CRITICAL_SECTION == 1 */
7894+
/*-----------------------------------------------------------*/
7895+
77827896
#if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
77837897

77847898
static char * prvWriteNameToBuffer( char * pcBuffer,

0 commit comments

Comments
 (0)