睡眠状态的任务的OSTaskSuspend

OSTaskSuspend()
最近的一个程序中用到OSTaskSuspend,并且待挂起的任务中有OSSemPend。结果发现程序运行异常。
当待挂起的任务正在延时或等待事件时,会有何后果?


网上常见的说法

【挂起操作需要被取消,而任务继续等待延时期满,并转入就绪状态。任务可以挂起自己或者其它任务。】

【任务的挂起是可以叠加到其他操作上的。例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:延时的结束以及其他任务的唤醒操作。又如,任务被挂起时正在等待信号量,当任务从信号量的等待队列中清除后也不能立即运行,而必须等到被唤醒后。】


说实话,我有点迷糊。那么从代码入手吧!(只摘录关键代码)

OSTaskSuspend (INT8U prio)
{
    ...
    y = ptcb->OSTCBY;
    OSRdyTbl[y] &= ~ptcb->OSTCBBitX;/* Make task not ready                 */
    if (OSRdyTbl[y] == 0x00) { 
        OSRdyGrp &= ~ptcb->OSTCBBitY;
    }
    ptcb->OSTCBStat |= OS_STAT_SUSPEND;                         /* Status of task is 'SUSPENDED'       */
    ...
}

void  OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
    ...
    OS_ENTER_CRITICAL();
    if (pevent->OSEventCnt > 0) {                     /* If sem. is positive, resource available ...   */
        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return;
    }                                                     /* Otherwise, must wait until event occurs       */
    ...
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* Find next highest priority task ready         */
    OS_ENTER_CRITICAL();
    ...
}


void  OS_EventTaskWait (OS_EVENT *pevent)
{
    ...
    pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;          /* Put task in waiting list  */
    pevent->OSEventGrp                   |= OSTCBCur->OSTCBBitY;
}


INT8U  OSSemPost (OS_EVENT *pevent)
{
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                          /* See if any task waiting for semaphore*/
        (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); /* Ready HPT waiting on event           */
        OS_EXIT_CRITICAL();
        OS_Sched();                                            /* Find HPT ready to run                */
        return (OS_NO_ERR);
    }
    if (pevent->OSEventCnt < 65535u) {                /* Make sure semaphore will not overflow         */
        pevent->OSEventCnt++;                         /* Increment semaphore count to register event   */
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();                               /* Semaphore value has reached its maximum       */
    return (OS_SEM_OVF);
}


INT8U  OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U msk)
{
    ...                                                 /* Find HPT waiting for message         */
    prio                   = (INT8U)((y << 3) + x);     /* Find priority of task getting the msg       */
    pevent->OSEventTbl[y] &= ~bitx;                     /* Remove this task from the waiting list      */
    if (pevent->OSEventTbl[y] == 0x00) {                
        pevent->OSEventGrp &= ~bity;                    /* Clr group bit if this was only task pending */
    }
    ... 
    if (ptcb->OSTCBStat == OS_STAT_RDY) {               /* See if task is ready (could be susp'd)      */
        OSRdyGrp        |=  bity;                       /* Put task in the ready to run list           */
        OSRdyTbl[y]     |=  bitx;
    }
    return (prio);
}

----------------------------------------------------------------------------------------------------------------------------
显然当TaskA正在pend一个Uart0ReadSem时,pend会调用OS_EventTaskWait(pevent)以Put task in waiting list,即置位pevent->OSEventTbl、pevent->OSEventGrp。

若TaskB将TaskA挂起,对pevent->OSEventTbl、pevent->OSEventGrp无影响,

Uart0接收中断post一个Uart0ReadSem,post判断(pevent->OSEventGrp != 0x00),则不对pevent->OSEventCnt进行+1,而是通过OS_EventTaskRdy将pend在事件上的任务列表中优先级最高的任务移出等待列表。若该任务处于OS_STAT_RDY就将它加入runlist,若处于OS_STAT_SUSPEND则跳过。
-----------------------------------------------------------------------------------------------------------------------------
结论:
TaskB若挂起TaskA,且TaskA正在等待事件sem,那么若发送了sem,TaskA仍能获得这个sem(前提TaskA优先级够高),但需到恢复TaskA时才继续执行。
如此一来,同样等待sem的TaskB就会被TaskA抢走一个sem,造成TaskA虽然被挂起却仍然同TaskB争夺了一次资源。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值