in queue.c there are two implementations of “IsQueueEmpty” as the follows:
~~~
static BaseType
t prvIsQueueEmpty( const Queuet *pxQueue )
{
BaseType_t xReturn;
taskENTER_CRITICAL();
{
if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
}
taskEXIT_CRITICAL();
return xReturn;
}
/
———————————————————–/
BaseType
t xQueueIsQueueEmptyFromISR( const QueueHandlet xQueue )
{
BaseType_t xReturn;
configASSERT( xQueue );
if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
~~~
prvIsQueueEmpty will disable interrupts by taskENTER_CRITICAL and enable interrupts by taskEXIT_CRITICAL, but xQueueIsQueueEmptyFromISR without any protection.
here is my assumption:
1, my system have interrupt being nested, eg, interrupt level 5 will preempt the interrupt level 6.
2, when xQueueIsQueueEmptyFromISR is called in interrupt level 6(low priority), and xQueueGenericSendFromISR being called in interrupt level 5(high priority).
3, when xQueueIsQueueEmptyFromISR execute:
3-1, fetch ( Queue
t * ) xQueue )->uxMessagesWaiting
3-2, do compare if (( Queuet * ) xQueue )->uxMessagesWaiting == 0)
4, if 3-1 is done, but it is preempted by interrupt level 5 which call xQueueGenericSendFromISR which increase the uxMessagesWaiting + 1, but 3-2 is not know this as it have save the value of ( Queue
t * ) xQueue )->uxMessagesWaiting, it is the inconsistent of the value of ( Queuet * ) xQueue )->uxMessagesWaiting.
5, is it a problem and how to avoid it?
my assumption is that xQueueIsQueueEmptyFromISR should add interrupt protection such as portSET
INTERRUPTMASK
FROMISR before it do 3-1 opration