xQueueIsQueueFullFromISR(), nested interrupts

kolodko1 wrote on Thursday, April 15, 2010:

Hi

FreeRTOS 6.3.0.

Question is:

Is such code save on port where nested IRQ are allowed? (for example Cortex-M3)
IRQ could be obviously preempted. The same question is for xQueueIsQueueEmptyFromISR() and general to all family of routines.

========================================================================
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
{
signed portBASE_TYPE xReturn;

xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );

return xReturn;
}

/Best Regards
/Greg K.

kolodko1 wrote on Thursday, April 15, 2010:

mean: save == safe

rtel wrote on Thursday, April 15, 2010:

While other (interrupt safe) queue functions make use of (interrupt safe) critical sections, in this case it was not deemed necessary.  The function in effect returns a Boolean, which is the result of the equality test.  The equality test could be placed in a critical section, but the returned result would still be incorrect if the queue was accessed between the critical section exiting and the function exiting.  In this case nothing would be gained by using the critical section.

Also, nothing in this function actually updates any structures, so there are no non atomic data consistency issues to worry about.

Regards.

kolodko1 wrote on Thursday, April 15, 2010:

Hi

Yep, make sense Richard if return boolean.

But what about if function do not return boolean but valid unsigned number?

=======================================================================================
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
{
unsigned portBASE_TYPE uxReturn;

uxReturn = pxQueue->uxMessagesWaiting;

return uxReturn;
}

rtel wrote on Thursday, April 15, 2010:

I think the same holds true in this case.  The assignment is atomic as it is assigning base type to base type.  The variable is held on the stack, so cannot be corrupted by any other interrupt activity.  If the assignment was in a critical section, then again this would do nothing to prevent the number of items in the queue changing between the critical section exiting and the function exiting.

Regards.

kolodko1 wrote on Thursday, April 15, 2010:

Hi
I think in most cases of ports it will be OK, however your assumption based on

“The assignment is atomic as it is assigning base type to base type”

is not portable because Ansi C standard do not assure this will be atomic and if compiler will take advantage of it, result is undefined. For example could return value bigger than queue can contain messages.
We can be sure atomic execution only using assembly macros.

richard_damon wrote on Thursday, April 15, 2010:

Well, FreeRTOS is not itself a totally portable program, because by its nature, it does things that the standard doesn’t provide guarantees (which is one reason for the large collection of “ports” for it. The key is that it doesn’t need to be portable to any and every implementation, but only to those processor/compiler combination that it supports.

The atomic nature of the base type is one assumption that it makes, and it turns out that it is a reasonable assumption on the platforms that it has been ported. to.

One other thing to point out, is that while functions like isfull may, by them selves, be “safe”, many constructions using them may not, especially something like, check if !full, and if !full, add an item to the queue, has a possibility of failure IF there exists a possibility that something could interrupt the sequence and add an item to the queue, To protect from that, a critical section of some sort would be needed around that whole section. 

kolodko1 wrote on Friday, April 16, 2010:

Hi

Thank you for your respond.
Do not try understand me wrong. I am not going criticise or whatever, I am simply curious boy what tends to perfection.
Always try to contribute such projects and learn new things.

About boolean expression … it is obvious, I completely forgot I use similar method all time, there is not need to any critical section at all :slight_smile:

According incrementing and assumption of atomic assigning.
By “portable” I mean portable in more sense. As I mention compiler is free to do anything, portable means you are secure against every possible compiler with every possible flags options in every port. You do not have to worry and test every possible configuration of optimalization flags and worry about new version of compiler. It is beauty that simply methods secure (if only compiler is OK) to produce 100% correct executable binary. It has another side, if in future you want to port to new architecture, are you going test all similar lines in source code? all time thinking about:
uxReturn = pxQueue->uxMessagesWaiting;
I agree that nowadays in common microcontrolers architecture, port base type seems to be atomic and there is not problems at all, but do not have to be.
I understand compiler and port is always associated considering RTOS. It is only my thoughts and point of view that if something could be close to perfect… why not. Performance (some extra cycles) is not issue nowadays.

Regards