FreeRTOS 原理 --- 临界区(critical section)

发布时间 2023-10-19 23:07:04作者: 流水灯

关调度器

void vTaskSuspendAll( void )
{
    /* A critical section is not required as the variable is of type
    BaseType_t.  Please read Richard Barry's reply in the following link to a
    post in the FreeRTOS support forum before reporting this as a bug! -
    http://goo.gl/wu4acr */
    ++uxSchedulerSuspended;
}

通过一个变量表示是否关调度器,大于0表示关调度器,等于0表示没有关调度器。

关调度器后,不允许主动或被动线程切换(因为关调度器和开调度器是成对出现,如果 delay 主动让出CPU,其他线程没有开调度器操作,delay 时间到也回不去,因为 tick 中断也 bypass 了,无法检查时间到从而切换线程),切换前都会检查是否关了调度器,关状态还主动切换会断言。

如下 delay 主动切换线程

    void vTaskDelay( const TickType_t xTicksToDelay )
    {
    BaseType_t xAlreadyYielded = pdFALSE;

        /* A delay time of zero just forces a reschedule. */
        if( xTicksToDelay > ( TickType_t ) 0U )
        {
            configASSERT( uxSchedulerSuspended == 0 );

如下 tick 中断被动切换线程,如果关调度器,直接 bypass 

BaseType_t xTaskIncrementTick( void )
{
TCB_t * pxTCB;
TickType_t xItemValue;
BaseType_t xSwitchRequired = pdFALSE;

    /* Called by the portable layer each time a tick interrupt occurs.
    Increments the tick then checks to see if the new tick value will cause any
    tasks to be unblocked. */
    traceTASK_INCREMENT_TICK( xTickCount );
    if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
    {
        /* Minor optimisation.  The tick count cannot change in this
        block. */
        const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;

 关中断

如果线程和中断都会修改共同的数据,就需要通过关中断来实现临界区