# Using Queues in critical sections

**URL:** <https://forums.freertos.org/t/using-queues-in-critical-sections/4660>\
**Category:** Kernel\
**Created:** [June 27, 2012, 10:37am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660 "2012-06-27T10:37:13Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [June 27, 2012, 10:37am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/1 "2012-06-27T10:37:13Z")

</div>

**anonymous** wrote on [Wednesday, June 27, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#f893):

Hi!

Is it possible to use queues in critical sections? Of course it cannot block, but I would like try to read a value from the queue, or return failiure if it is empty. Like receiving with 0 timeout.  
Should the normal Receive() function be used with 0 timeout, or should the ISR version be used?

Regards,  
&nbsp; Ákos Vandra

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [June 27, 2012, 7:44pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/2 "2012-06-27T19:44:23Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Wednesday, June 27, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#80d0):

As a general rule - do not call API functions from critical sections.&nbsp; That said, it might be ok in some situations for some API functions, but it is too complex to analise and document, and therefore too complex for the user, hence the general rule.

I would say, if you want to send or receive in a critical section, then do use the FromISR version.&nbsp; That is quite ok, and as you can’t block, will be faster too.

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 3, 2012, 6:50am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/3 "2012-07-03T06:50:50Z")

</div>

**anonymous** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#956d):

Hi Richard,

Thanks for taking interest in my problem.  
I looked over the code to be executed, and it \*should\* have worked, however I suspect there is a “bug” in the Cortex-M3 port - even though it does not cause a problem if the OS is used “as it should be”. That said, it is still a bug.

The following defines do not behave as they should:

#define portSET\_INTERRUPT\_MASK\_FROM\_ISR() 0;portSET\_INTERRUPT\_MASK()  
#define portCLEAR\_INTERRUPT\_MASK\_FROM\_ISR(x) portCLEAR\_INTERRUPT\_MASK();(void)x

First one always returns 0 as the interrupt mask, second one always clears all interrupts masks, and does not restore the previous state, as it would be logical in the context of xQueueGenericSendFromISR:

signed portBASE\_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void \* const pvItemToQueue, signed portBASE\_TYPE \*pxHigherPriorityTaskWoken, portBASE\_TYPE xCopyPosition )  
{  
signed portBASE\_TYPE xReturn;  
unsigned portBASE\_TYPE uxSavedInterruptStatus;

/\* Similar to xQueueGenericSend, except we don’t block if there is no room  
in the queue.&nbsp; Also we don’t directly wake a task that was blocked on a  
queue read, instead we return a flag to say whether a context switch is  
required or not (i.e. has a task with a higher priority than us been woken  
by this post). \*/  
uxSavedInterruptStatus = portSET\_INTERRUPT\_MASK\_FROM\_ISR();  
{

(…………………)

}  
portCLEAR\_INTERRUPT\_MASK\_FROM\_ISR( uxSavedInterruptStatus );

return xReturn;  
}

Now suppose I have a few interrupts that also need OS API, but have a low priority.  
When one of my functions are meddling with the same peripheral that is used by the ISR, they set mask that interrupt by setting the BASEPRI register (disabling all interrupts below a certain priority). If another interrupt happens at that point that will use queue ISR functions, after returning from the interrupt, my interrupt that should be disabled is not. BANG.

The fix for this problem is quite obvious, but if you like I can create a patch.

Regards,  
&nbsp; Ákos Vandra

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 3, 2012, 8:19am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/4 "2012-07-03T08:19:11Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#ddfd):

> First one always returns 0 as the interrupt mask, second one always clears all interrupts masks, and does not restore the previous state, as it would be logical in the context of xQueueGenericSendFromISR:

The first macro sets the mask to configMAX\_SYSCALL\_INTERRUPT\_PRIORITY.&nbsp; It does not have to return anything on the Cortex-M (see below), but because the macro is used in the core code and therefore its prototype cannot change, it has to conform to the standard prototype for the macro, so just hard codes 0 as the return type.&nbsp; Most compiles will just remove this because the value is not used anywhere.

The second macro lowers the interrupt mask again.&nbsp; It always clears the interrupt mask completely **but** the Cortex-M NVIC is intelligent and will not accept an interrupt that has a priority below the currently executing priority, no matter what its BASEPRI value.&nbsp; Therefore, I believe the macros do actually function as intended.

For example, if an interrupt at a medium priority, and that interrupt makes use of these macros, then BASEPRI will get set to zero.&nbsp; If a low priority interrupt is then set to pending, it will not be accepted by the CPU core even though BASEPRI is zero, because the currently executing interrupt has a medium priority.&nbsp; When the currently executing interrupt completes, the lower priority interrupt will then be accepted and executed.

Always setting the value to zero is an optimisation because it is not necessary to explicitly save and restore the priority mask as it is on most other (every other) processor that has an unintelligent interrupt controller.

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 3, 2012, 1:43pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/5 "2012-07-03T13:43:50Z")

