Calling non-blocking FreeRTOS API functions while scheduler is suspended

The FreeRTOS documentation for vTaskSuspendAll() states "Other FreeRTOS API functions must not be called while the scheduler is suspended. ".

I do not remember this always being the case, and I have always thought it was okay to make FreeRTOS API calls as long as the call does not block. So it would be okay to call something like xQueueSend(), with a block time of 0.

The same question also applies to critical sections, which have the same note in the documentation.

Also note that this rule is broken in stream_buffer.c and the FreeRTOS Plus TCP library.

This is quite a common question so we should really add it to the FAQ. The answer is “it depends”, and writing out the places it is and isn’t ok, and which ports it is and isn’t ok, is a bit of information overload so we instead just make a rule of thumb that says “don’t do it”. The think you absolutely must not do is make an API call that might block when the scheduler is suspended or from inside a critical section - as under those circumstances the task can’t block so you effectively get a logic error (which can result in data corruption, crashes, etc. if you are unlucky). Sending to a queue when the scheduler is suspended may result in a task being unblocked but not being able to run - it will run when the scheduler is resumed, but that means it is running “too late” - so potentially out of specification. Doing the same in a critical section (rather than with the scheduler suspended) can have worse outcomes depending on the port - generally categorized as probably ok if context switches use asynchronous interrupts, and probably not ok if the context switches use synchronous interrupts.

You can see now why we prefer a very simple catch all rule of saying - if you want to be sure your code is safe - don’t do it.

2 Likes