os_sem.c
上传用户:dongxin
上传日期:2022-06-22
资源大小:370k
文件大小:29k
源码类别:

uCOS

开发平台:

Others

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