</div>

**anonymous** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#21d6):

Hi!

I’m not sure you understood my scenario. I’ll try to clear it out for you:

1. “A” task is running, doing its job.  
2. “A” task enters some sort of ciritcal-ish section, and sets the NVIC interrupt mask to medium.  
3. “Low priority” interrupt occurs, ignored due to the interrupt mask  
4. “Medium priority” interrupt occurs, uses the mentioned functions, and thus sets the interrupt mask back to 0  
5. Low priority interrupt runs, even though “A” task expects it to be disabled&nbsp; \<- BAD  
6. “A” task gets back the control, and screws up, due to the handled low priority interrupt.

Regards,  
&nbsp; Ákos Vandra

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 3, 2012, 1:56pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/6 "2012-07-03T13:56:41Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#107b):

Ah - ok, now I think I understand.&nbsp; What you are pointing out is that the FromISR functions cannot be used in a task, not that the FromISR functions don’t work in an interrupt.

So the aforementioned macros could be modified to return BASEPRI and set the old BASEPRI, rather than returning and setting 0.&nbsp; Doing that would make the macros take longer to execute, for a scenario which is not really supposed to be done anyway.&nbsp; I’m not sure about including that in the main line code (not ruled it out, just need to think about it).

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 3, 2012, 1:58pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/7 "2012-07-03T13:58:56Z")

</div>

