改变任务的优先级,OSTaskChangePrio()

在用户建立任务的时候会分配给任务一个优先级。在程序运行期间,用户可以通过调用OSTaskChangePrio()来改变任务的优先级。换句话说,就是µC/OS-Ⅱ允许用户动态的改变任务的优先级。
	OSTaskChangePrio()的代码如程序清单 L4.15所示。用户不能改变空闲任务的优先级[L4.15(1)],但用户可以改变调用本函数的任务或者其它任务的优先级。为了改变调用本函数的任务的优先级,用户可以指定该任务当前的优先级或OS_PRIO_SELF,OSTaskChangePrio()会决定该任务的优先级。用户还必须指定任务的新(即想要的)优先级。因为µC/OS-Ⅱ不允许多个任务具有相同的优先级,所以OSTaskChangePrio()需要检验新优先级是否是合法的(即不存在具有新优先级的任务)[L4.15(2)]。如果新优先级是合法的,µC/OS-Ⅱ通过将某些东西储存到OSTCBPrioTbl[newprio]中保留这个优先级[L4.15(3)]。如此就使得OSTaskChangePrio()可以重新允许中断,因为此时其它任务已经不可能建立拥有该优先级的任务,也不能通过指定相同的新优先级来调用OSTaskChangePrio()。接下来OSTaskChangePrio()可以预先计算新优先级任务的OS_TCB中的某些值[L4.15(4)]。而这些值用来将任务放入就绪表或从该表中移除(参看3.04,就绪表)。
	接着,OSTaskChangePrio()检验目前的任务是否想改变它的优先级[L4.15(5)]。然后,OSTaskChangePrio()检查想要改变优先级的任务是否存在[L4.15(6)]。很明显,如果要改变优先级的任务就是当前任务,这个测试就会成功。但是,如果OSTaskChangePrio()想要改变优先级的任务不存在,它必须将保留的新优先级放回到优先级表OSTCBPrioTbl[]中[L4.15(17)],并返回给调用者一个错误码。
	现在,OSTaskChangePrio()可以通过插入NULL指针将指向当前任务OS_TCB的指针从优先级表中移除了[L4.15(7)]。这就使得当前任务的旧的优先级可以重新使用了。接着,我们检验一下OSTaskChangePrio()想要改变优先级的任务是否就绪[L4.15(8)]。如果该任务处于就绪状态,它必须在当前的优先级下从就绪表中移除[L4.15(9)],然后在新的优先级下插入到就绪表中[L4.15(10)]。这儿需要注意的是,OSTaskChangePrio()所用的是重新计算的值[L4.15(4)]将任务插入就绪表中的。
	如果任务已经就绪,它可能会正在等待一个信号量、一封邮件或是一个消息队列。如果OSTCBEventPtr非空(不等于NULL)[L4.15(8)],OSTaskChangePrio()就会知道任务正在等待以上的某件事。如果任务在等待某一事件的发生,OSTaskChangePrio()必须将任务从事件控制块(参看6.00,事件控制块)的等待队列(在旧的优先级下)中移除。并在新的优先级下将事件插入到等待队列中[L4.15(12)]。任务也有可能正在等待延时的期满(参看第五章-任务管理)或是被挂起(参看4.07,挂起任务,OSTaskSuspend())。在这些情况下,从L4.15(8)到L4.15(12)这几行可以略过。
	接着,OSTaskChangePrio()将指向任务OS_TCB的指针存到OSTCBPrioTbl[]中[L4.15(13)]。新的优先级被保存在OS_TCB中[L4.15(14)],重新计算的值也被保存在OS_TCB中[L4.15(15)]。OSTaskChangePrio()完成了关键性的步骤后,在新的优先级高于旧的优先级或新的优先级高于调用本函数的任务的优先级情况下,任务调度程序就会被调用[L4.15(16)]。

程序清单 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);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值