taskENTER_CRITICAL() vs vTaskSuspendAll()

ivernot wrote on Wednesday, July 09, 2008:

Hello,
I am writing code that will be used by several threads (a circular buffer module) so I need to protect a few lines of ‘critical section’ code.

My question is which method (ie taskENTER_CRITICAL() vs vTaskSuspendAll()) is ‘preferred’
My ‘requiremnets’ are
1. minimum blocking of interrupts…
2. minimum execution time of the chosen enter/exit fuctions

The module will not be used in ISRs so does not need to be protected from interrupts - in fact, I would prefer that interrupts continue to run while I am in the critical section.

I have looked through the documentation of the FreeRTOS web site but found no mention of which method is prefered & when.

Thank you in advance.

Ivan Vernot

rtel wrote on Wednesday, July 09, 2008:

Critical sections:  Sledge hammer approach that is very quick to enter and exit, but crude in implementation as it just disables interrupts.  The effect of disabling interrupts depends on the port being used.  Some disable interrupts globally, some mask to a certain level only.  This is the best method to use the section of code being protected is very short, a few lines.  Critical sections protect against other tasks accessing the protected data and against interrupts accessing the protected data.

Scheduler locking:  More elegant, but only protects against other tasks accessing the protected data.  Very quick to enter but can take longer to exit if there are lots of tasks move out of the blocked state while the scheduler was locked (by interrupts operating while the scheduler is locked) or if lots of tick interrupts are occur while the scheduler was locked - in either of these two cases a critical section is used in the unlock while the clean up is done so you can end up with interrupts disabled for a while anyway.  Scheduler locking is best when the region requiring protection is longer, with the caveat that unlocking is complex if lots are tasks become unblocked while the scheduler is locked.

Regards.

vinay1 wrote on Tuesday, July 22, 2008:

In addition to what richard has said:

if no protection from ISRs is required, you should use "vTaskSuspendAll()", as the taskENTER_CRITICAL() is also #defined to "vPortEnterCritical()", which only disable interrupts:

void vPortEnterCritical( void )
{
    /* Disable interrupts first! */
    portDISABLE_INTERRUPTS();

    /* Now interrupts are disabled ulCriticalNesting can be accessed
    directly.  Increment ulCriticalNesting to keep a count of how many times
    portENTER_CRITICAL() has been called. */
    ulCriticalNesting++;
}
regards
vinay