vTaskSuspendAll和xTaskResumeAll

来源:互联网 发布:贵阳大数据是什么 编辑:程序博客网 时间:2024/05/01 00:11

这是一种同步机制,比关中断要温和点。禁止调度由
vTaskSuspendAll实现,打开调度由xTaskResumeAll实现。
void vTaskSuspendAll( void )
{
    portENTER_CRITICAL();
        ++uxSchedulerSuspended;
    portEXIT_CRITICAL();
}
这个很简单,系统维护一个计数uxSchedulerSuspended,当它大于0时候表示禁止调度,等于0则打开调度(允许调度)。
signed portBASE_TYPE xTaskResumeAll( void )
{
register tskTCB *pxTCB;
signed portBASE_TYPE xAlreadyYielded = pdFALSE;
 
    /* It is possible that an ISR caused a task to be removed from an event
    list while the scheduler was suspended.  If this was the case then the
    removed task will have been added to the xPendingReadyList.  Once the
    scheduler has been resumed it is safe to move all the pending ready
    tasks from this list into their appropriate ready list. */
    portENTER_CRITICAL();
    {//将计数减一
        --uxSchedulerSuspended;
       //如果等于0,则允许调度
        if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
        {          
            if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 )
            {
                portBASE_TYPE xYieldRequired = pdFALSE;
               
                /*将所有在xPendingReadyList中的任务移到对应的就绪链表中 */
                while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY(  ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
                {
                    vListRemove( &( pxTCB->xEventListItem ) );
                    vListRemove( &( pxTCB->xGenericListItem ) );
                    prvAddTaskToReadyQueue( pxTCB );
                   
                    /* 如果我们移动的任务优先级高于当前任务优先级,则需要调度 */
                    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
                    {
                        xYieldRequired = pdTRUE;
                    }
                }
 
/* 如果在禁止调度期间,有时钟节拍中断发生,则我们把发生的次数记录在uxMissedTicks中,称为丢失的时钟节拍数;我们在这里模拟uxMissedTicks次时钟节拍中断,也就是说调用uxMissedTicks次时钟节拍isr: vTaskIncrementTick()。这样保证了所有任务的延时量不会出现偏差,它们将在正确的时间被唤醒*/
                if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
                {
                    while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
                    {
                        vTaskIncrementTick();//就是重新增加xTickCount
                        --uxMissedTicks;
                    }
 
                    /* As we have processed some ticks it is appropriate to yield
                    to ensure the highest priority task that is ready to run is
                    the task actually running. */
                    #if configUSE_PREEMPTION == 1
                    {
                        xYieldRequired = pdTRUE;
                    }
                    #endif
                }
               
                if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
                {
                    xAlreadyYielded = pdTRUE;
                    xMissedYield = pdFALSE;
                    taskYIELD();
                }
            }
        }
    }
    portEXIT_CRITICAL();
 
    return xAlreadyYielded;
}
在这里我们顺便看下void vTaskIncrementTick( void )这个函数:
void vTaskIncrementTick( void )
{
    /* 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. */
    if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
    {
        ++xTickCount;
        if( xTickCount == ( portTickType ) 0 )
        {
            xList *pxTemp;
 
            /* Tick count has overflowed so we need to swap the delay lists.
            If there are any items in pxDelayedTaskList here then there is
            an error! */
            pxTemp = pxDelayedTaskList;
            pxDelayedTaskList = pxOverflowDelayedTaskList;
            pxOverflowDelayedTaskList = pxTemp;
            xNumOfOverflows++;
        }
 
        /* See if this tick has made a timeout expire. */
        prvCheckDelayedTasks();
    }
    else
    {
        ++uxMissedTicks;
 
        /* The tick hook gets called at regular intervals, even if the
        scheduler is locked. */
        #if ( configUSE_TICK_HOOK == 1 )
        {
            extern void vApplicationTickHook( void );
 
            vApplicationTickHook();
        }
        #endif
    }
 
    #if ( configUSE_TICK_HOOK == 1 )
    {
        extern void vApplicationTickHook( void );
 
        /* Guard against the tick hook being called when the missed tick
        count is being unwound (when the scheduler is being unlocked. */
        if( uxMissedTicks == 0 )
        {
            vApplicationTickHook();
        }
    }
    #endif


 
    traceTASK_INCREMENT_TICK( xTickCount );
}
原创粉丝点击