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

📄 os_sem.c

📁 ucos_ii在S3C2410上的移植
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*********************************************************************************************************
*                                                uC/OS-II 实时内核
*                                                 信号量管理
*
*                            (c) 版权 1992-2002, 所有版权归Jean J. Labrosse, Weston, FL 所有
*                                         
*
* 文件名称 :          OS_SEM.C
* 程序作者 :          Jean J. Labrosse 
*********************************************************************************************************
*/

#ifndef  OS_MASTER_FILE
#include "includes.h"
#endif

#if OS_SEM_EN > 0
/*
*********************************************************************************************************
*                                           请求信号量
*
* 函数描述: 该函数检查信号量是否有效,或事件发生。假如资源无效或事件未发生,OSSemAccept()函数不和OSSemPend()
*           一样, 它不挂起调用的任务。
*
* 输入参数  : pevent     指向一个ECB的指针
*
* 返回值    : >  0       如果资源有效或事件未发生,信号量减少以获得资源。
*             == 0       如果资源无效或事件没有发生,或 'pevent' 是一个空指针,或没有传递一个信号量指针。
*********************************************************************************************************
*/

#if OS_SEM_ACCEPT_EN > 0
INT16U  OSSemAccept (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                                       /* 为CPU状态寄存器分配存储变量     */
    OS_CPU_SR  cpu_sr;
#endif    
    INT16U     cnt;


#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                                   /* 空指针 'pevent'          */
        return (0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM)
     {                                                            /* 无效的事件类型                  */
        return (0);
    }
#endif
    OS_ENTER_CRITICAL();
    cnt = pevent->OSEventCnt;
    if (cnt > 0) 
    {                                                  /* 看资源是否有效?                  */
        pevent->OSEventCnt--;                         /* 是,减少信号量,通知调用函数    */
    }
    OS_EXIT_CRITICAL();
    return (cnt);                                     /* 返回信号量计数器                        */
}
#endif    

/*$PAGE*/
/*
*********************************************************************************************************
*                                           建立一个信号量
*
* 函数描述: 该函数用于建立一个信号量
*
* 输入参数  : cnt           用于信号量的初始化.  如果是 0, 资源无效或没有事件发生。信号量初始化为非零值,则
*                           表示有多少资源可用。例如,如果有10个资源,则可初始化信号量为10。
*
* 返回值    : != (void *)0  是一个指向有已建信号量的事件任务块指针。
*             == (void *)0  无任何事件任务块可用
*********************************************************************************************************
*/

OS_EVENT  *OSSemCreate (INT16U cnt)
{
#if OS_CRITICAL_METHOD == 3                                         /*   为CPU状态寄存器分配存储变量   */
    OS_CPU_SR  cpu_sr;
#endif    
    OS_EVENT  *pevent;


    if (OSIntNesting > 0)                                                   /*    如果调用来自 ISR ... */
    {                                                                   
        return ((OS_EVENT *)0);                                    /* ... 从 ISR 中不能创建信号量      */
    }
    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                                       /*       得到空余事件控制块        */
    
    if (OSEventFreeList != (OS_EVENT *)0) 
    {                                                               /* 看空余事件控制块缓冲池是否为空?*/
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) 
    {                                                                  /*      得到一个事件控制块      */
        pevent->OSEventType = OS_EVENT_TYPE_SEM;
        pevent->OSEventCnt  = cnt;                                            /*     建立信号量值      */
        pevent->OSEventPtr  = (void *)0;                                      /* 从ECB空余链表中脱离   */
        OS_EventWaitListInit(pevent);                                         /*     初始化一个ECB     */
    }
    return (pevent);
}

