⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sem.c

📁 Rabbit 32Bit RTOS源代码
💻 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 + -