今天写代码将调度器上锁了以后执行一个函数,结果在函数里用OSTimeDly(ticks)延时失效,经过阅读源码得知本该无效。
源码分析
给调度器上锁:
void OSSchedLock (void) { if (OSRunning == TRUE) { OS_ENTER_CRITICAL(); OSLockNesting++; OS_EXIT_CRITICAL(); } }
上面的函数将OSSchedLock()将OSLockNesting加1,而OSLockNesting是unsigned char类型的,
一般情况下OSLockNesting > 0 了(OSLockNesting自增前为255的话就为0);
任务延时:
void OSTimeDly (INT16U ticks) { INT8U y; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; cpu_sr = 0; /* Prevent compiler warning */ #endif if (ticks > 0) { /* 0 means no delay! */ OS_ENTER_CRITICAL(); y = OSTCBCur->OSTCBY; /* Delay current task */ OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX; if (OSRdyTbl[y] == 0) { OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */ OS_EXIT_CRITICAL(); OS_Sched(); /* Find next task to run! */ } }
上面的函数OSTimeDly(ticks)检测ticks是否大于0,一般传递延时都是大于0的,否则就是故意为了等时序了,
既然ticks>0,就会引发一次任务调度,执行OS_Sched()。
任务调度函数:
void OS_Sched (void) { INT8U y; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; cpu_sr = 0; /* Prevent compiler warning */ #endif OS_ENTER_CRITICAL(); if (OSIntNesting == 0) { /* Schedule only if all ISRs done and ... */ if (OSLockNesting == 0) { /* ... scheduler is not locked */ y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to HPT ready to run */ OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; #if OS_TASK_PROFILE_EN > 0 OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ #endif OSCtxSwCtr++; /* Increment context switch counter */ OS_TASK_SW(); /* Perform a context switch */ } } } OS_EXIT_CRITICAL(); }
上面的函数OS_Sched ()检测到OSLockNesting != 0,自然不会执行if (OSLockNesting == 0)里面的内容,于是直接跳出函数了,
此时我们看PC指针是不是回到了OSTimeDly(ticks)的最后,那么此时程序将会执行的就是OSTimeDly(ticks)之后的代码了,
此处调度器上锁了,相当于OSTimeDly(ticks)白跑了一趟,而且飞快就跑完了,不但当前任务没挂起,而且也没有切换到其他任务,
更没有真正的起到延时的作用。
这就是为什么ucos说调度器上锁后用户不能调用任何能够引发调度的函数了,其实不是真的不能,是这样等于做无用功!