//通过OSSemCreate()建立信号量
OS_EVENT *OSSemCreate(INT16U cnt)
{
#if OS_CRITICAL_METHOD==3
OS_CPU_SR cpu_sr;
#endif
OS_EVENT *pevent;
if(OSIntNesting>0) //判断是否被中断服务子程序调用
{
return ((OS_EVENT*)0);
}
OS_ENTER_CRITICAL();
pevent=OSEventFreeList;//试图从空闲事件控制块联表中得到一个事件控制块ECB
if(OSEventFreeList!=(OS_EVENT *)0)
{
OSEventFreeList=(OS_EVENT *)OSEventFreeList->OSEventPtr;
//对空闲事件控制联表的指针进行调整,使它指向下一个空闲的事件控制块
}
OS_EXIT_CRITICAL();
if(pevent!=(OS_EVENT *)0)
{
pevent->OSEventType=OS_EVENT_TYPE_SEM;//如果由任务控制块可用,就将该任务的事件类型设置OS_EVENT_TYPE_SEM
pevent->OSEventCnt=cnt;//将信号的初始值存入事件控制块
pevent->OSEventPtr=(void*)0;//将OSEventPtr初始化NULL
OS_EventWaitListInit(pevent);//对事件控制块的等待任务列表进行初始化
}
return (pevent); //返回给调用函数一个指向事件控制块的ECB的指针
}
//通过OSSemPost()等待一个信号量
void OSSemPend(OS_EVENT *prevent,INT16U timeout,INT8U *err)
{
#if OS_CRITICAL_METHOD==3
OS_CPU_SR cpu_sr;
#endif
if(OSIntNesting>0) //检查OSSemPend是否由中断服务子程序调用_
{
*err=OS_ERR_PEND_ISR;
return;
}
#if OS_ARG_CHK_EN>0
if(pevent==(OS_EVENT *)0)
{
*err=OS_ERR_EVENT_TYPE;
return;
}
if(pevent->OSEventType!=OS_EVENT_TYPE_SEM)
{//检查指针pevent所指的任务控制块是否是由OSSemCreate();建立
*err=OS_ERR_EVENT_TYPE;
return;
}
#endif
OS_ENTER_CRITICAL();
if(pevent->OSEventCnt>0) //如果信号量当前可用,即信号量的计数值大于0,将信号量的计数值减一,然后函数返回“无措”的错误代码
{
pevent->OSEventCnt--;
OS_EXIT_CRITICAL();
*err=OS_NO_ERR;
return;
}
OSTCBCur->OSTCBStat|=OS_STAT_SEM;//将任务控制块的状态标志OSTCBStat置1,把任务置于睡觉的状态
OSTCBCur->OSTCBDly=timeout; //将等待时间置入任务控制块中
OS_EventTaskWait(pevent); //真正将任务置入睡民状态的操作在OSEventTaskWait()函数中执行
OS_EXIT_CRITICAL();
OS_Sched(); //当前任务不是就绪态,所以任务调度函数将下一个
OS_ENTER_CRITICAL();
if(OSTCBCur->OSTCBStat&OS_STAT_SEM)
{
OS_EventTO(pevent);
OS_EXIT_CRITICAL();
*err=OS_TIMEOUT;
return;
}
OSTCBCur->OSTCBEventPtr=(OS_EVENT *)0;
OS_EXIT_CRITICAL();
*err=OS_NO_ERR;
}
转载于:https://www.cnblogs.com/hzhida/archive/2012/03/14/2395681.html