📄 sem.c
字号:
/*********************************************************************
* Copyright (c) 2011-2012,李士伟
* All rights reserved.
*文 件 名:sem.c
*描 述:信号量操作源文件
*当前版本:V1.00
*作 者:李士伟
*创建日期:2011.12.30
**********************************************************************/
#include <kernel\sem.h>
#include <kernel\flag.h>
#include <kernel\sched.h>
#include <kernel\kd.h>
#include <kernel\asm.h>
/*********************************************************************
*函 数 名:API_InitSem
*描 述:初始化信号量
*输入参数:pSem: 信号量结构体指针
* SemCnt: 信号量值
*输出参数:无
*返 回 值:无
*注 意:
**********************************************************************/
void API_InitSem(OS_SEM *pSem, INT32U SemCnt)
{
if (pSem == NULL)
{
return ;
}
OS_ENTER_CRITICAL();
pSem->SemCnt = SemCnt;
pSem->WaitQ = NULL;
OS_EXIT_CRITICAL();
}
/*********************************************************************
*函 数 名:API_SemPend
*描 述:请求信号量
*输入参数:pSem: 信号量结构体指针
* timeout: 等待时限(单位:时钟节拍),
* timeout ==0 直到有信号返回,
* timeout > 0 则在获得信号时或等待时限到了返回
*输出参数:err: 等待错误信息
* err == OS_ERR 等待的信号量对象不存在
* err == OS_OVERTIME 等待时限到
* err == OS_NO_ERR 获得信号量
*返 回 值:OS_GET_SEM 获得信号量,OS_NO_SEM 未获得信号量
*注 意:
**********************************************************************/
INT32U API_SemPend(OS_SEM *pSem, INT32U timeout, INT32U *err)
{
if (pSem == NULL || OSIntNesting > 0 )
{
*err = OS_ERR;
return OS_NO_SEM;
}
OS_ENTER_CRITICAL();
if (pSem->SemCnt > 0) /* 获得信号量 */
{
(pSem->SemCnt)--;
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return OS_GET_SEM;
}
/* 等待信号量 */
OSTCBCur->Delay = timeout; /* 设置等待时限 */
for ( ; ; ) /* 循环查询信号量,防止其它任务广播发送信号量发生错误 */
{
OS_EnterWaitQHead(&(pSem->WaitQ), OSTCBCur); /* 加入信号量的等待队列 */
OS_Sched();
if (pSem->SemCnt > 0) /* 获得信号量 */
{
(pSem->SemCnt)--;
OSTCBCur->Delay = 0; /* 清除等待时限 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return OS_GET_SEM;
}
if ((timeout > 0) && (OSTCBCur->Delay == 0))
{
/* 等待时限到,未获得信号量 */
OS_EXIT_CRITICAL();
*err = OS_OVERTIME;
return OS_NO_SEM;
}
/* 未获得信号量,并且等待时限未到,进入下一个等待循环 */
}
}
/*********************************************************************
*函 数 名:API_SemPost
*描 述:发送信号量
*输入参数:pSem: 信号量结构指针
AddSem: 信号量增加值
*输出参数:
*返 回 值:
*注 意:pSem->SemCnt==1只唤醒一个等待的高优先级任务,
pSem->SemCnt >1唤醒所有等待的任务,
至于任务最终是否获得信号量,取决于它们的优先级
**********************************************************************/
void API_SemPost(OS_SEM *pSem, INT32U AddSem)
{
INT32U prio = 0;
OS_TCB *ptcb;
OS_TCB *wptcb;
OS_ENTER_CRITICAL();
if (pSem == NULL )
{
OS_EXIT_CRITICAL();
return ;
}
pSem->SemCnt += AddSem ;
ptcb = pSem->WaitQ;
wptcb = ptcb;
if (ptcb != NULL) /* 有任务等待信号量 */
{
prio = ptcb->Prio;
}
else /* 没有任务等待信号量,返回 */
{
OS_EXIT_CRITICAL();
return ;
}
/* 唤醒等待信号量的任务 */
if (pSem->SemCnt == 1) /* 基于优先级唤醒一个等待该信号量的高优先级任务 */
{
while (ptcb != NULL) /* 从等待队列查询一个高优先级任务 */
{
if (prio < ptcb->Prio)
{
prio = ptcb->Prio;
wptcb= ptcb;
}
ptcb = ptcb->QNext;
}
OS_EnterRunQ(wptcb); /* 加入运行队列 */
}
else if (pSem->SemCnt > 1) /* 广播方式唤醒所有等待该信号量的任务 */
{
while (ptcb != NULL)
{
wptcb = ptcb->QNext;
OS_EnterRunQ(ptcb); /* 加入运行队列 */
ptcb = wptcb;
}
}
OS_EXIT_CRITICAL();
OS_Sched();
}
/*********************************************************************
*函 数 名:API_SemAccept
*描 述:无等待获取信号量
*输入参数:pSem: 信号量结构体指针
*输出参数:无
*返 回 值:1,获取了信号量,0,未获得信号量
*注 意:
**********************************************************************/
INT32U API_SemAccept(OS_SEM *pSem)
{
OS_ENTER_CRITICAL();
if (pSem->SemCnt > 0)
{
(pSem->SemCnt)--;
OS_EXIT_CRITICAL();
return 1;
}
OS_EXIT_CRITICAL();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -