关于uc/os II OSSemPend()的一点疑惑

wjcapple 2011-10-31 05:29:05
void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif



#if OS_ARG_CHK_EN > 0
if (err == (INT8U *)0) { /* Validate 'err' */
return;
}
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return;
}
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return;
}
if (OSLockNesting > 0) { /* See if called with scheduler locked ... */
*err = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return;
}
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 */
OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */
OSTCBCur->OSTCBPendTO = OS_FALSE;
OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
1) OS_Sched(); /* Find next highest priority task ready */
OS_ENTER_CRITICAL();
2)if (OSTCBCur->OSTCBPendTO == OS_TRUE) { /* See if we timedout */
OS_EventTO(pevent);
OS_EXIT_CRITICAL();
*err = OS_TIMEOUT; /* Indicate that didn't get event within TO */
return;
}
OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}




1)执行玩任务调度之后,OSTCBCur指向的任务有可能不是调用OSSemPend的任务,如果那样的话,后面的代码岂不是出错了?请高人指点迷津
...全文
1003 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
liang_cheng_jie 2011-11-12
  • 打赏
  • 举报
回复
好深奥
wjcapple 2011-11-11
  • 打赏
  • 举报
回复
哎,而没人顶,自己顶
wjcapple 2011-11-01
  • 打赏
  • 举报
回复
继续发代码讨论问题,这次发的代码是关于等待互斥性信号量的源代码,感觉这里有个bug,虽然这个bug可以在应用编程的时候通过检查变量可以避免,从系统内核的角度上来讲,觉得还是可以避免的。
void OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
INT8U pip; /* Priority Inheritance Priority (PIP) */
INT8U mprio; /* Mutex owner priority */
BOOLEAN rdy; /* Flag indicating task was ready */
OS_TCB *ptcb;
OS_EVENT *pevent2;
INT8U y;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif



#if OS_ARG_CHK_EN > 0
if (err == (INT8U *)0) { /* Validate 'err' */
return;
}
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return;
}
#endif
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return;
}
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return;
}
if (OSLockNesting > 0) { /* See if called with scheduler locked ... */
*err = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return;
}
OS_ENTER_CRITICAL();
pip = (INT8U)(pevent->OSEventCnt >> 8); /* Get PIP from mutex */
/* Is Mutex available? */
if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */
pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save priority of owning task */
pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */
if (OSTCBCur->OSTCBPrio <= pip) { /* PIP 'must' have a SMALLER prio ... */
OS_EXIT_CRITICAL(); /* ... than current task! */
*err = OS_ERR_PIP_LOWER;
} else {
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
}
return;
}

标红的地方,觉得有些问题,本人觉得应该首先判断调用这个函数的任务的优先级是否高于信号量本身的优先级,如果高于,马上返回,而不是先对信号量的OSEventCnt操作之后,再比较,如果按照源代码流程,如果出现返回,那么这个信号的将永远处于被占用状态,因为返回前没有对信号进行恢复到没有使用状态。我看邵贝贝的那本书上的源代码,根本没有做OSTCBCur->OSTCBPrio <= pip的判断,我猜想是留给应用编程的时候进行判断,但根据网友(http://download.csdn.net/detail/wqygogo/818561)上传的资料里面看到的这个函数,个人感觉是个bug,既然做了检查,就应该保证安全性。本人前一段一直在做wince应用,现在想往底层走一走,在看uc/OsII的操作系统,发现一点问题,或者说的不对,以求抛砖引玉,和志同道合者一起讨论,共同提高。
chinaye1 2011-11-01
  • 打赏
  • 举报
回复
研究每句代码的强啊
wjcapple 2011-10-31
  • 打赏
  • 举报
回复
1) 执行完之后,如果有更高优先级的任务就绪,那么调用OSSemPend()的任务将被挂起(入栈),然后等到事件发生,或者超时,调用OSSemPend()的任务重新处于就绪状态,并且优先级满足的时候,出栈,从1)后面重新执行。
wjcapple 2011-10-31
  • 打赏
  • 举报
回复
有点小明白了,(*^__^*) 嘻嘻……
#include"..\ucos-ii\includes.h" /* uC/OS interface */ #include "..\ucos-ii\add\osaddition.h" #include "..\inc\drv.h" #include #include #pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting ///******************任务定义***************/// OS_STK Main_Stack[STACKSIZE*8]={0, }; //Main_Test_Task堆栈 void Main_Task(void *Id); //Main_Test_Task #define Main_Task_Prio 12 /**************已经定义的OS任务************* tcp监控任务 11 以太网物理层监控任务 8 触摸屏任务 9 键盘任务 10 lcd刷新任务 59 系统任务 1 *****************************************************/ ///*****************事件定义*****************/// OS_EVENT *Nand_Rw_Sem; //Nand_Flash读写控制权旗语 //and you can use it as folloeing: // Nand_Rw_Sem=OSSemCreate(1); //创建Nand-Flash读写控制权旗语,初值为1满足互斥条件// // OSSemPend(Nand_Rw_Sem,0,&err); // OSSemPost(Nand_Rw_Sem); OS_EVENT *Uart_Rw_Sem; //Uart读写控制权旗语 //and you can use it as folloeing: // Uart_Rw_Sem=OSSemCreate(1); //创建Uart读写控制权旗语,初值为1满足互斥条件// // OSSemPend(Uart_Rw_Sem,0,&err); // OSSemPost(Uart_Rw_Sem); ////////////////////////////////////////////////////////// void initOSGUI() //初始化操作系统的图形界面 { initOSMessage(); initOSList(); initOSDC(); initOSCtrl(); initOSFile(); } ///////////////////////////////////////////////////// // Main function. // ////////////////////////////////////////////////////

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