/*$PAGE*/
/*
*********************************************************************************************************
*                                         删除一个信号量
*
* 函数描述:  该函数删除一个信号量,并且就绪所有有关信号量的挂起的任务。
*
* 输入参数: pevent        指向已建有期望的信号量的ECB的指针。
*
*             opt          确定删除选择项:
*                          opt == OS_DEL_NO_PEND   无等待的任务时,删除信号量
*                          opt == OS_DEL_ALWAYS    即使任务正在等待,也要删除信号量。
*                                                   该种情况下,所有挂起的任务都将就绪.
*
*             err          指向下列值之一的出错代码的指针:
*                          OS_NO_ERR               调用成功,信号量被删除
*                          OS_ERR_DEL_ISR          试图从ISR中删除信号量
*                          OS_ERR_INVALID_OPT      指定的选项无效
*                          OS_ERR_TASK_WAITING     一个或更多的任务正在等待信号量。
*                          OS_ERR_EVENT_TYPE       传递的不是信号量
*                          OS_ERR_PEVENT_NULL      'pevent' 是空指针
*
* 返回值    : pevent        上面的出错代码
*             (OS_EVENT *)0 信号量被成功删除
*
* 注释    :    1) 该函数使用时要小心.  期望信号量的任务一定要检查OSSemPend() 的返回值。
*              2) OSSemAccept()的调用不知道信号量已被删除,除非检查到 'pevent' 为一个空指针。
*              3) 这种调用潜在的关闭中断很长时间。中断关闭时间直接正比于等待信号量的任务的数量。
*              4) 由于所有等待信号量的任务将要就绪,所以必须在使用互斥型信号量的场合要小心。因为
*                 资源将不再被信号量保护。
*********************************************************************************************************
*/

#if OS_SEM_DEL_EN > 0
OS_EVENT  *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                                /* 为CPU状态寄存器分配存储变量 */
    OS_CPU_SR  cpu_sr;
#endif    
    BOOLEAN    tasks_waiting;


    if (OSIntNesting > 0) 
    {                                                      /* 如果调用来自 ISR ...                */
        *err = OS_ERR_DEL_ISR;                             /* ... 从ISR 不能删除信号量            */
        return (pevent);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) 
    {                                                     /* 空指针 'pevent'                        */
        *err = OS_ERR_PEVENT_NULL;
        return (pevent);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) 
    {                                                      /* 传递的不是信号量                */
        *err = OS_ERR_EVENT_TYPE;
        return (pevent);
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) 
    {                                                      /* 看任务是否在等待信号量?    */
        tasks_waiting = TRUE;                              /* 是                                      */
    } 
    else 
    {
        tasks_waiting = FALSE;                             /* 没有                                       */
    }
    switch (opt) 
    {
        case OS_DEL_NO_PEND:                               /* 只在没有等待的任务时,才删除信号量 */
             if (tasks_waiting == FALSE) 
             {
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
                 pevent->OSEventPtr  = OSEventFreeList;    /* 返回ECB到空余链表中  */
                 OSEventFreeList     = pevent;             /* 加入空余链表中        */
                 OS_EXIT_CRITICAL();
                 *err = OS_NO_ERR;
                 return ((OS_EVENT *)0);                   /* 信号量删除               */
             } 
             else 
             {
                 OS_EXIT_CRITICAL();
                 *err = OS_ERR_TASK_WAITING;
                 return (pevent);
             }

        case OS_DEL_ALWAYS:                                /* 即使任务正在等待,也要删除信号量        */
             while (pevent->OSEventGrp != 0x00) 
             {                                             /* 就绪等待信号量的所有任务    */
                 OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);
             }
             pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
             pevent->OSEventPtr  = OSEventFreeList;        /* 返回ECB到空余链表中  */
             OSEventFreeList     = pevent;                 /* 加入空余链表中        */
             OS_EXIT_CRITICAL();
             if (tasks_waiting == TRUE) 
             {                                               /* 删除信号量前,有任务等待,则切换任务  */
                 OS_Sched();                               /* 寻找最高优先级任务就绪运行  */
             }
             *err = OS_NO_ERR;
             return ((OS_EVENT *)0);                       /* 信号量删除              */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -