Skip to content

Commit 5098b1a

Browse files
feat(freertos-smp): Optimize prvLockQueue() and prvUnlockQueue()
1 parent 1585b15 commit 5098b1a

File tree

1 file changed

+52
-5
lines changed

1 file changed

+52
-5
lines changed

queue.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,34 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
287287
/*
288288
* Macro to mark a queue as locked. Locking a queue prevents an ISR from
289289
* accessing the queue event lists.
290+
*
291+
* Under granular locks, queueLOCK()/queueUNLOCK() already surround this with
292+
* task-level spinlock + preemption-disabled region. To avoid redundant
293+
* data-group enter/exit (which would re-disable preemption and re-acquire the
294+
* same task spinlock), we minimize to interrupt masking only for the small
295+
* metadata updates here. For the non-granular path, retain the full
296+
* queueENTER_CRITICAL/queueEXIT_CRITICAL.
290297
*/
291-
#define prvLockQueue( pxQueue ) \
298+
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
299+
#define prvLockQueue( pxQueue ) \
300+
do { \
301+
UBaseType_t ulState = portSET_INTERRUPT_MASK(); \
302+
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \
303+
{ \
304+
if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
305+
{ \
306+
( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \
307+
} \
308+
if( ( pxQueue )->cTxLock == queueUNLOCKED ) \
309+
{ \
310+
( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \
311+
} \
312+
} \
313+
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \
314+
portCLEAR_INTERRUPT_MASK( ulState ); \
315+
} while( 0 )
316+
#else /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
317+
#define prvLockQueue( pxQueue ) \
292318
queueENTER_CRITICAL( pxQueue ); \
293319
{ \
294320
if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
@@ -301,6 +327,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
301327
} \
302328
} \
303329
queueEXIT_CRITICAL( pxQueue )
330+
#endif /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
304331

305332
/*
306333
* Macro to increment cTxLock member of the queue data structure. It is
@@ -2538,7 +2565,12 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
25382565
* removed from the queue while the queue was locked. When a queue is
25392566
* locked items can be added or removed, but the event lists cannot be
25402567
* updated. */
2541-
queueENTER_CRITICAL( pxQueue );
2568+
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
2569+
UBaseType_t ulState = portSET_INTERRUPT_MASK();
2570+
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2571+
#else
2572+
queueENTER_CRITICAL( pxQueue );
2573+
#endif
25422574
{
25432575
int8_t cTxLock = pxQueue->cTxLock;
25442576

@@ -2616,10 +2648,20 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
26162648

26172649
pxQueue->cTxLock = queueUNLOCKED;
26182650
}
2619-
queueEXIT_CRITICAL( pxQueue );
2651+
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
2652+
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2653+
portCLEAR_INTERRUPT_MASK( ulState );
2654+
#else
2655+
queueEXIT_CRITICAL( pxQueue );
2656+
#endif
26202657

26212658
/* Do the same for the Rx lock. */
2622-
queueENTER_CRITICAL( pxQueue );
2659+
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
2660+
ulState = portSET_INTERRUPT_MASK();
2661+
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2662+
#else
2663+
queueENTER_CRITICAL( pxQueue );
2664+
#endif
26232665
{
26242666
int8_t cRxLock = pxQueue->cRxLock;
26252667

@@ -2646,7 +2688,12 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
26462688

26472689
pxQueue->cRxLock = queueUNLOCKED;
26482690
}
2649-
queueEXIT_CRITICAL( pxQueue );
2691+
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
2692+
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2693+
portCLEAR_INTERRUPT_MASK( ulState );
2694+
#else
2695+
queueEXIT_CRITICAL( pxQueue );
2696+
#endif
26502697
}
26512698
/*-----------------------------------------------------------*/
26522699

0 commit comments

Comments
 (0)