- UID
- 1029342
- 性别
- 男
|
程序清单 L 4.15 OSTaskChangePrio().
INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio)
{
OS_TCB *ptcb;
OS_EVENT *pevent;
INT8U x;
INT8U y;
INT8U bitx;
INT8U bity;
if ((oldprio >= OS_LOWEST_PRIO && oldprio != OS_PRIO_SELF) || (1)
newprio >= OS_LOWEST_PRIO) {
return (OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { (2)
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
} else {
OSTCBPrioTbl[newprio] = (OS_TCB *)1; (3)
OS_EXIT_CRITICAL();
y = newprio >> 3; (4)
bity = OSMapTbl[y];
x = newprio & 0x07;
bitx = OSMapTbl[x];
OS_ENTER_CRITICAL();
if (oldprio == OS_PRIO_SELF) { (5)
oldprio = OSTCBCur->OSTCBPrio;
}
if ((ptcb = OSTCBPrioTbl[oldprio]) != (OS_TCB *)0) { (6)
OSTCBPrioTbl[oldprio] = (OS_TCB *)0; (7)
if (OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) { (8)
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {(9)
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
OSRdyGrp |= bity; (10)
OSRdyTbl[y] |= bitx;
} else {
if ((pevent = ptcb->OSTCBEventPtr) != (OS_EVENT *)0) { (11)
if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
}
pevent->OSEventGrp |= bity; (12)
pevent->OSEventTbl[y] |= bitx;
}
}
OSTCBPrioTbl[newprio] = ptcb; (13)
ptcb->OSTCBPrio = newprio; (14)
ptcb->OSTCBY = y; (15)
ptcb->OSTCBX = x;
ptcb->OSTCBBitY = bity;
ptcb->OSTCBBitX = bitx;
OS_EXIT_CRITICAL();
OSSched(); (16)
return (OS_NO_ERR);
} else {
OSTCBPrioTbl[newprio] = (OS_TCB *)0; (17)
OS_EXIT_CRITICAL();
return (OS_PRIO_ERR);
}
}
} 挂起任务,OSTaskSuspend()
有时候将任务挂起是很有用的。挂起任务可通过调用OSTaskSuspend()函数来完成。被挂起的任务只能通过调用OSTaskResume()函数 来恢复。任务挂起是一个附加功能。也就是说,如果任务在被挂起的同时也在等待延时的期满,那么,挂起操作需要被取消,而任务继续等待延时期满,并转入就绪 状态。任务可以挂起自己或者其它任务。
OSTaskSuspend()函数的代码如程序清单 L4.16所示。通常OSTaskSuspend()需要检验临界条件。首先,OSTaskSuspend()要确保用户的应用程序不是在挂起空闲任务 [L4.16(1)],接着确认用户指定优先级是有效的[L4.16(2)]。记住最大的有效的优先级数(即最低的优先级)是 OS_LOWEST_PRIO。注意,用户可以挂起统计任务(statistic)。可能用户已经注意到了,第一个测试[L4.16(1)]在 [L4.16(2)]中被重复了。笔者这样做是为了能与µC/OS兼容。第一个测试能够被移除并可以节省一点程序处理的时间,但是,这样做的意义不大,所 以笔者决定留下它。
接着,OSTaskSuspend()检验用户是否通过指定OS_PRIO_SELF来挂起调用本函数的任务本身 [L4.16(3)]。用户也可以通过指定优先级来挂起调用本函数的任务[L4.16(4)]。在这两种情况下,任务调度程序都需要被调用。这就是笔者为 什么要定义局部变量self的原因,该变量在适当的情况下会被测试。如果用户没有挂起调用本函数的任务,OSTaskSuspend()就没有必要运行任 务调度程序,因为正在挂起的是较低优先级的任务。
然后,OSTaskSuspend()检验要挂起的任务是否存在[L4.16(5)]。如果该 任务存在的话,它就会从就绪表中被移除[L4.16(6)]。注意要被挂起的任务有可能没有在就绪表中,因为它有可能在等待事件的发生或延时的期满。在这 种情况下,要被挂起的任务在OSRdyTbl[]中对应的位已被清除了(即为0)。再次清除该位,要比先检验该位是否被清除了再在它没被清除时清除它快得 多,所以笔者没有检验该位而直接清除它。现在,OSTaskSuspend()就可以在任务的OS_TCB中设置OS_STAT_SUSPEND标志了, 以表明任务正在被挂起[L4.16(7)]。最后,OSTaskSuspend()只有在被挂起的任务是调用本函数的任务本身的情况下才调用任务调度程序 [L4.16(8)]。 |
|