Skip to content

Commit a1cc3bd

Browse files
fix(freertos-smp): Update critical nesting count in prvLock/UnlockQueue
prvLockQueue() and prvUnlockQueue() helper functions now only take the ISR locks because they are always called with the task lock already taken. However, these functions must also increment and decrement the critical nesting count as both locks get taken eventually. This commit fixes it.
1 parent 1b91c54 commit a1cc3bd

File tree

1 file changed

+43
-23
lines changed

1 file changed

+43
-23
lines changed

queue.c

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -296,22 +296,28 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
296296
* queueENTER_CRITICAL/queueEXIT_CRITICAL.
297297
*/
298298
#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 ); \
299+
#define prvLockQueue( pxQueue ) \
300+
do { \
301+
UBaseType_t ulState = portSET_INTERRUPT_MASK(); \
302+
const BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID(); \
303+
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
304+
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \
305+
{ \
306+
if( ( pxQueue )->cRxLock == queueUNLOCKED ) \
307+
{ \
308+
( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \
309+
} \
310+
if( ( pxQueue )->cTxLock == queueUNLOCKED ) \
311+
{ \
312+
( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \
313+
} \
314+
} \
315+
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( ( pxQueue )->xISRSpinlock ) ); \
316+
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ); \
317+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 ) \
318+
{ \
319+
portCLEAR_INTERRUPT_MASK( ulState ); \
320+
} \
315321
} while( 0 )
316322
#else /* if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) ) */
317323
#define prvLockQueue( pxQueue ) \
@@ -2566,8 +2572,10 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
25662572
* locked items can be added or removed, but the event lists cannot be
25672573
* updated. */
25682574
#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 ) );
2575+
portDISABLE_INTERRUPTS();
2576+
BaseType_t xCoreID = ( BaseType_t ) portGET_CORE_ID();
2577+
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
2578+
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
25712579
#else
25722580
queueENTER_CRITICAL( pxQueue );
25732581
#endif
@@ -2650,15 +2658,22 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
26502658
}
26512659
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
26522660
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2653-
portCLEAR_INTERRUPT_MASK( ulState );
2661+
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
2662+
2663+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 )
2664+
{
2665+
portENABLE_INTERRUPTS();
2666+
}
26542667
#else
26552668
queueEXIT_CRITICAL( pxQueue );
26562669
#endif
26572670

26582671
/* Do the same for the Rx lock. */
26592672
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
2660-
ulState = portSET_INTERRUPT_MASK();
2661-
portGET_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2673+
portDISABLE_INTERRUPTS();
2674+
xCoreID = ( BaseType_t ) portGET_CORE_ID();
2675+
portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID );
2676+
portGET_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
26622677
#else
26632678
queueENTER_CRITICAL( pxQueue );
26642679
#endif
@@ -2689,8 +2704,13 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
26892704
pxQueue->cRxLock = queueUNLOCKED;
26902705
}
26912706
#if ( ( portUSING_GRANULAR_LOCKS == 1 ) && ( configNUMBER_OF_CORES > 1 ) )
2692-
portRELEASE_SPINLOCK( portGET_CORE_ID(), ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2693-
portCLEAR_INTERRUPT_MASK( ulState );
2707+
portRELEASE_SPINLOCK( xCoreID, ( portSPINLOCK_TYPE * ) &( pxQueue->xISRSpinlock ) );
2708+
portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID );
2709+
2710+
if( portGET_CRITICAL_NESTING_COUNT( xCoreID ) == 0 )
2711+
{
2712+
portENABLE_INTERRUPTS();
2713+
}
26942714
#else
26952715
queueEXIT_CRITICAL( pxQueue );
26962716
#endif

0 commit comments

Comments
 (0)