os_sem.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:29k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                          SEMAPHORE MANAGEMENT
  6. *
  7. *                              (c) Copyright 1992-2009, Micrium, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File    : OS_SEM.C
  11. * By      : Jean J. Labrosse
  12. * Version : V2.88
  13. *
  14. * LICENSING TERMS:
  15. * ---------------
  16. *   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.  
  17. * If you plan on using  uC/OS-II  in a commercial product you need to contact Micri祄 to properly license 
  18. * its use in your product. We provide ALL the source code for your convenience and to help you experience 
  19. * uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a 
  20. * licensing fee.
  21. *********************************************************************************************************
  22. */
  23. #ifndef  OS_MASTER_FILE
  24. #include <ucos_ii.h>
  25. #endif
  26. #if OS_SEM_EN > 0
  27. /*$PAGE*/
  28. /*
  29. *********************************************************************************************************
  30. *                                           ACCEPT SEMAPHORE
  31. *
  32. * Description: This function checks the semaphore to see if a resource is available or, if an event
  33. *              occurred.  Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
  34. *              resource is not available or the event did not occur.
  35. *
  36. * Arguments  : pevent     is a pointer to the event control block
  37. *
  38. * Returns    : >  0       if the resource is available or the event did not occur the semaphore is
  39. *                         decremented to obtain the resource.
  40. *              == 0       if the resource is not available or the event did not occur or,
  41. *                         if 'pevent' is a NULL pointer or,
  42. *                         if you didn't pass a pointer to a semaphore
  43. *********************************************************************************************************
  44. */
  45. #if OS_SEM_ACCEPT_EN > 0
  46. INT16U  OSSemAccept (OS_EVENT *pevent)
  47. {
  48.     INT16U     cnt;
  49. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  50.     OS_CPU_SR  cpu_sr = 0;
  51. #endif
  52. #if OS_ARG_CHK_EN > 0
  53.     if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  54.         return (0);
  55.     }
  56. #endif
  57.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
  58.         return (0);
  59.     }
  60.     OS_ENTER_CRITICAL();
  61.     cnt = pevent->OSEventCnt;
  62.     if (cnt > 0) {                                    /* See if resource is available                  */
  63.         pevent->OSEventCnt--;                         /* Yes, decrement semaphore and notify caller    */
  64.     }
  65.     OS_EXIT_CRITICAL();
  66.     return (cnt);                                     /* Return semaphore count                        */
  67. }
  68. #endif
  69. /*$PAGE*/
  70. /*
  71. *********************************************************************************************************
  72. *                                           CREATE A SEMAPHORE
  73. *
  74. * Description: This function creates a semaphore.
  75. *
  76. * Arguments  : cnt           is the initial value for the semaphore.  If the value is 0, no resource is
  77. *                            available (or no event has occurred).  You initialize the semaphore to a
  78. *                            non-zero value to specify how many resources are available (e.g. if you have
  79. *                            10 resources, you would initialize the semaphore to 10).
  80. *
  81. * Returns    : != (void *)0  is a pointer to the event control block (OS_EVENT) associated with the
  82. *                            created semaphore
  83. *              == (void *)0  if no event control blocks were available
  84. *********************************************************************************************************
  85. */
  86. OS_EVENT  *OSSemCreate (INT16U cnt)
  87. {
  88.     OS_EVENT  *pevent;
  89. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  90.     OS_CPU_SR  cpu_sr = 0;
  91. #endif
  92.     if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  93.         return ((OS_EVENT *)0);                            /* ... can't CREATE from an ISR             */
  94.     }
  95.     OS_ENTER_CRITICAL();
  96.     pevent = OSEventFreeList;                              /* Get next free event control block        */
  97.     if (OSEventFreeList != (OS_EVENT *)0) {                /* See if pool of free ECB pool was empty   */
  98.         OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  99.     }
  100.     OS_EXIT_CRITICAL();
  101.     if (pevent != (OS_EVENT *)0) {                         /* Get an event control block               */
  102.         pevent->OSEventType    = OS_EVENT_TYPE_SEM;
  103.         pevent->OSEventCnt     = cnt;                      /* Set semaphore value                      */
  104.         pevent->OSEventPtr     = (void *)0;                /* Unlink from ECB free list                */
  105. #if OS_EVENT_NAME_EN > 0
  106.         pevent->OSEventName    = "?";                       /* Unknown name                             */
  107. #endif
  108.         OS_EventWaitListInit(pevent);                      /* Initialize to 'nobody waiting' on sem.   */
  109.     }
  110.     return (pevent);
  111. }
  112. /*$PAGE*/
  113. /*
  114. *********************************************************************************************************
  115. *                                         DELETE A SEMAPHORE
  116. *
  117. * Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
  118. *
  119. * Arguments  : pevent        is a pointer to the event control block associated with the desired
  120. *                            semaphore.
  121. *
  122. *              opt           determines delete options as follows:
  123. *                            opt == OS_DEL_NO_PEND   Delete semaphore ONLY if no task pending
  124. *                            opt == OS_DEL_ALWAYS    Deletes the semaphore even if tasks are waiting.
  125. *                                                    In this case, all the tasks pending will be readied.
  126. *
  127. *              perr          is a pointer to an error code that can contain one of the following values:
  128. *                            OS_ERR_NONE             The call was successful and the semaphore was deleted
  129. *                            OS_ERR_DEL_ISR          If you attempted to delete the semaphore from an ISR
  130. *                            OS_ERR_INVALID_OPT      An invalid option was specified
  131. *                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the semaphore
  132. *                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a semaphore
  133. *                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
  134. *
  135. * Returns    : pevent        upon error
  136. *              (OS_EVENT *)0 if the semaphore was successfully deleted.
  137. *
  138. * Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
  139. *                 the semaphore MUST check the return code of OSSemPend().
  140. *              2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
  141. *                 they check 'pevent' to see that it's a NULL pointer.
  142. *              3) This call can potentially disable interrupts for a long time.  The interrupt disable
  143. *                 time is directly proportional to the number of tasks waiting on the semaphore.
  144. *              4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
  145. *                 applications where the semaphore is used for mutual exclusion because the resource(s)
  146. *                 will no longer be guarded by the semaphore.
  147. *********************************************************************************************************
  148. */
  149. #if OS_SEM_DEL_EN > 0
  150. OS_EVENT  *OSSemDel (OS_EVENT  *pevent, 
  151.                      INT8U      opt, 
  152.                      INT8U     *perr)
  153. {
  154.     BOOLEAN    tasks_waiting;
  155.     OS_EVENT  *pevent_return;
  156. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  157.     OS_CPU_SR  cpu_sr = 0;
  158. #endif
  159. #if OS_ARG_CHK_EN > 0
  160.     if (perr == (INT8U *)0) {                              /* Validate 'perr'                          */
  161.         return (pevent);
  162.     }
  163.     if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  164.         *perr = OS_ERR_PEVENT_NULL;
  165.         return (pevent);
  166.     }
  167. #endif
  168.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
  169.         *perr = OS_ERR_EVENT_TYPE;
  170.         return (pevent);
  171.     }
  172.     if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  173.         *perr = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */
  174.         return (pevent);
  175.     }
  176.     OS_ENTER_CRITICAL();
  177.     if (pevent->OSEventGrp != 0) {                         /* See if any tasks waiting on semaphore    */
  178.         tasks_waiting = OS_TRUE;                           /* Yes                                      */
  179.     } else {
  180.         tasks_waiting = OS_FALSE;                          /* No                                       */
  181.     }
  182.     switch (opt) {
  183.         case OS_DEL_NO_PEND:                               /* Delete semaphore only if no task waiting */
  184.              if (tasks_waiting == OS_FALSE) {
  185. #if OS_EVENT_NAME_EN > 0
  186.                  pevent->OSEventName    = "?";             /* Unknown name                             */
  187. #endif
  188.                  pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
  189.                  pevent->OSEventPtr     = OSEventFreeList; /* Return Event Control Block to free list  */
  190.                  pevent->OSEventCnt     = 0;
  191.                  OSEventFreeList        = pevent;          /* Get next free event control block        */
  192.                  OS_EXIT_CRITICAL();
  193.                  *perr                  = OS_ERR_NONE;
  194.                  pevent_return          = (OS_EVENT *)0;   /* Semaphore has been deleted               */
  195.              } else {
  196.                  OS_EXIT_CRITICAL();
  197.                  *perr                  = OS_ERR_TASK_WAITING;
  198.                  pevent_return          = pevent;
  199.              }
  200.              break;
  201.         case OS_DEL_ALWAYS:                                /* Always delete the semaphore              */
  202.              while (pevent->OSEventGrp != 0) {             /* Ready ALL tasks waiting for semaphore    */
  203.                  (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
  204.              }
  205. #if OS_EVENT_NAME_EN > 0
  206.              pevent->OSEventName    = "?";                 /* Unknown name                             */
  207. #endif
  208.              pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
  209.              pevent->OSEventPtr     = OSEventFreeList;     /* Return Event Control Block to free list  */
  210.              pevent->OSEventCnt     = 0;
  211.              OSEventFreeList        = pevent;              /* Get next free event control block        */
  212.              OS_EXIT_CRITICAL();
  213.              if (tasks_waiting == OS_TRUE) {               /* Reschedule only if task(s) were waiting  */
  214.                  OS_Sched();                               /* Find highest priority task ready to run  */
  215.              }
  216.              *perr                  = OS_ERR_NONE;
  217.              pevent_return          = (OS_EVENT *)0;       /* Semaphore has been deleted               */
  218.              break;
  219.         default:
  220.              OS_EXIT_CRITICAL();
  221.              *perr                  = OS_ERR_INVALID_OPT;
  222.              pevent_return          = pevent;
  223.              break;
  224.     }
  225.     return (pevent_return);
  226. }
  227. #endif
  228. /*$PAGE*/
  229. /*
  230. *********************************************************************************************************
  231. *                                           PEND ON SEMAPHORE
  232. *
  233. * Description: This function waits for a semaphore.
  234. *
  235. * Arguments  : pevent        is a pointer to the event control block associated with the desired
  236. *                            semaphore.
  237. *
  238. *              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
  239. *                            wait for the resource up to the amount of time specified by this argument.
  240. *                            If you specify 0, however, your task will wait forever at the specified
  241. *                            semaphore or, until the resource becomes available (or the event occurs).
  242. *
  243. *              perr          is a pointer to where an error message will be deposited.  Possible error
  244. *                            messages are:
  245. *
  246. *                            OS_ERR_NONE         The call was successful and your task owns the resource
  247. *                                                or, the event you are waiting for occurred.
  248. *                            OS_ERR_TIMEOUT      The semaphore was not received within the specified
  249. *                                                'timeout'.
  250. *                            OS_ERR_PEND_ABORT   The wait on the semaphore was aborted.
  251. *                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
  252. *                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
  253. *                                                would lead to a suspension.
  254. *                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
  255. *                            OS_ERR_PEND_LOCKED  If you called this function when the scheduler is locked
  256. *
  257. * Returns    : none
  258. *********************************************************************************************************
  259. */
  260. /*$PAGE*/
  261. void  OSSemPend (OS_EVENT  *pevent, 
  262.                  INT32U     timeout, 
  263.                  INT8U     *perr)
  264. {
  265. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  266.     OS_CPU_SR  cpu_sr = 0;
  267. #endif
  268. #if OS_ARG_CHK_EN > 0
  269.     if (perr == (INT8U *)0) {                         /* Validate 'perr'                               */
  270.         return;
  271.     }
  272.     if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  273.         *perr = OS_ERR_PEVENT_NULL;
  274.         return;
  275.     }
  276. #endif
  277.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
  278.         *perr = OS_ERR_EVENT_TYPE;
  279.         return;
  280.     }
  281.     if (OSIntNesting > 0) {                           /* See if called from ISR ...                    */
  282.         *perr = OS_ERR_PEND_ISR;                      /* ... can't PEND from an ISR                    */
  283.         return;
  284.     }
  285.     if (OSLockNesting > 0) {                          /* See if called with scheduler locked ...       */
  286.         *perr = OS_ERR_PEND_LOCKED;                   /* ... can't PEND when locked                    */
  287.         return;
  288.     }
  289.     OS_ENTER_CRITICAL();
  290.     if (pevent->OSEventCnt > 0) {                     /* If sem. is positive, resource available ...   */
  291.         pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
  292.         OS_EXIT_CRITICAL();
  293.         *perr = OS_ERR_NONE;
  294.         return;
  295.     }
  296.                                                       /* Otherwise, must wait until event occurs       */
  297.     OSTCBCur->OSTCBStat     |= OS_STAT_SEM;           /* Resource not available, pend on semaphore     */
  298.     OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;
  299.     OSTCBCur->OSTCBDly       = timeout;               /* Store pend timeout in TCB                     */
  300.     OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
  301.     OS_EXIT_CRITICAL();
  302.     OS_Sched();                                       /* Find next highest priority task ready         */
  303.     OS_ENTER_CRITICAL();
  304.     switch (OSTCBCur->OSTCBStatPend) {                /* See if we timed-out or aborted                */
  305.         case OS_STAT_PEND_OK:
  306.              *perr = OS_ERR_NONE;
  307.              break;
  308.         case OS_STAT_PEND_ABORT:
  309.              *perr = OS_ERR_PEND_ABORT;               /* Indicate that we aborted                      */
  310.              break;
  311.         case OS_STAT_PEND_TO:
  312.         default:        
  313.              OS_EventTaskRemove(OSTCBCur, pevent);
  314.              *perr = OS_ERR_TIMEOUT;                  /* Indicate that we didn't get event within TO   */
  315.              break;
  316.     }
  317.     OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */
  318.     OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */
  319.     OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
  320. #if (OS_EVENT_MULTI_EN > 0)
  321.     OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
  322. #endif
  323.     OS_EXIT_CRITICAL();
  324. }
  325. /*$PAGE*/
  326. /*
  327. *********************************************************************************************************
  328. *                                      ABORT WAITING ON A SEMAPHORE
  329. *
  330. * Description: This function aborts & readies any tasks currently waiting on a semaphore.  This function 
  331. *              should be used to fault-abort the wait on the semaphore, rather than to normally signal
  332. *              the semaphore via OSSemPost().
  333. *
  334. * Arguments  : pevent        is a pointer to the event control block associated with the desired
  335. *                            semaphore.
  336. *
  337. *              opt           determines the type of ABORT performed:
  338. *                            OS_PEND_OPT_NONE         ABORT wait for a single task (HPT) waiting on the
  339. *                                                     semaphore
  340. *                            OS_PEND_OPT_BROADCAST    ABORT wait for ALL tasks that are  waiting on the
  341. *                                                     semaphore
  342. *
  343. *              perr          is a pointer to where an error message will be deposited.  Possible error
  344. *                            messages are:
  345. *
  346. *                            OS_ERR_NONE         No tasks were     waiting on the semaphore.
  347. *                            OS_ERR_PEND_ABORT   At least one task waiting on the semaphore was readied
  348. *                                                and informed of the aborted wait; check return value 
  349. *                                                for the number of tasks whose wait on the semaphore 
  350. *                                                was aborted.
  351. *                            OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore.
  352. *                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
  353. *
  354. * Returns    : == 0          if no tasks were waiting on the semaphore, or upon error.
  355. *              >  0          if one or more tasks waiting on the semaphore are now readied and informed.
  356. *********************************************************************************************************
  357. */
  358. #if OS_SEM_PEND_ABORT_EN > 0
  359. INT8U  OSSemPendAbort (OS_EVENT  *pevent, 
  360.                        INT8U      opt, 
  361.                        INT8U     *perr)
  362. {
  363.     INT8U      nbr_tasks;
  364. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  365.     OS_CPU_SR  cpu_sr = 0;
  366. #endif
  367. #if OS_ARG_CHK_EN > 0
  368.     if (perr == (INT8U *)0) {                         /* Validate 'perr'                               */
  369.         return (0);
  370.     }
  371.     if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  372.         *perr = OS_ERR_PEVENT_NULL;
  373.         return (0);
  374.     }
  375. #endif
  376.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
  377.         *perr = OS_ERR_EVENT_TYPE;
  378.         return (0);
  379.     }
  380.     OS_ENTER_CRITICAL();
  381.     if (pevent->OSEventGrp != 0) {                    /* See if any task waiting on semaphore?         */
  382.         nbr_tasks = 0;
  383.         switch (opt) {
  384.             case OS_PEND_OPT_BROADCAST:               /* Do we need to abort ALL waiting tasks?        */
  385.                  while (pevent->OSEventGrp != 0) {    /* Yes, ready ALL tasks waiting on semaphore     */
  386.                      (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  387.                      nbr_tasks++;
  388.                  }
  389.                  break;
  390.                  
  391.             case OS_PEND_OPT_NONE:
  392.             default:                                  /* No,  ready HPT       waiting on semaphore     */
  393.                  (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  394.                  nbr_tasks++;
  395.                  break;
  396.         }
  397.         OS_EXIT_CRITICAL();
  398.         OS_Sched();                                   /* Find HPT ready to run                         */
  399.         *perr = OS_ERR_PEND_ABORT;
  400.         return (nbr_tasks);
  401.     }
  402.     OS_EXIT_CRITICAL();
  403.     *perr = OS_ERR_NONE;
  404.     return (0);                                       /* No tasks waiting on semaphore                 */
  405. }
  406. #endif
  407. /*$PAGE*/
  408. /*
  409. *********************************************************************************************************
  410. *                                         POST TO A SEMAPHORE
  411. *
  412. * Description: This function signals a semaphore
  413. *
  414. * Arguments  : pevent        is a pointer to the event control block associated with the desired
  415. *                            semaphore.
  416. *
  417. * Returns    : OS_ERR_NONE         The call was successful and the semaphore was signaled.
  418. *              OS_ERR_SEM_OVF      If the semaphore count exceeded its limit.  In other words, you have
  419. *                                  signalled the semaphore more often than you waited on it with either
  420. *                                  OSSemAccept() or OSSemPend().
  421. *              OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a semaphore
  422. *              OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer.
  423. *********************************************************************************************************
  424. */
  425. INT8U  OSSemPost (OS_EVENT *pevent)
  426. {
  427. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  428.     OS_CPU_SR  cpu_sr = 0;
  429. #endif
  430. #if OS_ARG_CHK_EN > 0
  431.     if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  432.         return (OS_ERR_PEVENT_NULL);
  433.     }
  434. #endif
  435.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
  436.         return (OS_ERR_EVENT_TYPE);
  437.     }
  438.     OS_ENTER_CRITICAL();
  439.     if (pevent->OSEventGrp != 0) {                    /* See if any task waiting for semaphore         */
  440.                                                       /* Ready HPT waiting on event                    */
  441.         (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
  442.         OS_EXIT_CRITICAL();
  443.         OS_Sched();                                   /* Find HPT ready to run                         */
  444.         return (OS_ERR_NONE);
  445.     }
  446.     if (pevent->OSEventCnt < 65535u) {                /* Make sure semaphore will not overflow         */
  447.         pevent->OSEventCnt++;                         /* Increment semaphore count to register event   */
  448.         OS_EXIT_CRITICAL();
  449.         return (OS_ERR_NONE);
  450.     }
  451.     OS_EXIT_CRITICAL();                               /* Semaphore value has reached its maximum       */
  452.     return (OS_ERR_SEM_OVF);
  453. }
  454. /*$PAGE*/
  455. /*
  456. *********************************************************************************************************
  457. *                                          QUERY A SEMAPHORE
  458. *
  459. * Description: This function obtains information about a semaphore
  460. *
  461. * Arguments  : pevent        is a pointer to the event control block associated with the desired
  462. *                            semaphore
  463. *
  464. *              p_sem_data    is a pointer to a structure that will contain information about the
  465. *                            semaphore.
  466. *
  467. * Returns    : OS_ERR_NONE         The call was successful and the message was sent
  468. *              OS_ERR_EVENT_TYPE   If you are attempting to obtain data from a non semaphore.
  469. *              OS_ERR_PEVENT_NULL  If 'pevent'     is a NULL pointer.
  470. *              OS_ERR_PDATA_NULL   If 'p_sem_data' is a NULL pointer
  471. *********************************************************************************************************
  472. */
  473. #if OS_SEM_QUERY_EN > 0
  474. INT8U  OSSemQuery (OS_EVENT     *pevent, 
  475.                    OS_SEM_DATA  *p_sem_data)
  476. {
  477. #if OS_LOWEST_PRIO <= 63
  478.     INT8U     *psrc;
  479.     INT8U     *pdest;
  480. #else
  481.     INT16U    *psrc;
  482.     INT16U    *pdest;
  483. #endif
  484.     INT8U      i;
  485. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  486.     OS_CPU_SR  cpu_sr = 0;
  487. #endif
  488. #if OS_ARG_CHK_EN > 0
  489.     if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  490.         return (OS_ERR_PEVENT_NULL);
  491.     }
  492.     if (p_sem_data == (OS_SEM_DATA *)0) {                  /* Validate 'p_sem_data'                    */
  493.         return (OS_ERR_PDATA_NULL);
  494.     }
  495. #endif
  496.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate event block type                */
  497.         return (OS_ERR_EVENT_TYPE);
  498.     }
  499.     OS_ENTER_CRITICAL();
  500.     p_sem_data->OSEventGrp = pevent->OSEventGrp;           /* Copy message mailbox wait list           */
  501.     psrc                   = &pevent->OSEventTbl[0];
  502.     pdest                  = &p_sem_data->OSEventTbl[0];
  503.     for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
  504.         *pdest++ = *psrc++;
  505.     }
  506.     p_sem_data->OSCnt = pevent->OSEventCnt;                /* Get semaphore count                      */
  507.     OS_EXIT_CRITICAL();
  508.     return (OS_ERR_NONE);
  509. }
  510. #endif                                                     /* OS_SEM_QUERY_EN                          */
  511. /*$PAGE*/
  512. /*
  513. *********************************************************************************************************
  514. *                                              SET SEMAPHORE
  515. *
  516. * Description: This function sets the semaphore count to the value specified as an argument.  Typically,
  517. *              this value would be 0.
  518. *
  519. *              You would typically use this function when a semaphore is used as a signaling mechanism
  520. *              and, you want to reset the count value.
  521. *
  522. * Arguments  : pevent     is a pointer to the event control block
  523. *
  524. *              cnt        is the new value for the semaphore count.  You would pass 0 to reset the
  525. *                         semaphore count.
  526. *
  527. *              perr       is a pointer to an error code returned by the function as follows:
  528. *
  529. *                            OS_ERR_NONE          The call was successful and the semaphore value was set.
  530. *                            OS_ERR_EVENT_TYPE    If you didn't pass a pointer to a semaphore.
  531. *                            OS_ERR_PEVENT_NULL   If 'pevent' is a NULL pointer.
  532. *                            OS_ERR_TASK_WAITING  If tasks are waiting on the semaphore.
  533. *********************************************************************************************************
  534. */
  535. #if OS_SEM_SET_EN > 0
  536. void  OSSemSet (OS_EVENT  *pevent, 
  537.                 INT16U     cnt, 
  538.                 INT8U     *perr)
  539. {
  540. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  541.     OS_CPU_SR  cpu_sr = 0;
  542. #endif
  543. #if OS_ARG_CHK_EN > 0
  544.     if (perr == (INT8U *)0) {                         /* Validate 'perr'                               */
  545.         return;
  546.     }
  547.     if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  548.         *perr = OS_ERR_PEVENT_NULL;
  549.         return;
  550.     }
  551. #endif
  552.     if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
  553.         *perr = OS_ERR_EVENT_TYPE;
  554.         return;
  555.     }
  556.     OS_ENTER_CRITICAL();
  557.     *perr = OS_ERR_NONE;
  558.     if (pevent->OSEventCnt > 0) {                     /* See if semaphore already has a count          */
  559.         pevent->OSEventCnt = cnt;                     /* Yes, set it to the new value specified.       */
  560.     } else {                                          /* No                                            */
  561.         if (pevent->OSEventGrp == 0) {                /*      See if task(s) waiting?                  */
  562.             pevent->OSEventCnt = cnt;                 /*      No, OK to set the value                  */
  563.         } else {
  564.             *perr              = OS_ERR_TASK_WAITING;
  565.         }
  566.     }
  567.     OS_EXIT_CRITICAL();
  568. }
  569. #endif
  570. #endif                                                /* OS_SEM_EN                                     */