mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2026-07-10 13:29:45 -04:00
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>
This commit is contained in:
parent
212dcfec1b
commit
62f334a51e
3 changed files with 1093 additions and 634 deletions
|
|
@ -2972,8 +2972,8 @@
|
|||
* portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
|
||||
* the tick count is returned to the standard critical section macros. */
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL_DATA_GROUP( &xTaskSpinlock, &xISRSpinlock )
|
||||
#define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL_DATA_GROUP( &xTaskSpinlock, &xISRSpinlock )
|
||||
#define portTICK_TYPE_ENTER_CRITICAL() kernelENTER_CRITICAL()
|
||||
#define portTICK_TYPE_EXIT_CRITICAL() kernelEXIT_CRITICAL()
|
||||
#else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
#define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL()
|
||||
#define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL()
|
||||
|
|
@ -3242,6 +3242,9 @@ typedef struct xSTATIC_TCB
|
|||
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
||||
UBaseType_t xDummy25;
|
||||
#endif
|
||||
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
||||
BaseType_t xDummy26;
|
||||
#endif
|
||||
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
|
||||
void * pxDummy8;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ typedef enum
|
|||
* \defgroup taskYIELD taskYIELD
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
#define taskYIELD() portYIELD()
|
||||
#define taskYIELD() portYIELD()
|
||||
|
||||
/**
|
||||
* task. h
|
||||
|
|
@ -231,19 +231,12 @@ typedef enum
|
|||
* \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
#define taskENTER_CRITICAL() portENTER_CRITICAL()
|
||||
#define taskENTER_CRITICAL() portENTER_CRITICAL()
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
|
||||
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
|
||||
#else
|
||||
#define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR()
|
||||
#define taskENTER_CRITICAL_FROM_ISR() portENTER_CRITICAL_FROM_ISR()
|
||||
#endif
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#define taskLOCK_DATA_GROUP( pxTaskSpinlock, pxISRSpinlock ) portLOCK_DATA_GROUP( ( portSPINLOCK_TYPE * ) pxTaskSpinlock, ( portSPINLOCK_TYPE * ) pxISRSpinlock )
|
||||
#define taskLOCK_DATA_GROUP_FROM_ISR( pxISRSpinlock ) portLOCK_DATA_GROUP_FROM_ISR( pxISRSpinlock )
|
||||
#else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
#define taskLOCK_DATA_GROUP( pxTaskSpinlock, pxISRSpinlock ) taskENTER_CRITICAL()
|
||||
#define taskLOCK_DATA_GROUP_FROM_ISR( pxISRSpinlock ) taskENTER_CRITICAL_FROM_ISR()
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/**
|
||||
* task. h
|
||||
|
|
@ -257,19 +250,12 @@ typedef enum
|
|||
* \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
|
||||
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
|
||||
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
|
||||
#else
|
||||
#define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x )
|
||||
#define taskEXIT_CRITICAL_FROM_ISR( x ) portEXIT_CRITICAL_FROM_ISR( x )
|
||||
#endif
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#define taskUNLOCK_DATA_GROUP( pxTaskSpinlock, pxISRSpinlock ) portUNLOCK_DATA_GROUP( ( portSPINLOCK_TYPE * ) pxTaskSpinlock, ( portSPINLOCK_TYPE * ) pxISRSpinlock )
|
||||
#define taskUNLOCK_DATA_GROUP_FROM_ISR( x, pxISRSpinlock ) portUNLOCK_DATA_GROUP_FROM_ISR( x, pxISRSpinlock )
|
||||
#else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
#define taskUNLOCK_DATA_GROUP( pxTaskSpinlock, pxISRSpinlock ) taskEXIT_CRITICAL()
|
||||
#define taskUNLOCK_DATA_GROUP_FROM_ISR( x, pxISRSpinlock ) taskEXIT_CRITICAL_FROM_ISR( x )
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/**
|
||||
* task. h
|
||||
|
|
@ -317,11 +303,11 @@ typedef enum
|
|||
{ \
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
|
||||
/* Task spinlock is always taken first */ \
|
||||
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxTaskSpinlock ); \
|
||||
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \
|
||||
/* Disable interrupts */ \
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
/* Take the ISR spinlock next */ \
|
||||
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \
|
||||
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \
|
||||
/* Increment the critical nesting count */ \
|
||||
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
|
||||
} \
|
||||
|
|
@ -340,11 +326,13 @@ typedef enum
|
|||
#define taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( pxISRSpinlock, puxSavedInterruptStatus ) \
|
||||
do { \
|
||||
*( puxSavedInterruptStatus ) = portSET_INTERRUPT_MASK_FROM_ISR(); \
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
|
||||
/* Take the ISR spinlock */ \
|
||||
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \
|
||||
/* Increment the critical nesting count */ \
|
||||
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
|
||||
{ \
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
|
||||
/* Take the ISR spinlock */ \
|
||||
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \
|
||||
/* Increment the critical nesting count */ \
|
||||
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
|
||||
} \
|
||||
} while( 0 )
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
|
|
@ -357,27 +345,27 @@ typedef enum
|
|||
* \ingroup GranularLocks
|
||||
*/
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
#define taskDATA_GROUP_EXIT_CRITICAL( pxTaskSpinlock, pxISRSpinlock ) \
|
||||
do { \
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
|
||||
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); \
|
||||
/* Release the ISR spinlock */ \
|
||||
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \
|
||||
/* Release the task spinlock */ \
|
||||
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxTaskSpinlock ); \
|
||||
/* Decrement the critical nesting count */ \
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
|
||||
/* Enable interrupts only if the critical nesting count is 0 */ \
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
mtCOVERAGE_TEST_MARKER(); \
|
||||
} \
|
||||
/* Re-enable preemption */ \
|
||||
vTaskPreemptionEnable( NULL ); \
|
||||
#define taskDATA_GROUP_EXIT_CRITICAL( pxTaskSpinlock, pxISRSpinlock ) \
|
||||
do { \
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
|
||||
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U ); \
|
||||
/* Release the ISR spinlock */ \
|
||||
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \
|
||||
/* Release the task spinlock */ \
|
||||
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \
|
||||
/* Decrement the critical nesting count */ \
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
|
||||
/* Enable interrupts only if the critical nesting count is 0 */ \
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
mtCOVERAGE_TEST_MARKER(); \
|
||||
} \
|
||||
/* Re-enable preemption */ \
|
||||
prvTaskPreemptionEnable( NULL ); \
|
||||
} while( 0 )
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
|
|
@ -397,7 +385,7 @@ typedef enum
|
|||
/* Decrement the critical nesting count */ \
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
|
||||
/* Release the ISR spinlock */ \
|
||||
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) pxISRSpinlock ); \
|
||||
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) ( pxISRSpinlock ) ); \
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \
|
||||
{ \
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
|
||||
|
|
@ -3897,7 +3885,7 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
|
|||
* It should be used in the implementation of portENTER_CRITICAL if port is running a
|
||||
* multiple core FreeRTOS.
|
||||
*/
|
||||
#if !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) || ( configNUMBER_OF_CORES > 1 ) )
|
||||
void vTaskEnterCritical( void );
|
||||
#endif
|
||||
|
||||
|
|
@ -3909,7 +3897,7 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
|
|||
* It should be used in the implementation of portEXIT_CRITICAL if port is running a
|
||||
* multiple core FreeRTOS.
|
||||
*/
|
||||
#if !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) || ( configNUMBER_OF_CORES > 1 ) )
|
||||
void vTaskExitCritical( void );
|
||||
#endif
|
||||
|
||||
|
|
@ -3919,7 +3907,7 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
|
|||
* should be used in the implementation of portENTER_CRITICAL_FROM_ISR if port is
|
||||
* running a multiple core FreeRTOS.
|
||||
*/
|
||||
#if !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
UBaseType_t vTaskEnterCriticalFromISR( void );
|
||||
#endif
|
||||
|
||||
|
|
@ -3929,12 +3917,12 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
|
|||
* should be used in the implementation of portEXIT_CRITICAL_FROM_ISR if port is
|
||||
* running a multiple core FreeRTOS.
|
||||
*/
|
||||
#if !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Checks whether a yield is required after taskUNLOCK_DATA_GROUP() returns.
|
||||
* Checks whether a yield is required after portUNLOCK_DATA_GROUP() returns.
|
||||
* To be called while data group is locked.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue