# Critical section entry/exit - which facility to use where

**URL:** <https://forums.freertos.org/t/critical-section-entry-exit-which-facility-to-use-where/7109>\
**Category:** Kernel\
**Created:** [April 5, 2018, 12:32pm UTC](https://forums.freertos.org/t/critical-section-entry-exit-which-facility-to-use-where/7109 "2018-04-05T12:32:57Z")\
**Posts on this page:** 4\
**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:** [April 5, 2018, 12:32pm UTC](https://forums.freertos.org/t/critical-section-entry-exit-which-facility-to-use-where/7109/1 "2018-04-05T12:32:57Z")

</div>

**[dcrocker](https://sourceforge.net/u/dcrocker/)** wrote on [Thursday, April 05, 2018](https://sourceforge.net/p/freertos/discussion/382005/thread/588ea90a/#b596):

I’m adding protection against multiple tasks accessing/modify mutating data structures (e.g. linked lists) concurrently and I’m wondering what mechanisms it is best practice to use and when. I see the following possibilities:

1. Take and give a recursive mutex.
2. vTaskSuspendAll and xTaskResumeAll. The documentation doesn’t state whether this is recursive, but I can wrap it to make it so if necessary.
3. taskENTER\_CRITICAL and task EXIT\_CRITICAL.
4. cpu\_irq\_save and cpu\_irq\_restore from the ARM Cortex library.

My thinking is along these lines:

- use #4 if the data is access/modified by an ISR with a higher priority than configMAX\_SYSCALL\_INTERRUPT\_PRIORITY;
- use #3 if the data is accessed/modified by an ISR with a priority less than or equal to configMAX\_SYSCALL\_INTERRUPT\_PRIORITY;
- otherwise use #2 if the critical section is short and guaranteed not to block;
- otherwise use #1.

Is that right? Are there any other considerations I shold be aware of?

---

<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:** [April 5, 2018, 4:16pm UTC](https://forums.freertos.org/t/critical-section-entry-exit-which-facility-to-use-where/7109/2 "2018-04-05T16:16:51Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Thursday, April 05, 2018](https://sourceforge.net/p/freertos/discussion/382005/thread/588ea90a/#b596/8b01):

> 1. Take and give a recursive mutex.

Probably a bit heavy for linked list, assuming the linked list is fast.

> 1. vTaskSuspendAll and xTaskResumeAll. The documentation doesn’s state  
> whether this is recursive, but I can wrap it to make it so if necessary.

Yes, this is recursive. Suspending the scheduler is fast and  
deterministic, resuming the scheduler can take longer because, if tasks  
were moved out of the blocked state while the scheduler was suspended  
then they will have been placed into a pending list, and moved from the  
pending list into their respective ready lists when the scheduler is  
resumed. So this method is fast in most cases, but could be slightly  
slower occasionally if tasks are unblocked while the scheduler is  
suspended. Note that suspending the scheduler does NOT mask interrupts,  
they keep executing, so this does not protect the linked list if  
interrupts also access the list. It also means that only interrupts can  
ever move tasks out of the Blocked state (and into the above mentioned  
pending list) while the scheduler is suspended. If non of your  
interrupts can do that then this is a good method.

> 1. taskENTER\_CRITICAL and task EXIT\_CRITICAL.

This is the fastest method - very fast to enter a critical section and  
very fast to exit, so is the ideal method if the section being protected  
is very short. It does however mask interrupts up to  
configMAX\_SYSCALL\_INTERRUPT\_PRIORITY.

> 1. cpu\_irq\_save and cpu\_irq\_restore from the ARM Cortex library.

Would be very wary about using that method if it modifies the BASEPRI  
register as BASEPRI is under the control of FreeRTOS. If it only  
updates the global interrupt enable bit then that should be ok but keep  
in mind it will mask all your interrupts, whereas FreeRTOS critical  
sections only mask some.

Given all the above, I think your statements are basically correct.

---

<div class="post-metadata">

**Author:** ![system](https://d2v6vdsk2p900z.cloudfront.net/original/1X/7fc8fdb729c645aab5b20282bbe34e57cb407be6.jpeg) [@system](https://forums.freertos.org/u/system)\
**Post date:** [April 5, 2018, 5:38pm UTC](https://forums.freertos.org/t/critical-section-entry-exit-which-facility-to-use-where/7109/3 "2018-04-05T17:38:15Z")

</div>

**[dcrocker](https://sourceforge.net/u/dcrocker/)** wrote on [Thursday, April 05, 2018](https://sourceforge.net/p/freertos/discussion/382005/thread/588ea90a/#6d9e):

Barry, thanks for your response. One bit I didn’t quite understand:

> It also means that only interrupts can ever move tasks out of the Blocked state (and into the above mentioned pending list) while the scheduler is suspended. If non of your interrupts can do that then this is a good method.

I do have interrupts that unblock tasks, e.g. when a DMA transfer to/from the SD card interface completes. As I understand it, this doesn’t stop me using vTaskSuspendAll and xTaskResumeAll to implement critical sections. The (only?) drawback is that a task that is unblocked while the scheduler is suspended will have to be moved once to the pending list (when the ISR calls vTaskNotifyGiveFromISR) and then from the pending list to the ready list when xTaskResumeAll is called. So not quite as fast as if it moved direct to the ready list. Is that right?

---

<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:** [April 5, 2018, 6:51pm UTC](https://forums.freertos.org/t/critical-section-entry-exit-which-facility-to-use-where/7109/4 "2018-04-05T18:51:56Z")

</div>

**[rtel](https://sourceforge.net/u/rtel/)** wrote on [Thursday, April 05, 2018](https://sourceforge.net/p/freertos/discussion/382005/thread/588ea90a/#6d9e/5e8a):

Yes, that is right.

The reason I said the only thing that can unblock tasks while the  
scheduler is suspended is interrupts is because, if the scheduler is  
suspended, then no task other than the task that suspended the scheduler  
will ever be running.
