zoukankan      html  css  js  c++  java
  • uC/OS-II信号(OS_sem)块

    /*
    *********************************************************************************************************
    *                                                uC/OS-II
    *                                          The Real-Time Kernel
    *                                          SEMAPHORE MANAGEMENT
    *
    *                          (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
    *                                           All Rights Reserved
    *
    * File : OS_SEM.C
    * By   : Jean J. Labrosse
    *********************************************************************************************************
    */

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

    #if OS_SEM_EN > 0
    /*
    *********************************************************************************************************
    *                                           ACCEPT SEMAPHORE
    *
    * Description: This function checks the semaphore to see if a resource is available or, if an event
    *              occurred.  Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
    *              resource is not available or the event did not occur.
    *
    * Arguments  : pevent     is a pointer to the event control block
    *
    * Returns    : >  0       if the resource is available or the event did not occur the semaphore is
    *                         decremented to obtain the resource.
    *              == 0       if the resource is not available or the event did not occur or,
    *                         if 'pevent' is a NULL pointer or,
    *                         if you didn't pass a pointer to a semaphore
    *********************************************************************************************************
    */
    //无等待请求信号量--这函数function:当一个任务请求信号量时,如果希望在信
    //量无效时准许任务不进入等待状态而继续运行,则不调用函数OSSPend 而是调用本函数OSSemAccept
    #if OS_SEM_ACCEPT_EN > 0
    INT16U  OSSemAccept (OS_EVENT *pevent)
    {
    #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
        OS_CPU_SR  cpu_sr;
    #endif    
        INT16U     cnt;


    #if OS_ARG_CHK_EN > 0
        if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
            return (0);
        }
        if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
            return (0);
        }
    #endif
        OS_ENTER_CRITICAL();
        cnt = pevent->OSEventCnt;
        //See if resource is available
        if (cnt > 0) {                                    /* See if resource is available                  */
            pevent->OSEventCnt--;                         /* Yes, decrement semaphore and notify caller    */
        }
        OS_EXIT_CRITICAL();
        return (cnt);                                     /* Return semaphore count                        */
    }
    #endif    

    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                           CREATE A SEMAPHORE
    *
    * Description: This function creates a semaphore.
    *
    * Arguments  : cnt           is the initial value for the semaphore.  If the value is 0, no resource is
    *                            available (or no event has occurred).  You initialize the semaphore to a
    *                            non-zero value to specify how many resources are available (e.g. if you have
    *                            10 resources, you would initialize the semaphore to 10).
    *
    * Returns    : != (void *)0  is a pointer to the event control clock (OS_EVENT) associated with the
    *                            created semaphore
    *              == (void *)0  if no event control blocks were available
    *********************************************************************************************************
    */
    //This function creates a semaphore.
    OS_EVENT  *OSSemCreate (INT16U cnt)
    {
    #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
        OS_CPU_SR  cpu_sr;
    #endif    
        OS_EVENT  *pevent;

        
        if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
            return ((OS_EVENT *)0);                            /* ... can't CREATE from an ISR             */
        }
        OS_ENTER_CRITICAL();
        /* Get next free event control block        */
        pevent = OSEventFreeList;                              /* Get next free event control block        */
        if (OSEventFreeList != (OS_EVENT *)0) {                /* See if pool of free ECB pool was empty   */
            OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
        }
        OS_EXIT_CRITICAL();
        if (pevent != (OS_EVENT *)0) {                         /* Get an event control block               */
            pevent->OSEventType = OS_EVENT_TYPE_SEM;            //OS_EVENT_TYPE_SEM信号量类型
            pevent->OSEventCnt  = cnt;                         /* Set semaphore value                      */
            pevent->OSEventPtr  = (void *)0;                   /* Unlink from ECB free list                */
            //初始化一个信号量 Initialize to 'nobody waiting' on sem.  
            OS_EventWaitListInit(pevent);                      /* Initialize to 'nobody waiting' on sem.   */
        }
        return (pevent);
    }

    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                         DELETE A SEMAPHORE
    *
    * Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
    *
    * Arguments  : pevent        is a pointer to the event control block associated with the desired
    *                            semaphore.
    *
    *              opt           determines delete options as follows:
    *                            opt == OS_DEL_NO_PEND   Delete semaphore ONLY if no task pending
    *                            opt == OS_DEL_ALWAYS    Deletes the semaphore even if tasks are waiting.
    *                                                    In this case, all the tasks pending will be readied.
    *
    *              err           is a pointer to an error code that can contain one of the following values:
    *                            OS_NO_ERR               The call was successful and the semaphore was deleted
    *                            OS_ERR_DEL_ISR          If you attempted to delete the semaphore from an ISR
    *                            OS_ERR_INVALID_OPT      An invalid option was specified
    *                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the semaphore
    *                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a semaphore
    *                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
    *
    * Returns    : pevent        upon error
    *              (OS_EVENT *)0 if the semaphore was successfully deleted.
    *
    * Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
    *                 the semaphore MUST check the return code of OSSemPend().
    *              2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
    *                 they check 'pevent' to see that it's a NULL pointer.
    *              3) This call can potentially disable interrupts for a long time.  The interrupt disable
    *                 time is directly proportional to the number of tasks waiting on the semaphore.
    *              4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
    *                 applications where the semaphore is used for mutual exclusion because the resource(s)
    *                 will no longer be guarded by the semaphore.
    *********************************************************************************************************
    */
    //This function deletes a semaphore and readies all tasks pending on the semaphore  opt指明信号量的删除条件
    #if OS_SEM_DEL_EN > 0
    OS_EVENT  *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
    {
    #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
        OS_CPU_SR  cpu_sr;
    #endif    
        BOOLEAN    tasks_waiting;
        
        //各种判断
        if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
            *err = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */
            return (pevent);
        }
    #if OS_ARG_CHK_EN > 0
        if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
            *err = OS_ERR_PEVENT_NULL;
            return (pevent);
        }
        if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
            *err = OS_ERR_EVENT_TYPE;
            return (pevent);
        }
    #endif
        OS_ENTER_CRITICAL();
        //See if any tasks waiting on semaphore
        if (pevent->OSEventGrp != 0x00) {                      /* See if any tasks waiting on semaphore    */
            tasks_waiting = TRUE;                              /* Yes                                      */
        } else {
            tasks_waiting = FALSE;                             /* No                                       */
        }
        switch (opt) {
            // Delete semaphore only if no task waiting
            case OS_DEL_NO_PEND:                               /* Delete semaphore only if no task waiting */
                 if (tasks_waiting == FALSE) {
                     pevent->OSEventType = OS_EVENT_TYPE_UNUSED;//0
                     pevent->OSEventPtr  = OSEventFreeList;    /* Return Event Control Block to free list  */
                     OSEventFreeList     = pevent;             /* Get next free event control block        */
                     OS_EXIT_CRITICAL();
                     *err = OS_NO_ERR;
                    // Semaphore has been deleted  
                     return ((OS_EVENT *)0);                   /* Semaphore has been deleted               */
                 } else {
                     OS_EXIT_CRITICAL();
                     *err = OS_EpeventRR_TASK_WAITING;
                     return ();
                 }
            //Always delete the semaphore   无论如何都删除
            case OS_DEL_ALWAYS:                                /* Always delete the semaphore              */
                 while (pevent->OSEventGrp != 0x00) {          /* Ready ALL tasks waiting for semaphore    */
                     //若事件就绪不为0  说明有任务等待  --让任务就绪
                     OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);
                 }
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
                 pevent->OSEventPtr  = OSEventFreeList;        /* Return Event Control Block to free list  */
                 OSEventFreeList     = pevent;                 /* Get next free event control block        */
                 OS_EXIT_CRITICAL();
                 if (tasks_waiting == TRUE) {                  /* Reschedule only if task(s) were waiting  */
                    //若任务是在等待的话
                     OS_Sched();                               /* Find highest priority task ready to run  */
                 }
                 *err = OS_NO_ERR;
                 return ((OS_EVENT *)0);                       /* Semaphore has been deleted               */

            default:
                 OS_EXIT_CRITICAL();
                 *err = OS_ERR_INVALID_OPT;
                 return (pevent);
        }
    }
    #endif

    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                           PEND ON SEMAPHORE
    *
    * Description: This function waits for a semaphore.
    *
    * Arguments  : pevent        is a pointer to the event control block associated with the desired
    *                            semaphore.
    *
    *              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
    *                            wait for the resource up to the amount of time specified by this argument.
    *                            If you specify 0, however, your task will wait forever at the specified
    *                            semaphore or, until the resource becomes available (or the event occurs).
    *
    *              err           is a pointer to where an error message will be deposited.  Possible error
    *                            messages are:
    *
    *                            OS_NO_ERR           The call was successful and your task owns the resource
    *                                                or, the event you are waiting for occurred.
    *                            OS_TIMEOUT          The semaphore was not received within the specified
    *                                                timeout.
    *                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
    *                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
    *                                                would lead to a suspension.
    *                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
    *
    * Returns    : none
    *********************************************************************************************************
    */
    //This function waits for a semaphore. timeout--表示等待时延0也就是说防止
    //得不到信号量而处于长期的等待状态,函数容许用时间延迟来设置一个时间限制---pevent表示被请求信号量的指针
    void  OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
    {
    #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
        OS_CPU_SR  cpu_sr;
    #endif    

        //各种判断
        if (OSIntNesting > 0) {                           /* See if called from ISR ...                    */
            *err = OS_ERR_PEND_ISR;                       /* ... can't PEND from an ISR                    */
            return;
        }
    #if OS_ARG_CHK_EN > 0
        if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
            *err = OS_ERR_PEVENT_NULL;
            return;
        }
        if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
            *err = OS_ERR_EVENT_TYPE;
            return;
        }
    #endif
        OS_ENTER_CRITICAL();
        //成立  表示资源可用
        if (pevent->OSEventCnt > 0) {                     /* If sem. is positive, resource available ...   */
            //信号量计数器减一
            pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
            OS_EXIT_CRITICAL();
            *err = OS_NO_ERR;
            return;
        }
        //否则
                                                          /* Otherwise, must wait until event occurs       */
        OSTCBCur->OSTCBStat |= OS_STAT_SEM;               /* Resource not available, pend on semaphore     */
        OSTCBCur->OSTCBDly   = timeout;                   /* Store pend timeout in TCB                     */
        OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
        OS_EXIT_CRITICAL();
        OS_Sched();                                       /* Find next highest priority task ready         */
        
        OS_ENTER_CRITICAL();
        if (OSTCBCur->OSTCBStat & OS_STAT_SEM) {          /* Must have timed out if still waiting for event*/
            // to make a task ready to run because a timeout occurred.
            OS_EventTO(pevent);
            OS_EXIT_CRITICAL();
            *err = OS_TIMEOUT;                            /* Indicate that didn't get event within TO      */
            return;
        }
        OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
    }
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                         POST TO A SEMAPHORE
    *
    * Description: This function signals a semaphore
    *
    * Arguments  : pevent        is a pointer to the event control block associated with the desired
    *                            semaphore.
    *
    * Returns    : OS_NO_ERR           The call was successful and the semaphore was signaled.
    *              OS_SEM_OVF          If the semaphore count exceeded its limit.  In other words, you have
    *                                  signalled the semaphore more often than you waited on it with either
    *                                  OSSemAccept() or OSSemPend().
    *              OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore
    *              OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
    *********************************************************************************************************
    */
    //发送信号量--也就是释放一个信号量
    INT8U  OSSemPost (OS_EVENT *pevent)
    {
    #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
        OS_CPU_SR  cpu_sr;                               
    #endif    


    #if OS_ARG_CHK_EN > 0
        if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
            return (OS_ERR_PEVENT_NULL);
        }
        if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
            return (OS_ERR_EVENT_TYPE);
        }
    #endif
        OS_ENTER_CRITICAL();
        //See if any task waiting for semaphore
        if (pevent->OSEventGrp != 0x00) {                      /* See if any task waiting for semaphore    */
            //Ready highest prio task waiting on event
            OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM);   /* Ready highest prio task waiting on event */
            OS_EXIT_CRITICAL();
            //任务调度
            OS_Sched();                                        /* Find highest priority task ready to run  */
            return (OS_NO_ERR);
        }
        //Make sure semaphore will not overflow  
        if (pevent->OSEventCnt < 65535) {                 /* Make sure semaphore will not overflow         */
        //信号计数器加1
            pevent->OSEventCnt++;                         /* Increment semaphore count to register event   */
            OS_EXIT_CRITICAL();
            return (OS_NO_ERR);
        }
        OS_EXIT_CRITICAL();                               /* Semaphore value has reached its maximum       */
        return (OS_SEM_OVF);
    }
    /*$PAGE*/
    /*
    *********************************************************************************************************
    *                                          QUERY A SEMAPHORE
    *
    * Description: This function obtains information about a semaphore
    *
    * Arguments  : pevent        is a pointer to the event control block associated with the desired
    *                            semaphore
    *
    *              pdata         is a pointer to a structure that will contain information about the
    *                            semaphore.
    *
    * Returns    : OS_NO_ERR           The call was successful and the message was sent
    *              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non semaphore.
    *              OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
    *********************************************************************************************************
    */
    //This function obtains/获取 information about a semaphore  pdata存储信号量状态的结构OS_SEM_DATA---结构体指针
    #if OS_SEM_QUERY_EN > 0
    INT8U  OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
    {
    #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
        OS_CPU_SR  cpu_sr;
    #endif    
        INT8U     *psrc;
        INT8U     *pdest;

    //判断
    #if OS_ARG_CHK_EN > 0
        if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
            return (OS_ERR_PEVENT_NULL);
        }
        if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
            return (OS_ERR_EVENT_TYPE);
        }
    #endif
        OS_ENTER_CRITICAL();
        pdata->OSEventGrp = pevent->OSEventGrp;                /* Copy message mailbox wait list           */
        psrc              = &pevent->OSEventTbl[0];
        pdest             = &pdata->OSEventTbl[0];
    #if OS_EVENT_TBL_SIZE > 0
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 1
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 2
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 3
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 4
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 5
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 6
        *pdest++          = *psrc++;
    #endif

    #if OS_EVENT_TBL_SIZE > 7
        *pdest            = *psrc;
    #endif
        pdata->OSCnt      = pevent->OSEventCnt;                /* Get semaphore count                      */
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }
    #endif                                                     /* OS_SEM_QUERY_EN                          */
    #endif                                                     /* OS_SEM_EN                                */

  • 相关阅读:
    第一节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
    Tensorflow 错误:Unknown command line flag 'f'
    Python 多线程总结
    Git 强制拉取覆盖本地所有文件
    Hive常用函数 傻瓜学习笔记 附完整示例
    Linux 删除指定大小(范围)的文件
    Python 操作 HBase —— Trift Trift2 Happybase 安装使用
    梯度消失 梯度爆炸 梯度偏置 梯度饱和 梯度死亡 文献收藏
    Embedding 文献收藏
    深度学习在CTR预估中的应用 文献收藏
  • 原文地址:https://www.cnblogs.com/wxb20/p/6230846.html
Copyright © 2011-2022 走看看