mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-14 00:37:44 -04:00
feat(freertos-smp): Optimize prvLockQueue() and prvUnlockQueue()
This commit is contained in:
parent
1585b157d5
commit
5098b1ae26
1 changed files with 52 additions and 5 deletions
57
queue.c
57
queue.c
|
@ -287,8 +287,34 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
|
||||||
/*
|
/*
|
||||||
* Macro to mark a queue as locked. Locking a queue prevents an ISR from
|
* Macro to mark a queue as locked. Locking a queue prevents an ISR from
|
||||||
* accessing the queue event lists.
|
* accessing the queue event lists.
|
||||||
|
*
|
||||||
|
* Under granular locks, queueLOCK()/queueUNLOCK() already surround this with
|
||||||
|
* task-level spinlock + preemption-disabled region. To avoid redundant
|
||||||
|
* data-group enter/exit (which would re-disable preemption and re-acquire the
|
||||||
|
* same task spinlock), we minimize to interrupt masking only for the small
|
||||||
|
* metadata updates here. For the non-granular path, retain the full
|
||||||
|
* queueENTER_CRITICAL/queueEXIT_CRITICAL.
|
||||||
*/
|
*/
|
||||||
#define prvLockQueue( pxQueue ) \
|
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||||
|
#define prvLockQueue( pxQueue ) \
|
||||||
|
do { \
|
||||||
|
UBaseType_t ulState = portSET_INTERRUPT_MASK(); \
|
||||||
|
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \
|
||||||
|
{ \
|
||||||
|
if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
|
||||||
|
{ \
|
||||||
|
( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \
|
||||||
|
} \
|
||||||
|
if( ( pxQueue )->cTxLock == queueUNLOCKED ) \
|
||||||
|
{ \
|
||||||
|
( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \
|
||||||
|
portCLEAR_INTERRUPT_MASK( ulState ); \
|
||||||
|
} while( 0 )
|
||||||
|
#else /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||||
|
#define prvLockQueue( pxQueue ) \
|
||||||
queueENTER_CRITICAL( pxQueue ); \
|
queueENTER_CRITICAL( pxQueue ); \
|
||||||
{ \
|
{ \
|
||||||
if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
|
if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
|
||||||
|
@ -301,6 +327,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
queueEXIT_CRITICAL( pxQueue )
|
queueEXIT_CRITICAL( pxQueue )
|
||||||
|
#endif /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macro to increment cTxLock member of the queue data structure. It is
|
* Macro to increment cTxLock member of the queue data structure. It is
|
||||||
|
@ -2538,7 +2565,12 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
|
||||||
* removed from the queue while the queue was locked. When a queue is
|
* removed from the queue while the queue was locked. When a queue is
|
||||||
* locked items can be added or removed, but the event lists cannot be
|
* locked items can be added or removed, but the event lists cannot be
|
||||||
* updated. */
|
* updated. */
|
||||||
queueENTER_CRITICAL( pxQueue );
|
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||||
|
UBaseType_t ulState = portSET_INTERRUPT_MASK();
|
||||||
|
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
|
||||||
|
#else
|
||||||
|
queueENTER_CRITICAL( pxQueue );
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int8_t cTxLock = pxQueue->cTxLock;
|
int8_t cTxLock = pxQueue->cTxLock;
|
||||||
|
|
||||||
|
@ -2616,10 +2648,20 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
|
||||||
|
|
||||||
pxQueue->cTxLock = queueUNLOCKED;
|
pxQueue->cTxLock = queueUNLOCKED;
|
||||||
}
|
}
|
||||||
queueEXIT_CRITICAL( pxQueue );
|
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||||
|
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
|
||||||
|
portCLEAR_INTERRUPT_MASK( ulState );
|
||||||
|
#else
|
||||||
|
queueEXIT_CRITICAL( pxQueue );
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Do the same for the Rx lock. */
|
/* Do the same for the Rx lock. */
|
||||||
queueENTER_CRITICAL( pxQueue );
|
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||||
|
ulState = portSET_INTERRUPT_MASK();
|
||||||
|
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
|
||||||
|
#else
|
||||||
|
queueENTER_CRITICAL( pxQueue );
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int8_t cRxLock = pxQueue->cRxLock;
|
int8_t cRxLock = pxQueue->cRxLock;
|
||||||
|
|
||||||
|
@ -2646,7 +2688,12 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
|
||||||
|
|
||||||
pxQueue->cRxLock = queueUNLOCKED;
|
pxQueue->cRxLock = queueUNLOCKED;
|
||||||
}
|
}
|
||||||
queueEXIT_CRITICAL( pxQueue );
|
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
|
||||||
|
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
|
||||||
|
portCLEAR_INTERRUPT_MASK( ulState );
|
||||||
|
#else
|
||||||
|
queueEXIT_CRITICAL( pxQueue );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue