mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-13 16:27:43 -04:00
fix(freertos-smp): Miscellaneous fixes for granular locks
This commit is contained in:
parent
e3d92dd5fd
commit
35025858cf
7 changed files with 302 additions and 359 deletions
|
@ -87,24 +87,6 @@
|
|||
#define event_groupsEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxEventBits ) taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
/*
|
||||
* Locks an event group for tasks. Prevents other tasks from accessing the event group but allows
|
||||
* ISRs to pend access to the event group. Caller cannot be preempted by other tasks
|
||||
* after locking the event group, thus allowing the caller to execute non-deterministic
|
||||
* operations.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static void prvLockEventGroupForTasks( EventGroup_t * pxEventBits ) PRIVILEGED_FUNCTION;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/*
|
||||
* Unlocks an event group for tasks. Handles all pended access from ISRs, then reenables
|
||||
* preemption for the caller.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static BaseType_t prvUnlockEventGroupForTasks( EventGroup_t * pxEventBits ) PRIVILEGED_FUNCTION;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/*
|
||||
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
|
||||
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
|
||||
|
@ -129,8 +111,22 @@
|
|||
* When the task unlocks the event group, all pended access attempts are handled.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#define event_groupsLOCK( pxEventBits ) prvLockEventGroupForTasks( pxEventBits )
|
||||
#define event_groupsUNLOCK( pxEventBits ) prvUnlockEventGroupForTasks( pxEventBits );
|
||||
#define event_groupsLOCK( pxEventBits ) taskDATA_GROUP_LOCK( &( ( pxEventBits )->xTaskSpinlock ) )
|
||||
#define event_groupsUNLOCK( pxEventBits ) \
|
||||
( { \
|
||||
taskDATA_GROUP_UNLOCK( &( ( pxEventBits )->xTaskSpinlock ) ); \
|
||||
BaseType_t xAlreadyYielded; \
|
||||
if( xTaskUnlockCanYield() == pdTRUE ) \
|
||||
{ \
|
||||
taskYIELD_WITHIN_API(); \
|
||||
xAlreadyYielded = pdTRUE; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
xAlreadyYielded = pdFALSE; \
|
||||
} \
|
||||
xAlreadyYielded; \
|
||||
} )
|
||||
#else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
#define event_groupsLOCK( pxEventBits ) vTaskSuspendAll()
|
||||
#define event_groupsUNLOCK( pxEventBits ) xTaskResumeAll()
|
||||
|
@ -867,48 +863,6 @@
|
|||
traceRETURN_vEventGroupClearBitsCallback();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static void prvLockEventGroupForTasks( EventGroup_t * pxEventBits )
|
||||
{
|
||||
/* Disable preemption so that the current task cannot be preempted by another task */
|
||||
vTaskPreemptionDisable( NULL );
|
||||
|
||||
/* Keep holding xTaskSpinlock to prevent tasks on other cores from accessing
|
||||
* the event group while it is suspended. */
|
||||
portGET_SPINLOCK( portGET_CORE_ID(), &( pxEventBits->xTaskSpinlock ) );
|
||||
}
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static BaseType_t prvUnlockEventGroupForTasks( EventGroup_t * pxEventBits )
|
||||
{
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
|
||||
/* Release the previously held task spinlock */
|
||||
portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxEventBits->xTaskSpinlock ) );
|
||||
|
||||
/* Re-enable preemption */
|
||||
vTaskPreemptionEnable( NULL );
|
||||
|
||||
/* Yield if preemption was re-enabled*/
|
||||
if( xTaskUnlockCanYield() == pdTRUE )
|
||||
{
|
||||
taskYIELD_WITHIN_API();
|
||||
|
||||
/* Return true as the task was preempted */
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return false as the task was not preempted */
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -299,11 +299,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 ); \
|
||||
} \
|
||||
|
@ -322,11 +322,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 ) */
|
||||
|
||||
|
@ -339,27 +341,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 */ \
|
||||
vTaskPreemptionEnable( NULL ); \
|
||||
} while( 0 )
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
|
@ -379,7 +381,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 ); \
|
||||
|
@ -387,6 +389,44 @@ typedef enum
|
|||
} while( 0 )
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*
|
||||
* Macros to lock a data group (task-level lock only).
|
||||
*
|
||||
* \defgroup taskDATA_GROUP_LOCK taskDATA_GROUP_LOCK
|
||||
* \ingroup GranularLocks
|
||||
*/
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
#define taskDATA_GROUP_LOCK( pxTaskSpinlock ) \
|
||||
do { \
|
||||
/* Disable preemption while holding the task spinlock. */ \
|
||||
vTaskPreemptionDisable( NULL ); \
|
||||
{ \
|
||||
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \
|
||||
} \
|
||||
} while( 0 )
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*
|
||||
* Macros to unlock a data group (task-level lock only).
|
||||
*
|
||||
* \defgroup taskDATA_GROUP_UNLOCK taskDATA_GROUP_UNLOCK
|
||||
* \ingroup GranularLocks
|
||||
*/
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
#define taskDATA_GROUP_UNLOCK( pxTaskSpinlock ) \
|
||||
do { \
|
||||
{ \
|
||||
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) ( pxTaskSpinlock ) ); \
|
||||
} \
|
||||
/* Re-enable preemption after releasing the task spinlock. */ \
|
||||
vTaskPreemptionEnable( NULL ); \
|
||||
} while( 0 )
|
||||
#endif /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CREATION API
|
||||
*----------------------------------------------------------*/
|
||||
|
|
34
queue.c
34
queue.c
|
@ -328,25 +328,23 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
|
|||
* When the tasks unlocks the queue, all pended access attempts are handled.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#define queueLOCK( pxQueue ) \
|
||||
do { \
|
||||
vTaskPreemptionDisable( NULL ); \
|
||||
prvLockQueue( ( pxQueue ) ); \
|
||||
portGET_SPINLOCK( portGET_CORE_ID(), &( pxQueue->xTaskSpinlock ) ); \
|
||||
#define queueLOCK( pxQueue ) \
|
||||
do { \
|
||||
taskDATA_GROUP_LOCK( &( ( pxQueue )->xTaskSpinlock ) ); \
|
||||
prvLockQueue( ( pxQueue ) ); \
|
||||
} while( 0 )
|
||||
#define queueUNLOCK( pxQueue, xYieldAPI ) \
|
||||
do { \
|
||||
prvUnlockQueue( ( pxQueue ) ); \
|
||||
portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxQueue->xTaskSpinlock ) ); \
|
||||
vTaskPreemptionEnable( NULL ); \
|
||||
if( ( xYieldAPI ) == pdTRUE ) \
|
||||
{ \
|
||||
taskYIELD_WITHIN_API(); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
mtCOVERAGE_TEST_MARKER(); \
|
||||
} \
|
||||
#define queueUNLOCK( pxQueue, xYieldAPI ) \
|
||||
do { \
|
||||
prvUnlockQueue( ( pxQueue ) ); \
|
||||
taskDATA_GROUP_UNLOCK( &( ( pxQueue )->xTaskSpinlock ) ); \
|
||||
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 ) \
|
||||
|
|
|
@ -63,10 +63,10 @@
|
|||
* Macros to mark the start and end of a critical code region.
|
||||
*/
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
#define sbENTER_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_ENTER_CRITICAL( &pxStreamBuffer->xTaskSpinlock, &pxStreamBuffer->xISRSpinlock )
|
||||
#define sbENTER_CRITICAL_FROM_ISR( pxStreamBuffer, puxSavedInterruptStatus ) taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( &pxStreamBuffer->xISRSpinlock, puxSavedInterruptStatus )
|
||||
#define sbEXIT_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL( &pxStreamBuffer->xTaskSpinlock, &pxStreamBuffer->xISRSpinlock )
|
||||
#define sbEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, &pxStreamBuffer->xISRSpinlock )
|
||||
#define sbENTER_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_ENTER_CRITICAL( &( ( pxStreamBuffer )->xTaskSpinlock ), &( ( pxStreamBuffer )->xISRSpinlock ) )
|
||||
#define sbENTER_CRITICAL_FROM_ISR( pxStreamBuffer, puxSavedInterruptStatus ) taskDATA_GROUP_ENTER_CRITICAL_FROM_ISR( &( ( pxStreamBuffer )->xISRSpinlock ), puxSavedInterruptStatus )
|
||||
#define sbEXIT_CRITICAL( pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL( &( ( pxStreamBuffer )->xTaskSpinlock ), &( ( pxStreamBuffer )->xISRSpinlock ) )
|
||||
#define sbEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, pxStreamBuffer ) taskDATA_GROUP_EXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus, &( ( pxStreamBuffer )->xISRSpinlock ) )
|
||||
#else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
#define sbENTER_CRITICAL( pxStreamBuffer ) taskENTER_CRITICAL();
|
||||
#define sbENTER_CRITICAL_FROM_ISR( pxStreamBuffer, puxSavedInterruptStatus ) do { *( puxSavedInterruptStatus ) = taskENTER_CRITICAL_FROM_ISR(); } while( 0 )
|
||||
|
@ -84,8 +84,8 @@
|
|||
* When the task unlocks the stream buffer, all pended access attempts are handled.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
#define sbLOCK( pxStreamBuffer ) prvLockStreamBufferForTasks( pxStreamBuffer )
|
||||
#define sbUNLOCK( pxStreamBuffer ) prvUnlockStreamBufferForTasks( pxStreamBuffer )
|
||||
#define sbLOCK( pxStreamBuffer ) taskDATA_GROUP_LOCK( &( ( pxStreamBuffer )->xTaskSpinlock ) )
|
||||
#define sbUNLOCK( pxStreamBuffer ) taskDATA_GROUP_UNLOCK( &( ( pxStreamBuffer )->xTaskSpinlock ) )
|
||||
#else /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
#define sbLOCK( pxStreamBuffer ) vTaskSuspendAll()
|
||||
#define sbUNLOCK( pxStreamBuffer ) ( void ) xTaskResumeAll()
|
||||
|
@ -109,7 +109,7 @@
|
|||
( pxStreamBuffer )->xTaskWaitingToSend = NULL; \
|
||||
} \
|
||||
} \
|
||||
( void ) sbUNLOCK( pxStreamBuffer ); \
|
||||
sbUNLOCK( pxStreamBuffer ); \
|
||||
} while( 0 )
|
||||
#endif /* sbRECEIVE_COMPLETED */
|
||||
|
||||
|
@ -189,7 +189,7 @@
|
|||
( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \
|
||||
} \
|
||||
} \
|
||||
( void ) sbUNLOCK( pxStreamBuffer )
|
||||
sbUNLOCK( pxStreamBuffer )
|
||||
#endif /* sbSEND_COMPLETED */
|
||||
|
||||
/* If user has provided a per-instance send completed callback, then
|
||||
|
@ -288,24 +288,6 @@ typedef struct StreamBufferDef_t
|
|||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
} StreamBuffer_t;
|
||||
|
||||
/*
|
||||
* Locks a stream buffer for tasks. Prevents other tasks from accessing the stream buffer
|
||||
* but allows ISRs to pend access to the stream buffer. Caller cannot be preempted
|
||||
* by other tasks after locking the stream buffer, thus allowing the caller to
|
||||
* execute non-deterministic operations.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static void prvLockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/*
|
||||
* Unlocks a stream buffer for tasks. Handles all pended access from ISRs, then reenables preemption
|
||||
* for the caller.
|
||||
*/
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static void prvUnlockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/*
|
||||
* The number of bytes available to be read from the buffer.
|
||||
*/
|
||||
|
@ -381,31 +363,6 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer,
|
|||
StreamBufferCallbackFunction_t pxSendCompletedCallback,
|
||||
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static void prvLockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer )
|
||||
{
|
||||
/* Disable preemption so that the current task cannot be preempted by another task */
|
||||
vTaskPreemptionDisable( NULL );
|
||||
|
||||
/* Keep holding xTaskSpinlock after unlocking the data group to prevent tasks
|
||||
* on other cores from accessing the stream buffer while it is suspended. */
|
||||
portGET_SPINLOCK( portGET_CORE_ID(), &( pxStreamBuffer->xTaskSpinlock ) );
|
||||
}
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
static void prvUnlockStreamBufferForTasks( StreamBuffer_t * const pxStreamBuffer )
|
||||
{
|
||||
/* Release the previously held task spinlock */
|
||||
portRELEASE_SPINLOCK( portGET_CORE_ID(), &( pxStreamBuffer->xTaskSpinlock ) );
|
||||
|
||||
/* Re-enable preemption */
|
||||
vTaskPreemptionEnable( NULL );
|
||||
}
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
|
340
tasks.c
340
tasks.c
|
@ -630,6 +630,7 @@ static BaseType_t prvCreateIdleTasks( void );
|
|||
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
||||
|
||||
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
|
||||
|
||||
/*
|
||||
* Checks to see if another task moved the current task out of the ready
|
||||
* list while it was waiting to enter a lightweight critical section and yields, if so.
|
||||
|
@ -971,7 +972,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
#if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 )
|
||||
static void prvLightWeightCheckForRunStateChange( void )
|
||||
{
|
||||
|
||||
const TCB_t * pxThisTCB;
|
||||
BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
|
||||
|
||||
|
@ -1024,8 +1024,8 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
kernelGET_ISR_LOCK( xCoreID );
|
||||
|
||||
portSET_CRITICAL_NESTING_COUNT( xCoreID, uxPrevCriticalNesting );
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* #if ( configLIGHTWEIGHT_CRITICAL_SECTION == 1 ) */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -1096,12 +1096,12 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
xYieldPendings[ xCoreID ] = pdTRUE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
{
|
||||
xLowestPriorityToPreempt = xCurrentCoreTaskPriority;
|
||||
xLowestPriorityCore = xCoreID;
|
||||
}
|
||||
#endif
|
||||
#endif /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1413,12 +1413,12 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
|
|||
xYieldPendings[ uxCore ] = pdTRUE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
{
|
||||
xLowestPriority = xTaskPriority;
|
||||
xLowestPriorityCore = ( BaseType_t ) uxCore;
|
||||
}
|
||||
#endif
|
||||
#endif /* if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2840,7 +2840,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
|
||||
traceENTER_uxTaskPriorityGet( xTask );
|
||||
|
||||
kernelENTER_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
kernelENTER_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_ENTER_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
/* If null is passed in here then it is the priority of the task
|
||||
* that called uxTaskPriorityGet() that is being queried. */
|
||||
|
@ -2849,7 +2857,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
|
||||
uxReturn = pxTCB->uxPriority;
|
||||
}
|
||||
kernelEXIT_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
kernelEXIT_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
|
||||
traceRETURN_uxTaskPriorityGet( uxReturn );
|
||||
|
||||
|
@ -2918,7 +2934,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
|
||||
traceENTER_uxTaskBasePriorityGet( xTask );
|
||||
|
||||
kernelENTER_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
kernelENTER_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_ENTER_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
/* If null is passed in here then it is the base priority of the task
|
||||
* that called uxTaskBasePriorityGet() that is being queried. */
|
||||
|
@ -2927,7 +2951,15 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
|
||||
uxReturn = pxTCB->uxBasePriority;
|
||||
}
|
||||
kernelEXIT_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
kernelEXIT_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
|
||||
traceRETURN_uxTaskBasePriorityGet( uxReturn );
|
||||
|
||||
|
@ -3262,14 +3294,30 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
|
||||
traceENTER_vTaskCoreAffinityGet( xTask );
|
||||
|
||||
kernelENTER_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
kernelENTER_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_ENTER_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
pxTCB = prvGetTCBFromHandle( xTask );
|
||||
configASSERT( pxTCB != NULL );
|
||||
|
||||
uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
|
||||
}
|
||||
kernelEXIT_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
kernelEXIT_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
|
||||
traceRETURN_vTaskCoreAffinityGet( uxCoreAffinityMask );
|
||||
|
||||
|
@ -3351,7 +3399,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
}
|
||||
else
|
||||
{
|
||||
if( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) )
|
||||
if( ( xYieldPendings[ pxTCB->xTaskRunState ] != pdFALSE ) && ( taskTASK_IS_RUNNING( pxTCB ) != pdFALSE ) )
|
||||
{
|
||||
prvYieldCore( pxTCB->xTaskRunState );
|
||||
}
|
||||
|
@ -4443,11 +4491,7 @@ BaseType_t xTaskResumeAll( void )
|
|||
}
|
||||
}
|
||||
|
||||
if( xYieldPendings[ xCoreID ] != pdFALSE
|
||||
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
||||
&& ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U )
|
||||
#endif
|
||||
)
|
||||
if( xYieldPendings[ xCoreID ] != pdFALSE )
|
||||
{
|
||||
#if ( configUSE_PREEMPTION != 0 )
|
||||
{
|
||||
|
@ -5052,10 +5096,14 @@ BaseType_t xTaskIncrementTick( void )
|
|||
TickType_t xItemValue;
|
||||
BaseType_t xSwitchRequired = pdFALSE;
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
UBaseType_t uxSavedInterruptStatus;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
traceENTER_xTaskIncrementTick();
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
UBaseType_t uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR();
|
||||
uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR();
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/* Called by the portable layer each time a tick interrupt occurs.
|
||||
|
@ -5191,32 +5239,14 @@ BaseType_t xTaskIncrementTick( void )
|
|||
{
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
{
|
||||
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
||||
if( pxCurrentTCB->uxPreemptionDisable != 0U )
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
|
||||
{
|
||||
xSwitchRequired = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#else /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
|
||||
{
|
||||
xSwitchRequired = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
#endif /* #if ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1U )
|
||||
{
|
||||
xSwitchRequired = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#else /* #if ( configNUMBER_OF_CORES == 1 ) */
|
||||
{
|
||||
|
@ -5789,6 +5819,10 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
|
|||
TCB_t * pxUnblockedTCB;
|
||||
BaseType_t xReturn;
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
UBaseType_t uxSavedInterruptStatus;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
traceENTER_xTaskRemoveFromEventList( pxEventList );
|
||||
|
||||
#if ( !( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) )
|
||||
|
@ -5797,8 +5831,6 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
|
|||
* called from a critical section within an ISR. */
|
||||
#else /* #if ( ! ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) ) */
|
||||
/* Lock the kernel data group as we are about to access its members */
|
||||
UBaseType_t uxSavedInterruptStatus;
|
||||
|
||||
if( portCHECK_IF_IN_ISR() == pdTRUE )
|
||||
{
|
||||
uxSavedInterruptStatus = kernelENTER_CRITICAL_FROM_ISR();
|
||||
|
@ -7098,9 +7130,7 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
|
||||
traceENTER_xTaskPriorityInherit( pxMutexHolder );
|
||||
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
kernelENTER_CRITICAL();
|
||||
#endif
|
||||
kernelENTER_CRITICAL();
|
||||
{
|
||||
/* If the mutex is taken by an interrupt, the mutex holder is NULL. Priority
|
||||
* inheritance is not applied in this scenario. */
|
||||
|
@ -7188,9 +7218,7 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
kernelEXIT_CRITICAL();
|
||||
#endif
|
||||
kernelEXIT_CRITICAL();
|
||||
|
||||
traceRETURN_xTaskPriorityInherit( xReturn );
|
||||
|
||||
|
@ -7499,7 +7527,7 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
#endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) )
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
||||
void vTaskEnterCritical( void )
|
||||
{
|
||||
|
@ -7511,11 +7539,24 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
|
||||
/* When using granular locks, the critical section nesting count
|
||||
* might have already been incremented if this call is a nested
|
||||
* call from a data group critical section. Hence, we have to
|
||||
* acquire the kernel task and ISR locks unconditionally. */
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
{
|
||||
kernelGET_TASK_LOCK( xCoreID );
|
||||
kernelGET_ISR_LOCK( xCoreID );
|
||||
}
|
||||
#else /* portUSING_GRANULAR_LOCKS */
|
||||
{
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
|
||||
{
|
||||
kernelGET_TASK_LOCK( xCoreID );
|
||||
kernelGET_ISR_LOCK( xCoreID );
|
||||
}
|
||||
}
|
||||
#endif /* portUSING_GRANULAR_LOCKS */
|
||||
|
||||
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
|
||||
|
||||
|
@ -7548,56 +7589,7 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
traceRETURN_vTaskEnterCritical();
|
||||
}
|
||||
|
||||
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) )
|
||||
|
||||
void vTaskEnterCritical( void )
|
||||
{
|
||||
traceENTER_vTaskEnterCritical();
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
kernelGET_TASK_LOCK( xCoreID );
|
||||
kernelGET_ISR_LOCK( xCoreID );
|
||||
|
||||
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
|
||||
|
||||
/* This is not the interrupt safe version of the enter critical
|
||||
* function so assert() if it is being called from an interrupt
|
||||
* context. Only API functions that end in "FromISR" can be used in an
|
||||
* interrupt. Only assert if the critical nesting count is 1 to
|
||||
* protect against recursive calls if the assert function also uses a
|
||||
* critical section. */
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 1U )
|
||||
{
|
||||
portASSERT_IF_IN_ISR();
|
||||
|
||||
if( uxSchedulerSuspended == 0U )
|
||||
{
|
||||
/* The only time there would be a problem is if this is called
|
||||
* before a context switch and vTaskExitCritical() is called
|
||||
* after pxCurrentTCB changes. Therefore this should not be
|
||||
* used within vTaskSwitchContext(). */
|
||||
prvCheckForRunStateChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
traceRETURN_vTaskEnterCritical();
|
||||
}
|
||||
|
||||
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) ) */
|
||||
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
@ -7678,7 +7670,7 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
#endif /* #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) && ( configNUMBER_OF_CORES == 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) )
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
||||
void vTaskExitCritical( void )
|
||||
{
|
||||
|
@ -7698,97 +7690,67 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U )
|
||||
{
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
|
||||
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
|
||||
{
|
||||
BaseType_t xYieldCurrentTask;
|
||||
|
||||
/* Get the xYieldPending stats inside the critical section. */
|
||||
xYieldCurrentTask = xYieldPendings[ xCoreID ];
|
||||
|
||||
kernelRELEASE_ISR_LOCK( xCoreID );
|
||||
kernelRELEASE_TASK_LOCK( xCoreID );
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
/* When a task yields in a critical section it just sets
|
||||
* xYieldPending to true. So now that we have exited the
|
||||
* critical section check if xYieldPending is true, and
|
||||
* if so yield. */
|
||||
if( xYieldCurrentTask != pdFALSE )
|
||||
{
|
||||
portYIELD();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceRETURN_vTaskExitCritical();
|
||||
}
|
||||
|
||||
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS != 1 ) ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) )
|
||||
|
||||
void vTaskExitCritical( void )
|
||||
{
|
||||
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
|
||||
|
||||
traceENTER_vTaskExitCritical();
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
/* If critical nesting count is zero then this function
|
||||
* does not match a previous call to vTaskEnterCritical(). */
|
||||
configASSERT( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U );
|
||||
|
||||
/* This function should not be called in ISR. Use vTaskExitCriticalFromISR
|
||||
* to exit critical section from ISR. */
|
||||
portASSERT_IF_IN_ISR();
|
||||
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) > 0U )
|
||||
{
|
||||
/* Release the ISR and task locks */
|
||||
kernelRELEASE_ISR_LOCK( xCoreID );
|
||||
kernelRELEASE_TASK_LOCK( xCoreID );
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
|
||||
|
||||
/* If the critical nesting count is 0, enable interrupts */
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
{
|
||||
BaseType_t xYieldCurrentTask;
|
||||
|
||||
/* Get the xYieldPending stats inside the critical section. */
|
||||
xYieldCurrentTask = xTaskUnlockCanYield();
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
/* Release the ISR and task locks first when using granular locks. */
|
||||
kernelRELEASE_ISR_LOCK( xCoreID );
|
||||
kernelRELEASE_TASK_LOCK( xCoreID );
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
|
||||
|
||||
/* When a task yields in a critical section it just sets
|
||||
* xYieldPending to true. So now that we have exited the
|
||||
* critical section check if xYieldPending is true, and
|
||||
* if so yield. */
|
||||
if( xYieldCurrentTask != pdFALSE )
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
|
||||
{
|
||||
portYIELD();
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
/* When a task yields in a critical section it just sets
|
||||
* xYieldPending to true. So now that we have exited the
|
||||
* critical section check if xYieldPending is true, and
|
||||
* if so yield. */
|
||||
if( xYieldCurrentTask != pdFALSE )
|
||||
{
|
||||
portYIELD();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
#else /* portUSING_GRANULAR_LOCKS */
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
/* Decrement first; release locks and enable interrupts when count reaches zero. */
|
||||
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
|
||||
|
||||
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0U )
|
||||
{
|
||||
BaseType_t xYieldCurrentTask;
|
||||
|
||||
/* Get the xYieldPending stats inside the critical section. */
|
||||
xYieldCurrentTask = xYieldPendings[ xCoreID ];
|
||||
|
||||
kernelRELEASE_ISR_LOCK( xCoreID );
|
||||
kernelRELEASE_TASK_LOCK( xCoreID );
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
/* When a task yields in a critical section it just sets
|
||||
* xYieldPending to true. So now that we have exited the
|
||||
* critical section check if xYieldPending is true, and
|
||||
* if so yield. */
|
||||
if( xYieldCurrentTask != pdFALSE )
|
||||
{
|
||||
portYIELD();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* portUSING_GRANULAR_LOCKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7803,7 +7765,7 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
traceRETURN_vTaskExitCritical();
|
||||
}
|
||||
|
||||
#endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portUSING_GRANULAR_LOCKS == 1 ) ) */
|
||||
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
@ -7923,8 +7885,8 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
|
||||
if( ( xYieldPendings[ xCoreID ] == pdTRUE ) && ( uxSchedulerSuspended == pdFALSE )
|
||||
#if ( configUSE_TASK_PREEMPTION_DISABLE == 1 )
|
||||
&& ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U )
|
||||
&& ( pxCurrentTCBs[ xCoreID ]->uxDeferredStateChange == 0U )
|
||||
&& ( pxCurrentTCBs[ xCoreID ]->uxPreemptionDisable == 0U ) &&
|
||||
( pxCurrentTCBs[ xCoreID ]->uxDeferredStateChange == 0U )
|
||||
#endif /* ( configUSE_TASK_PREEMPTION_DISABLE == 1 ) */
|
||||
)
|
||||
{
|
||||
|
|
48
timers.c
48
timers.c
|
@ -83,8 +83,8 @@
|
|||
* Macros to mark the start and end of a critical code region.
|
||||
*/
|
||||
#if ( portUSING_GRANULAR_LOCKS == 1 )
|
||||
#define tmrENTER_CRITICAL() taskDATA_GROUP_ENTER_CRITICAL( &xTaskSpinlock, &xISRSpinlock )
|
||||
#define tmrEXIT_CRITICAL() taskDATA_GROUP_EXIT_CRITICAL( &xTaskSpinlock, &xISRSpinlock )
|
||||
#define tmrENTER_CRITICAL() taskDATA_GROUP_ENTER_CRITICAL( &xTimerTaskSpinlock, &xTimerISRSpinlock )
|
||||
#define tmrEXIT_CRITICAL() taskDATA_GROUP_EXIT_CRITICAL( &xTimerTaskSpinlock, &xTimerISRSpinlock )
|
||||
#else /* #if ( portUSING_GRANULAR_LOCKS == 1 ) */
|
||||
#define tmrENTER_CRITICAL() taskENTER_CRITICAL()
|
||||
#define tmrEXIT_CRITICAL() taskEXIT_CRITICAL()
|
||||
|
@ -161,8 +161,8 @@
|
|||
PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
|
||||
|
||||
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||
PRIVILEGED_DATA static portSPINLOCK_TYPE xTaskSpinlock = portINIT_SPINLOCK_STATIC;
|
||||
PRIVILEGED_DATA static portSPINLOCK_TYPE xISRSpinlock = portINIT_SPINLOCK_STATIC;
|
||||
PRIVILEGED_DATA static portSPINLOCK_TYPE xTimerTaskSpinlock = portINIT_SPINLOCK_STATIC;
|
||||
PRIVILEGED_DATA static portSPINLOCK_TYPE xTimerISRSpinlock = portINIT_SPINLOCK_STATIC;
|
||||
#endif /* #if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -613,7 +613,15 @@
|
|||
traceENTER_xTimerGetReloadMode( xTimer );
|
||||
|
||||
configASSERT( xTimer );
|
||||
tmrENTER_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
tmrENTER_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_ENTER_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0U )
|
||||
{
|
||||
|
@ -626,7 +634,15 @@
|
|||
xReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
tmrEXIT_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
tmrEXIT_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
|
||||
traceRETURN_xTimerGetReloadMode( xReturn );
|
||||
|
||||
|
@ -1188,7 +1204,15 @@
|
|||
configASSERT( xTimer );
|
||||
|
||||
/* Is the timer in the list of active timers? */
|
||||
tmrENTER_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
tmrENTER_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_ENTER_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
{
|
||||
if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0U )
|
||||
{
|
||||
|
@ -1199,7 +1223,15 @@
|
|||
xReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
tmrEXIT_CRITICAL();
|
||||
#if ( ( configNUMBER_OF_CORES > 1 ) )
|
||||
{
|
||||
tmrEXIT_CRITICAL();
|
||||
}
|
||||
#else
|
||||
{
|
||||
portBASE_TYPE_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
|
||||
traceRETURN_xTimerIsTimerActive( xReturn );
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue