//信号量不可用:即已被占用
//从该信号量中获得PIP
pip = (INT8U)(pevent->OSEventCnt >> 8);
//从该信号量中获得占用该信号量的任务的优先级。
mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);
//从信号量中获得占用该信号量的任务
ptcb = (OS_TCB *)(pevent->OSEventPtr);
/*
如果原先占用该mutex的优先级比提出申请该mutex的任务的优先级低
(mprio > OSTCBCur->OSTCBPrio),则提升原任务的优先级至PIP
*/
if (ptcb->OSTCBPrio != pip && mprio > OSTCBCur->OSTCBPrio) {
if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) {
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) {
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
//若原任务已就绪,则将其从就绪表中删除,并置就绪标志rdy
rdy = TRUE;
} else {
rdy = FALSE;
}
//修改优先级,及相关参数
ptcb->OSTCBPrio = pip;
ptcb->OSTCBY = ptcb->OSTCBPrio >> 3;
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = ptcb->OSTCBPrio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
//如果原任务是就绪的,则继续让新的优先级就绪
if (rdy == TRUE) {
OSRdyGrp |= ptcb->OSTCBBitY;
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
}
OSTCBPrioTbl[pip] = (OS_TCB *)ptcb;
}
//让提出申请的任务先等待(从就绪表中删除,如mutex的等待队列)………
OSTCBCur->OSTCBStat |= OS_STAT_MUTEX;
OSTCBCur->OSTCBDly = timeout;
OS_EventTaskWait(pevent);
OS_EXIT_CRITICAL();
//执行任务切换(如果原来低优先级的任务优先级被抬高了,则该任务将被执行)
OS_Sched();
OS_ENTER_CRITICAL();
//提出申请的任务被唤醒继续执行
if (OSTCBCur->OSTCBStat & OS_STAT_MUTEX) {
//1)由于等待超时被定时器唤醒
OS_EventTO(pevent);
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT;
return;
}
/*
2)原先占用mutex的任务执行完成释放了mutex
并唤醒了等待该mutex的最高优先级的任务
*/
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
释放一个互斥信号量:OSMutexPost()
关键代码剖析:
INT8U OSMutexPost (OS_EVENT *pevent)
{
//不得在中断中调用该函数
if (OSIntNesting > 0) {
return (OS_ERR_POST_ISR);
}
OS_ENTER_CRITICAL(); |