vTaskSuspendAll和xTaskResumeAll


这是一种同步机制,比关中断要温和点。禁止调度由
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 );
}
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) { TickType_t xTimeToWake; BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; configASSERT( pxPreviousWakeTime ); configASSERT( ( xTimeIncrement > 0U ) ); configASSERT( uxSchedulerSuspended == 0 ); vTaskSuspendAll(); { /* Minor optimisation. The tick count cannot change in this block. */ const TickType_t xConstTickCount = xTickCount; /* Generate the tick time at which the task wants to wake. */ xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; if( xConstTickCount < *pxPreviousWakeTime ) { /* The tick count has overflowed since this function was lasted called. In this case the only time we should ever actually delay is if the wake time has also overflowed, and the wake time is greater than the tick time. When this is the case it is as if neither time had overflowed. */ if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } else { /* The tick time has not overflowed. In this case we will delay if either the wake time has overflowed, and/or the tick time is less than the wake time. */ if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) { xShouldDelay = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } /* Update the wake time ready for the next call. */ *pxPreviousWakeTime = xTimeToWake; if( xShouldDelay != pdFALSE ) { traceTASK_DELAY_UNTIL( xTimeToWake ); /* prvAddCurrentTaskToDelayedList() needs the block time, not the time to wake, so subtract the current tick count. */ prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); } else { mtCOVERAGE_TEST_MARKER(); } } xAlreadyYielded = xTaskResumeAll(); /* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */ if( xAlreadyYielded == pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } }
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值