一步一步学ucos之释放一个互斥信号量

释放一个互斥信号量:OSMutexPost()

关键代码剖析:

INT8U  OSMutexPost (OS_EVENT *pevent)

{

   //不得在中断中调用该函数

    if (OSIntNesting > 0) {                           

        return (OS_ERR_POST_ISR);                    

    }

OS_ENTER_CRITICAL();

//从该信号量中获得PIP

pip  = (INT8U)(pevent->OSEventCnt >> 8);          

/*

    从该信号量中获得占用该信号量的任务的优先级。

    在OSEventCnt中的低8位保存占用mutex的任务的原始优先级,

    不随优先级的提高而改变。

*/

prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);  

/*

    确认释放mutex的任务确实是占用mutex的任务自身。

    占用/申请mutex的任务的优先级可能是pip(被提高),也可能是原先任务的优先级。

*/

    if (OSTCBCur->OSTCBPrio != pip && 

        OSTCBCur->OSTCBPrio != prio) {               

        OS_EXIT_CRITICAL();

        //若释放mutex的任务非占用/申请的任务,则返回错误信息。

        return (OS_ERR_NOT_MUTEX_OWNER);

}

   //若当前释放mutex的任务的优先级为pip,则需将该任务的优先级降到原来水平

if (OSTCBCur->OSTCBPrio == pip) {

   //首先将pip从就绪表删除

        if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {

            OSRdyGrp &= ~OSTCBCur->OSTCBBitY;

        }

        //将任务优先级修改为原始优先级,并修改相关参数

        OSTCBCur->OSTCBPrio   = prio;

        OSTCBCur->OSTCBY     = prio >> 3;

        OSTCBCur->OSTCBBitY   = OSMapTbl[OSTCBCur->OSTCBY];

        OSTCBCur->OSTCBX      = prio & 0x07;

        OSTCBCur->OSTCBBitX    = OSMapTbl[OSTCBCur->OSTCBX];

        //将修改优先级后的任务重新如就绪表

        OSRdyGrp           |= OSTCBCur->OSTCBBitY;

        OSRdyTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;

        OSTCBPrioTbl[prio]    = (OS_TCB *)OSTCBCur;

    }

OSTCBPrioTbl[pip] = (OS_TCB *)1;                  

//若mutex的等待列表不空,唤醒等待列表中最高优先级的任务,并将mutex分配给它

if (pevent->OSEventGrp != 0x00) {           

    /*

        唤醒等待列表中最高优先级的任务(从mutex等待列表中删除,使其入就绪表),

        清除等待任务的OS_STAT_MUTEX标志,并返回其优先级prio

    */

        prio  = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX);

        pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;  

        //将mutex分配给新任务:置OSEventCnt为prio

        pevent->OSEventCnt |= prio;

        //在mutex中保存占用信号量的任务

        pevent->OSEventPtr  = OSTCBPrioTbl[prio];     

        OS_EXIT_CRITICAL();

        //任务切换(如果唤醒的任务优先级比当前任务高,则使唤醒的任务得到运行)

        OS_Sched();                                   

        return (OS_NO_ERR);

}

//mutex的等待列表为空,即该mutex可用:置mutex可用标志及占用任务指针。

    pevent->OSEventCnt |= OS_MUTEX_AVAILABLE;        

    pevent->OSEventPtr  = (void *)0;

    OS_EXIT_CRITICAL();

    return (OS_NO_ERR);

}
冯大同 发表于03-13 08:53 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

冯大同
冯大同(元帅)
金币:1539个|学分:34354个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号