一步一步学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次