feat(freertos-smp): Create private function for task preemption enable

This commit is contained in:
Sudeep Mohanty 2025-08-19 15:07:19 +02:00
parent 35025858cf
commit 1b14543e7d
2 changed files with 52 additions and 18 deletions

View file

@ -361,7 +361,7 @@ typedef enum
mtCOVERAGE_TEST_MARKER(); \ mtCOVERAGE_TEST_MARKER(); \
} \ } \
/* Re-enable preemption */ \ /* Re-enable preemption */ \
vTaskPreemptionEnable( NULL ); \ prvTaskPreemptionEnable( NULL ); \
} while( 0 ) } while( 0 )
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
@ -417,14 +417,12 @@ typedef enum
* \ingroup GranularLocks * \ingroup GranularLocks
*/ */
#if ( portUSING_GRANULAR_LOCKS == 1 ) #if ( portUSING_GRANULAR_LOCKS == 1 )
#define taskDATA_GROUP_UNLOCK( pxTaskSpinlock ) \ #define taskDATA_GROUP_UNLOCK( pxTaskSpinlock ) \
do { \ ( { \
{ \ portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \ /* Re-enable preemption after releasing the task spinlock. */ \
} \ prvTaskPreemptionEnable( NULL ); \
/* Re-enable preemption after releasing the task spinlock. */ \ } )
vTaskPreemptionEnable( NULL ); \
} while( 0 )
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */ #endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -1627,6 +1625,23 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
void vTaskPreemptionEnable( const TaskHandle_t xTask ); void vTaskPreemptionEnable( const TaskHandle_t xTask );
#endif #endif
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
/*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY
* INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
* AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
*
* @param xTask The handle of the task to enable preemption. Passing NULL
* enables preemption for the calling task.
*
* @return pdTRUE if enabling preemption for the task resulted in a context
* switch, otherwise pdFALSE. This is used by the scheduler to determine if a
* context switch may be required following the enable.
*/
BaseType_t prvTaskPreemptionEnable( const TaskHandle_t xTask );
#endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER CONTROL * SCHEDULER CONTROL
*----------------------------------------------------------*/ *----------------------------------------------------------*/

37
tasks.c
View file

@ -857,6 +857,13 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif /* #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */ #endif /* #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
/*
* Helper function to enable preemption for a task.
*/
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
BaseType_t prvTaskPreemptionEnable( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
/* /*
* freertos_tasks_c_additions_init() should only be called if the user definable * freertos_tasks_c_additions_init() should only be called if the user definable
* macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
@ -1096,7 +1103,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
xYieldPendings[ xCoreID ] = pdTRUE; xYieldPendings[ xCoreID ] = pdTRUE;
} }
} }
#else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ #else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
{ {
xLowestPriorityToPreempt = xCurrentCoreTaskPriority; xLowestPriorityToPreempt = xCurrentCoreTaskPriority;
xLowestPriorityCore = xCoreID; xLowestPriorityCore = xCoreID;
@ -1413,7 +1420,7 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
xYieldPendings[ uxCore ] = pdTRUE; xYieldPendings[ uxCore ] = pdTRUE;
} }
} }
#else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */ #else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
{ {
xLowestPriority = xTaskPriority; xLowestPriority = xTaskPriority;
xLowestPriorityCore = ( BaseType_t ) uxCore; xLowestPriorityCore = ( BaseType_t ) uxCore;
@ -3367,12 +3374,11 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
void vTaskPreemptionEnable( const TaskHandle_t xTask ) BaseType_t prvTaskPreemptionEnable( const TaskHandle_t xTask )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
UBaseType_t uxDeferredAction = 0U; UBaseType_t uxDeferredAction = 0U;
BaseType_t xAlreadyYielded = pdFALSE;
traceENTER_vTaskPreemptionEnable( xTask );
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 ) #if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
vKernelLightWeightEnterCritical(); vKernelLightWeightEnterCritical();
@ -3390,11 +3396,8 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
if( pxTCB->uxPreemptionDisable == 0U ) if( pxTCB->uxPreemptionDisable == 0U )
{ {
/* Process deferred state changes which were inflicted while
* preemption was disabled. */
if( pxTCB->uxDeferredStateChange != 0U ) if( pxTCB->uxDeferredStateChange != 0U )
{ {
/* Capture the deferred action to perform outside critical section */
uxDeferredAction = pxTCB->uxDeferredStateChange; uxDeferredAction = pxTCB->uxDeferredStateChange;
} }
else else
@ -3402,6 +3405,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
if( ( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) ) if( ( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) )
{ {
prvYieldCore( pxTCB->xTaskRunState ); prvYieldCore( pxTCB->xTaskRunState );
xAlreadyYielded = pdTRUE;
} }
else else
{ {
@ -3425,7 +3429,6 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
kernelEXIT_CRITICAL(); kernelEXIT_CRITICAL();
#endif #endif
/* Handle deferred actions outside critical section */
if( uxDeferredAction != 0U ) if( uxDeferredAction != 0U )
{ {
if( uxDeferredAction & tskDEFERRED_DELETION ) if( uxDeferredAction & tskDEFERRED_DELETION )
@ -3440,8 +3443,24 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
{ {
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
/* Any deferred action on the task would result in a context switch. */
xAlreadyYielded = pdTRUE;
} }
return xAlreadyYielded;
}
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
/*-----------------------------------------------------------*/
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
void vTaskPreemptionEnable( const TaskHandle_t xTask )
{
traceENTER_vTaskPreemptionEnable( xTask );
( void ) prvTaskPreemptionEnable( xTask );
traceRETURN_vTaskPreemptionEnable(); traceRETURN_vTaskPreemptionEnable();
} }