?? sem.c
字號:
/*********************************************************************
* Copyright (c) 2011-2012,李士偉
* All rights reserved.
*文 件 名:sem.c
*描 述:信號量操作源文件
*當(dāng)前版本:V1.00
*作 者:李士偉
*創(chuàng)建日期:2011.12.30
**********************************************************************/
#include <kernel\sem.h>
#include <kernel\flag.h>
#include <kernel\sched.h>
#include <kernel\kd.h>
#include <kernel\asm.h>
/*********************************************************************
*函 數(shù) 名:API_InitSem
*描 述:初始化信號量
*輸入?yún)?shù):pSem: 信號量結(jié)構(gòu)體指針
* SemCnt: 信號量值
*輸出參數(shù):無
*返 回 值:無
*注 意:
**********************************************************************/
void API_InitSem(OS_SEM *pSem, INT32U SemCnt)
{
if (pSem == NULL)
{
return ;
}
OS_ENTER_CRITICAL();
pSem->SemCnt = SemCnt;
pSem->WaitQ = NULL;
OS_EXIT_CRITICAL();
}
/*********************************************************************
*函 數(shù) 名:API_SemPend
*描 述:請求信號量
*輸入?yún)?shù):pSem: 信號量結(jié)構(gòu)體指針
* timeout: 等待時限(單位:時鐘節(jié)拍),
* timeout ==0 直到有信號返回,
* timeout > 0 則在獲得信號時或等待時限到了返回
*輸出參數(shù):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; /* 設(shè)置等待時限 */
for ( ; ; ) /* 循環(huán)查詢信號量,防止其它任務(wù)廣播發(fā)送信號量發(fā)生錯誤 */
{
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;
}
/* 未獲得信號量,并且等待時限未到,進入下一個等待循環(huán) */
}
}
/*********************************************************************
*函 數(shù) 名:API_SemPost
*描 述:發(fā)送信號量
*輸入?yún)?shù):pSem: 信號量結(jié)構(gòu)指針
AddSem: 信號量增加值
*輸出參數(shù):
*返 回 值:
*注 意:pSem->SemCnt==1只喚醒一個等待的高優(yōu)先級任務(wù),
pSem->SemCnt >1喚醒所有等待的任務(wù),
至于任務(wù)最終是否獲得信號量,取決于它們的優(yōu)先級
**********************************************************************/
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) /* 有任務(wù)等待信號量 */
{
prio = ptcb->Prio;
}
else /* 沒有任務(wù)等待信號量,返回 */
{
OS_EXIT_CRITICAL();
return ;
}
/* 喚醒等待信號量的任務(wù) */
if (pSem->SemCnt == 1) /* 基于優(yōu)先級喚醒一個等待該信號量的高優(yōu)先級任務(wù) */
{
while (ptcb != NULL) /* 從等待隊列查詢一個高優(yōu)先級任務(wù) */
{
if (prio < ptcb->Prio)
{
prio = ptcb->Prio;
wptcb= ptcb;
}
ptcb = ptcb->QNext;
}
OS_EnterRunQ(wptcb); /* 加入運行隊列 */
}
else if (pSem->SemCnt > 1) /* 廣播方式喚醒所有等待該信號量的任務(wù) */
{
while (ptcb != NULL)
{
wptcb = ptcb->QNext;
OS_EnterRunQ(ptcb); /* 加入運行隊列 */
ptcb = wptcb;
}
}
OS_EXIT_CRITICAL();
OS_Sched();
}
/*********************************************************************
*函 數(shù) 名:API_SemAccept
*描 述:無等待獲取信號量
*輸入?yún)?shù):pSem: 信號量結(jié)構(gòu)體指針
*輸出參數(shù):無
*返 回 值: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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -