Skip to content

Commit b20d191

Browse files
feat(freertos-smp): Use lock-free increment/decrement for uxPreemptionDisable
1 parent 27151d2 commit b20d191

File tree

1 file changed

+77
-48
lines changed

1 file changed

+77
-48
lines changed

tasks.c

Lines changed: 77 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3286,29 +3286,33 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
32863286

32873287
traceENTER_vTaskPreemptionDisable( xTask );
32883288

3289-
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
3290-
vKernelLightWeightEnterCritical();
3291-
#else
3292-
kernelENTER_CRITICAL();
3293-
#endif
3289+
if( xSchedulerRunning != pdFALSE )
32943290
{
3295-
if( xSchedulerRunning != pdFALSE )
3296-
{
3297-
pxTCB = prvGetTCBFromHandle( xTask );
3298-
configASSERT( pxTCB != NULL );
3291+
pxTCB = prvGetTCBFromHandle( xTask );
3292+
configASSERT( pxTCB != NULL );
32993293

3300-
pxTCB->uxPreemptionDisable++;
3301-
}
3302-
else
3294+
/* Lock-free atomic increment */
3295+
for( ;; )
33033296
{
3304-
mtCOVERAGE_TEST_MARKER();
3297+
UBaseType_t uxOld = pxTCB->uxPreemptionDisable;
3298+
UBaseType_t uxNew = uxOld + ( UBaseType_t ) 1U;
3299+
3300+
if( portCOMPARE_AND_SET( &pxTCB->uxPreemptionDisable, uxOld, uxNew ) )
3301+
{
3302+
/* Success */
3303+
break;
3304+
}
3305+
else
3306+
{
3307+
/* Retry on CAS failure */
3308+
mtCOVERAGE_TEST_MARKER();
3309+
}
33053310
}
33063311
}
3307-
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
3308-
vKernelLightWeightExitCritical();
3309-
#else
3310-
kernelEXIT_CRITICAL();
3311-
#endif
3312+
else
3313+
{
3314+
mtCOVERAGE_TEST_MARKER();
3315+
}
33123316

33133317
traceRETURN_vTaskPreemptionDisable();
33143318
}
@@ -3324,55 +3328,80 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
33243328
UBaseType_t uxDeferredAction = 0U;
33253329
BaseType_t xAlreadyYielded = pdFALSE;
33263330

3327-
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
3328-
vKernelLightWeightEnterCritical();
3329-
#else
3330-
kernelENTER_CRITICAL();
3331-
#endif
3331+
if( xSchedulerRunning != pdFALSE )
33323332
{
3333-
if( xSchedulerRunning != pdFALSE )
3334-
{
3335-
pxTCB = prvGetTCBFromHandle( xTask );
3336-
configASSERT( pxTCB != NULL );
3337-
configASSERT( pxTCB->uxPreemptionDisable > 0U );
3333+
pxTCB = prvGetTCBFromHandle( xTask );
3334+
configASSERT( pxTCB != NULL );
33383335

3339-
pxTCB->uxPreemptionDisable--;
3336+
/* Lock-free atomic decrement with critical section only for final unlock */
3337+
for( ;; )
3338+
{
3339+
UBaseType_t uxOld = pxTCB->uxPreemptionDisable;
3340+
configASSERT( uxOld > 0U );
33403341

3341-
if( pxTCB->uxPreemptionDisable == 0U )
3342+
if( uxOld > 1U )
33423343
{
3343-
if( pxTCB->uxDeferredStateChange != 0U )
3344+
/* Fast path: still nested after decrement, use lock-free atomic operation */
3345+
UBaseType_t uxNew = uxOld - ( UBaseType_t ) 1U;
3346+
if( portCOMPARE_AND_SET( &pxTCB->uxPreemptionDisable, uxOld, uxNew ) )
33443347
{
3345-
uxDeferredAction = pxTCB->uxDeferredStateChange;
3348+
/* Success: still disabled after decrement, no yield coordination needed */
3349+
return pdFALSE;
33463350
}
33473351
else
33483352
{
3349-
if( ( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) )
3353+
/* Retry on CAS failure */
3354+
mtCOVERAGE_TEST_MARKER();
3355+
}
3356+
}
3357+
else /* uxOld == 1U */
3358+
{
3359+
/* Slow path: final unlock (1->0), requires lightweight critical section for coordination */
3360+
vKernelLightWeightEnterCritical();
3361+
{
3362+
UBaseType_t uxCheck = pxTCB->uxPreemptionDisable;
3363+
3364+
if( uxCheck == 1U )
33503365
{
3351-
prvYieldCore( pxTCB->xTaskRunState );
3352-
xAlreadyYielded = pdTRUE;
3366+
pxTCB->uxPreemptionDisable = ( UBaseType_t ) 0U;
3367+
3368+
/* Check for deferred actions and yield coordination */
3369+
if( pxTCB->uxDeferredStateChange != 0U )
3370+
{
3371+
uxDeferredAction = pxTCB->uxDeferredStateChange;
3372+
}
3373+
else
3374+
{
3375+
if( ( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) )
3376+
{
3377+
prvYieldCore( pxTCB->xTaskRunState );
3378+
xAlreadyYielded = pdTRUE;
3379+
}
3380+
else
3381+
{
3382+
mtCOVERAGE_TEST_MARKER();
3383+
}
3384+
}
3385+
3386+
vKernelLightWeightExitCritical();
3387+
break; /* Final unlock complete */
33533388
}
33543389
else
33553390
{
3391+
/* Value changed during critical section acquisition, retry */
33563392
mtCOVERAGE_TEST_MARKER();
33573393
}
33583394
}
3395+
vKernelLightWeightExitCritical();
33593396
}
3360-
else
3361-
{
3362-
mtCOVERAGE_TEST_MARKER();
3363-
}
3364-
}
3365-
else
3366-
{
3367-
mtCOVERAGE_TEST_MARKER();
33683397
}
33693398
}
3370-
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
3371-
vKernelLightWeightExitCritical();
3372-
#else
3373-
kernelEXIT_CRITICAL();
3374-
#endif
3399+
else
3400+
{
3401+
mtCOVERAGE_TEST_MARKER();
3402+
}
33753403

3404+
/* Handle deferred actions outside of critical section */
33763405
if( uxDeferredAction != 0U )
33773406
{
33783407
if( uxDeferredAction & tskDEFERRED_DELETION )

0 commit comments

Comments
 (0)