**[axos88](https://sourceforge.net/u/axos88/)** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#6418):

Hi richard,

In the scenario the FromISR functions are called from within the medium interrupt routine, not the task.

Regards,  
&nbsp; Ákos Vandra

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 3, 2012, 2:09pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/8 "2012-07-03T14:09:47Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#147f):

Ok - maybe this still needs some clarification.&nbsp; I will break down your scenario:

> 1. “A” task is running, doing its job.

A good starting point!

> 2. “A” task enters some sort of ciritcal-ish section, and sets the NVIC interrupt mask to medium.

A task entering a critical section should only do so by calling taskENTER\_CRITICAL() / taskEXIT\_CRITICAL().&nbsp; This will set basepri to configMAX\_SYSCALL\_INTERRUPT\_PRIORITY, which prevents any interrupt that can legitimately use the FreeRTOS ISR safe API functions from executing.&nbsp; See: [http://www.freertos.org/RTOS-Cortex-M3-M4.html](http://www.freertos.org/RTOS-Cortex-M3-M4.html)

> 3. “Low priority” interrupt occurs, ignored due to the interrupt mask

So this interrupt has a priority that is masked by configMAX\_SYSCALL\_INTERRUPT\_PRIORITY.

> 4. “Medium priority” interrupt occurs, uses the mentioned functions, and thus sets the interrupt mask back to 0

This is where it breaks down.&nbsp; An interrupt that is not masked by configMAX\_SYSCALL\_INTERRUPT\_PRIORITY must **not** use system calls (FreeRTOS API functions).&nbsp; Therefore, if this scenario really happens, then the application is out of the stated user requirements.

So that leaves the question as to whether it is OK to call the FromISR functions from a task, and the answer is I think as per my original answer - yes it is - but with the caveat that the FromISR function is not itself called from a task level critical section.&nbsp; However, there is another rule that API functions should not be called from critical sections, so that too should never happen.

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 3, 2012, 2:55pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/9 "2012-07-03T14:55:25Z")

</div>

**[axos88](https://sourceforge.net/u/axos88/)** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#469a):

Hi richard.

My medium interrupt priority is lower than the MAX\_SYSCALL\_INTERRUPT\_PRIORITY, thus it should be able to call API functions.  
My low interrupt priority is even lower.

I called it critical-ish section because it does not need to disable all interrupts that are lower than max\_syscall\_priority, it needs to disable only the lower priority interrupt, that’s why it sets the basepri register directly, and expects it not to change until it exits from that section.

So let’s see some numbers, maybe that clarifies.

We have one task, TaskA.  
Two interrupts:  
&nbsp;&nbsp; ItL with priority 25 (higher number denotes lower priority)  
&nbsp;&nbsp; ItM with priority 7  
Max\_SYSCALL is 6.

1. “A” task is running, doing its job.  
2. “A” task enters a section where it needs to disable ItL, but ItM may run without bothering the job, so it’s best if we leave it on, so we may handle that one asap. We set BasePRI to 15.

3. ItL interrupt occurs, ignored due to its priority (25) \> baspri (15)  
4. ItM interrupt occurs, calls xQueueReceiveFromISR, and thus sets the interrupt mask back to 0. It may call the function, as it’s priority is lower than SysCall\_priority.

5. Low priority interrupt runs, bacause BASEPRI was reset. “A” task expects it to be still disabled&nbsp; \<- BAD  
6. “A” task gets back the control, and screws up, due to the handled low priority interrupt.

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 3, 2012, 3:12pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/10 "2012-07-03T15:12:48Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Tuesday, July 03, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#b1e1):

I think I understand the scenario now - and my previous reply is still valid.&nbsp; Your problem is occurring because you are accessing BASEPRI directly, rather than through the kernel using taskENTER\_CRITICAL().&nbsp; The kernel assumes it has control of BASEPRI.

Have you considered just disabling the interrupt for the peripheral you are accessing in the critical-ish section, rather than masking all interrupts up to the syscall value?

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 6, 2012, 8:29am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/11 "2012-07-06T08:29:35Z")

</div>

**anonymous** wrote on [Friday, July 06, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#045f):

Ah, I see. It wasn’t clear for me that accessing the BASEPRI register should be done only through the kernel. Maybe this fact needs mentioning somewhere in the docs?

Your suggestion should work, thanks.

Regards,  
&nbsp; Ákos Vandra

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [July 6, 2012, 8:36am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/12 "2012-07-06T08:36:27Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Friday, July 06, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#c0b0):

> Maybe this fact needs mentioning somewhere in the docs?

See item number 5:  
[http://www.freertos.org/FAQHelp.html](http://www.freertos.org/FAQHelp.html)

Regards.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 6, 2012, 8:38am UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/13 "2012-07-06T08:38:21Z")

</div>

**anonymous** wrote on [Friday, July 06, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#15f8):

Oops, my bad, sorry! :-/

Regards,  
&nbsp; Ákos Vandra

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [July 6, 2012, 11:37pm UTC](https://forums.freertos.org/t/using-queues-in-critical-sections/4660/14 "2012-07-06T23:37:40Z")

</div>

**[pabigot](https://sourceforge.net/u/pabigot/)** wrote on [Friday, July 06, 2012](https://sourceforge.net/p/freertos/discussion/382005/thread/cc08580d/#211e):

The FAQ has:

> Do not use any method for disabling and enabling interrupts other than calls to portENTER\_CRITICAL() and portEXIT\_CRITICAL().

I’ve always found it rather confusing that many of the portX macros have taskX equivalents which are macros that do nothing but invoke the portX one.&nbsp; What’s the recommended practice on selecting which spelling of that functionality should be used in code?&nbsp; Is there any function/macro for which there’s a taskX version that is not equivalent to a portX version (if both exist)?
