完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近看实时操作系统,鸟哥提问了个问题、、有处一直没理解。求大神讲解下
mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get priority of mutex owner */ ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */ if (ptcb->OSTCBPrio > pcp) /* Need to promote prio of owner?*/ { if (mprio > OSTCBCur->OSTCBPrio) { 。。。。。。 } } 谁知道这两个if起什么作用? |
|
相关推荐
10个回答
|
|
if (ptcb->OSTCBPrio > pcp) /* Need to promote prio of owner?*/
{ if (mprio > OSTCBCur->OSTCBPrio) { 。。。。。。 } } 优先级的对比,如果没有其它的执行逻辑,可以理解为(ptcb->OSTCBPrio>pcp) && (mprio>OSTCBCur->OSTCBPrio) |
|
|
|
7762642422d 发表于 2018-9-14 19:25 表示赞同 外面的优先级高 |
|
|
|
|
|
//提升优先级之前该task处于事件控制矩阵中,等待事件的到来
//需要说明一点,一个task只有两种状态, //1.要么在就绪控制矩阵中等待被cpu调度 //2.要么阻塞在事件控制矩阵中[gliethttp] pevent2 = ptcb->OSTCBEventPtr; if (pevent2 != (OS_EVENT *)0) { pevent2->OSEventGrp |= ptcb->OSTCBBitY; pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; } } OSTCBPrioTbl[pip] = ptcb;//添加新pip优先级下的TCB } } OSTCBCur->OSTCBStat |= OS_STAT_MUTEX;//是Mutex事件让本task进入悬停等待的 OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;//假定不是超时,为正常收到信号 //超时,如果timeout=0,那么,本task将一直悬停,仅仅当收到事件触发信号后才重新进入调度队列 OSTCBCur->OSTCBDly = timeout; //OS_EventTaskWait()函数实现的功能: //把本task从就绪控制矩阵中摘下,放到pevent事件专有的进程事件控制矩阵表中. OS_EventTaskWait(pevent); OS_EXIT_CRITICAL(); //因为本task正在运行,所以本task现在的优先级最高的,现在本task已经将自己从就绪控制矩阵--调度器(x,y)矩形阵列中 //把自己摘掉,所以调度函数OS_Sched()一定会切换到另一个task中执行新task的代码[gliethttp] OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》 OS_ENTER_CRITICAL(); //2007-09-09 gliethttp //可能因为OSMutexPend()中指定的timeout已经超时 //[由OSTimeTick()函数把本task重新置入了就绪队列,具体参考《浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理》], //又或者确实在应用程序的某个地方调用了OSMutexPost(),以下代码将具体解析是有什么引起的:1.超时,2.收到正常信号 if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) { //是因为timeout超时,使得本task获得重新执行的机会 pend_stat = OSTCBCur->OSTCBStatPend; //清除event事件块上本task的标志 OS_EventTOAbort(pevent); OS_EXIT_CRITICAL(); switch (pend_stat) { case OS_STAT_PEND_TO: default: *perr = OS_ERR_TIMEOUT; break; case OS_STAT_PEND_ABORT: *perr = OS_ERR_PEND_ABORT; break; } return; } //由OSMutexPost()抛出正常事件,唤醒了本task,因为在OSMutexPost()时, //已经将本task在event事件控制矩阵上的对应位清除掉,并且把本task放入了就绪控制矩阵中, //否则本task也不会执行至此. OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; OS_EXIT_CRITICAL(); *perr = OS_ERR_NONE; } //---------------------------------------------------------------------- //2.OS_EventTaskWait()函数 void OS_EventTaskWait (OS_EVENT *pevent) { INT8U y; //2007-09-09 gliethttp //pevent为此次task挂起的EventPtr单元 OSTCBCur->OSTCBEventPtr = pevent; //清除调度器中该task对应的标志位 y = OSTCBCur->OSTCBY; OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX; if (OSRdyTbl[y] == 0) { //当前y行对应的8个或16个task都已经悬停,那么当前y行也清除. OSRdyGrp &= ~OSTCBCur->OSTCBBitY; } //2007-09-09 gliethttp //将该task的prio添加到pevent事件控制矩阵中,这个矩阵的功能和OSRdyGrp、OSRdyTbl就绪控制矩阵没有区别 //都是用来计算出已经就绪tasks中的优先级最高的那个 pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; } //---------------------------------------------------------------------- //3.OS_EventTOAbort()函数 void OS_EventTOAbort (OS_EVENT *pevent) { INT8U y; //清除event事件控制矩阵上本task的标志,因为OSTimeTick()函数未清除该单元 //它仅仅把本task放入就绪控制矩阵,使得本task重新获得被OS调度的机会而已 //具体的清除工作还要自己完成 //具体参考《浅析μC/OS-II v2.85内核OSTimeDly()函数工作原理》 y = OSTCBCur->OSTCBY; pevent->OSEventTbl[y] &= ~OSTCBCur->OSTCBBitX; if (pevent->OSEventTbl[y] == 0x00) { pevent->OSEventGrp &= ~OSTCBCur->OSTCBBitY; } OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; OSTCBCur->OSTCBStat = OS_STAT_RDY; OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;//现在本task不悬停在任何event事件上 } |
|
|
|
//----------------------------------------------------------------------
//4.OSMutexPost()函数 INT8U OSMutexPost (OS_EVENT *pevent) { INT8U pip; INT8U prio; #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr = 0;//方式3将把cpsr状态寄存器推入临时堆栈cpu_sr中,可以安全返回之前的中断状态 #endif if (OSIntNesting > 0) { return (OS_ERR_POST_ISR); } #if OS_ARG_CHK_EN > 0 if (pevent == (OS_EVENT *)0) { return (OS_ERR_PEVENT_NULL); } #endif if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { return (OS_ERR_EVENT_TYPE); } OS_ENTER_CRITICAL(); pip = (INT8U)(pevent->OSEventCnt >> 8);//变相置顶值pip prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);//持有mutex资源的task原始优先级 if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr) { //因为解决了局部优先级翻转问题,所以OSTCBCur肯定要等于pevent->OSEventPtr //否则发生了不知名的异常 OS_EXIT_CRITICAL(); return (OS_ERR_NOT_MUTEX_OWNER); } if (OSTCBCur->OSTCBPrio == pip) { //task被提升了优先级到pip置顶值,也就是一个比该task优先级高 //比pip低的进程需要访问互斥资源,即:存在B角色进程, //那么使用OSMutex_RdyAtPrio()把本task从就绪控制矩阵中摘下来 //同时将自己还原到prio优先级 OSMutex_RdyAtPrio(OSTCBCur, prio); } OSTCBPrioTbl[pip] = OS_TCB_RESERVED; if (pevent->OSEventGrp != 0) { //2007-09-09 gliethttp //OS_EventTaskRdy()函数将摘掉等待在pevent事件控制矩阵上的task中优先级最高的task //如果该task仅仅等待该pevent事件,那么将该task添加到就绪控制矩阵中 //OSRdyGrp |= bity; //OSRdyTbl[y] |= bitx;这样调度程序就会根据情况调度OS_Sched()该task了 prio = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK); //保持处于高8位的pip置顶优先级值 //同时清除低8位数据 pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; pevent->OSEventCnt |= prio;//获得执行权的task充当优先级翻转计算中的C角色 pevent->OSEventPtr = OSTCBPrioTbl[prio];//task的控制块传给OSEventPtr指针,供优先级翻转计算使用 if (prio <= pip) { //2007-09-09 gliethttp //prio比pip小,那么说明比置顶值pip优先级还要高的进程竟然访问了共享资源, //那么这时可能会出现优先级翻转,因为这时mutex机制已经不起作用, //所以应该保证"变相置顶的方式"初始化时,自己内定的最高优先级pip务必大于所有能访问互斥资源的进程优先级[gliethttp] OS_EXIT_CRITICAL(); OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》 return (OS_ERR_PIP_LOWER); } else { OS_EXIT_CRITICAL(); OS_Sched();//具体参见《浅析μC/OS-II v2.85内核调度函数》 return (OS_ERR_NONE); } } //没有任何一个task悬停在本event事件控制矩阵上[gliethttp] pevent->OSEventCnt |= OS_MUTEX_AVAILABLE;//还原为初始值 pevent->OSEventPtr = (void *)0;//现在本task不悬停在任何event事件上 OS_EXIT_CRITICAL(); return (OS_ERR_NONE); } //---------------------------------------------------------------------- //5.OS_EventTaskRdy()函数 INT8U OS_EventTaskRdy (OS_EVENT *pevent, void *pmsg, INT8U msk, INT8U pend_stat) { OS_TCB *ptcb; INT8U x; INT8U y; INT8U prio; #if OS_LOWEST_PRIO <= 63 INT8U bitx; INT8U bity; #else INT16U bitx; INT16U bity; INT16U *ptbl; #endif #if OS_LOWEST_PRIO <= 63 //小于64个task时,快速计算 //最有优先权的task位于事件控制矩阵中的第y行的第x列 y = OSUnMapTbl[pevent->OSEventGrp]; bity = (INT8U)(1 << y); x = OSUnMapTbl[pevent->OSEventTbl[y]]; bitx = (INT8U)(1 << x); prio = (INT8U)((y << 3) + x); #else //对于256个task //最有优先权的task位于事件控制矩阵中的第y行的第x列 //以下的操作原理具体参见《浅析μC/OS-II v2.85内核调度函数》 if ((pevent->OSEventGrp & 0xFF) != 0) { y = OSUnMapTbl[pevent->OSEventGrp & 0xFF]; } else { y = OSUnMapTbl[(pevent->OSEventGrp >> 8) & 0xFF] + 8; } bity = (INT16U)(1 << y); ptbl = &pevent->OSEventTbl[y]; if ((*ptbl & 0xFF) != 0) { x = OSUnMapTbl[*ptbl & 0xFF]; } else { x = OSUnMapTbl[(*ptbl >> 8) & 0xFF] + 8; } bitx = (INT16U)(1 << x); prio = (INT8U)((y << 4) + x);//该task对应的prio优先级值 //ok,等待在event事件上的所有task中,只有在事件控制矩阵中的第y行的第x列task //优先级最高、最值的成为此次事件的唤醒对象[gliethttp] #endif //清除此task在event事件控制矩阵中的bit位 pevent->OSEventTbl[y] &= ~bitx; if (pevent->OSEventTbl[y] == 0) { pevent->OSEventGrp &= ~bity; } //通过prio优先级找到该prio唯一对应的task对应的ptcb进程上下文控制块 ptcb = OSTCBPrioTbl[prio]; ptcb->OSTCBDly = 0;//复原为正常 ptcb->OSTCBEventPtr = (OS_EVENT *)0;//现在本task不悬停在任何event事件上 #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) ptcb->OSTCBMsg = pmsg;//传递消息指针 #else pmsg = pmsg; #endif ptcb->OSTCBStatPend = pend_stat;//悬停状态值 ptcb->OSTCBStat &= ~msk;//该msk事件已经发生,清除task上下文控制块上的msk位,如:OS_STAT_MUTEX if (ptcb->OSTCBStat == OS_STAT_RDY) { //如果当前task只是等待该事件,那么把该task放到就绪控制矩阵中,允许内核调度本task OSRdyGrp |= bity; OSRdyTbl[y] |= bitx; } return (prio);//返回本task对应的优先级值 } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PS:"所以从这里来看,os中的各个功能单元管理着自己的事情,就像面向对象的封装一样," "事件控制矩阵和就绪控制矩阵是各个对象独立自治的关键因素" "其他对象,都努力说服自己相信别的对象是独立的、可信任的、安全的"[gliethttp] //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
|
这个#if和if语句不是差不多的吗?根据不同的宏定义来选择不同的语句进行编译
|
|
|
|
楼主搞明白了么?
|
|
|
|
|
|
|
|
|
|
|
|
似懂非懂啊
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1049 浏览 0 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1017 浏览 2 评论
2123 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
1219 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
1639 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 14:37 , Processed in 0.748744 second(s), Total 92, Slave 75 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号