os_mutex.c
上传用户:yyyd609
上传日期:2022-07-18
资源大小:183k
文件大小:29k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                  MUTUAL EXCLUSION SEMAPHORE MANAGEMENT
  6. *
  7. *                          (c) Copyright 1992-2003, Jean J. Labrosse, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File    : OS_MUTEX.C
  11. * By      : Jean J. Labrosse
  12. * Version : V2.76
  13. *********************************************************************************************************
  14. */
  15. #ifndef  OS_MASTER_FILE
  16. #include <ucos_ii.h>
  17. #endif
  18. /*
  19. *********************************************************************************************************
  20. *                                            LOCAL CONSTANTS
  21. *********************************************************************************************************
  22. */
  23. #define  OS_MUTEX_KEEP_LOWER_8   0x00FF
  24. #define  OS_MUTEX_KEEP_UPPER_8   0xFF00
  25. #define  OS_MUTEX_AVAILABLE      0x00FF
  26. #if OS_MUTEX_EN > 0
  27. /*
  28. *********************************************************************************************************
  29. *                                   ACCEPT MUTUAL EXCLUSION SEMAPHORE
  30. *
  31. * Description: This  function checks the mutual exclusion semaphore to see if a resource is available.
  32. *              Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is
  33. *              not available or the event did not occur.
  34. *
  35. * Arguments  : pevent     is a pointer to the event control block
  36. *
  37. *              err        is a pointer to an error code which will be returned to your application:
  38. *                            OS_NO_ERR          if the call was successful.
  39. *                            OS_ERR_EVENT_TYPE  if 'pevent' is not a pointer to a mutex
  40. *                            OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
  41. *                            OS_ERR_PEND_ISR     if you called this function from an ISR
  42. *
  43. * Returns    : == 1       if the resource is available, the mutual exclusion semaphore is acquired
  44. *              == 0       a) if the resource is not available
  45. *                         b) you didn't pass a pointer to a mutual exclusion semaphore
  46. *                         c) you called this function from an ISR
  47. *
  48. * Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are
  49. *              intended to be used by tasks only.
  50. *********************************************************************************************************
  51. */
  52. #if OS_MUTEX_ACCEPT_EN > 0
  53. INT8U  OSMutexAccept (OS_EVENT *pevent, INT8U *err)
  54. {
  55. #if OS_CRITICAL_METHOD == 3                            /* Allocate storage for CPU status register     */
  56.     OS_CPU_SR  cpu_sr;
  57.     
  58.     
  59.     cpu_sr = 0;                                        /* Prevent compiler warning                     */
  60. #endif    
  61.     if (OSIntNesting > 0) {                            /* Make sure it's not called from an ISR        */
  62.         *err = OS_ERR_PEND_ISR;
  63.         return (0);
  64.     }
  65. #if OS_ARG_CHK_EN > 0
  66.     if (pevent == (OS_EVENT *)0) {                     /* Validate 'pevent'                            */
  67.         *err = OS_ERR_PEVENT_NULL;
  68.         return (0);
  69.     }
  70. #endif                                                     
  71.     if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {  /* Validate event block type                    */
  72.         *err = OS_ERR_EVENT_TYPE;
  73.         return (0);
  74.     }
  75.     OS_ENTER_CRITICAL();    /* Get value (0 or 1) of Mutex                  */
  76.     if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {     
  77.         pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;   /*      Mask off LSByte (Acquire Mutex)         */
  78.         pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;     /*      Save current task priority in LSByte    */
  79.         pevent->OSEventPtr  = (void *)OSTCBCur;        /*      Link TCB of task owning Mutex           */
  80.         OS_EXIT_CRITICAL();
  81.         *err = OS_NO_ERR;
  82.         return (1);
  83.     }
  84.     OS_EXIT_CRITICAL();
  85.     *err = OS_NO_ERR;
  86.     return (0);
  87. }
  88. #endif                                                     
  89. /*$PAGE*/
  90. /*
  91. *********************************************************************************************************
  92. *                                  CREATE A MUTUAL EXCLUSION SEMAPHORE
  93. *
  94. * Description: This function creates a mutual exclusion semaphore.
  95. *
  96. * Arguments  : prio          is the priority to use when accessing the mutual exclusion semaphore.  In
  97. *                            other words, when the semaphore is acquired and a higher priority task
  98. *                            attempts to obtain the semaphore then the priority of the task owning the
  99. *                            semaphore is raised to this priority.  It is assumed that you will specify
  100. *                            a priority that is LOWER in value than ANY of the tasks competing for the
  101. *                            mutex.
  102. *
  103. *              err           is a pointer to an error code which will be returned to your application:
  104. *                               OS_NO_ERR           if the call was successful.
  105. *                               OS_ERR_CREATE_ISR   if you attempted to create a MUTEX from an ISR
  106. *                               OS_PRIO_EXIST       if a task at the priority inheritance priority
  107. *                                                   already exist.
  108. *                               OS_ERR_PEVENT_NULL  No more event control blocks available.
  109. *                               OS_PRIO_INVALID     if the priority you specify is higher that the 
  110. *                                                   maximum allowed (i.e. > OS_LOWEST_PRIO)
  111. *
  112. * Returns    : != (void *)0  is a pointer to the event control clock (OS_EVENT) associated with the
  113. *                            created mutex.
  114. *              == (void *)0  if an error is detected.
  115. *
  116. * Note(s)    : 1) The LEAST significant 8 bits of '.OSEventCnt' are used to hold the priority number
  117. *                 of the task owning the mutex or 0xFF if no task owns the mutex.
  118. *              2) The MOST  significant 8 bits of '.OSEventCnt' are used to hold the priority number
  119. *                 to use to reduce priority inversion.
  120. *********************************************************************************************************
  121. */
  122. OS_EVENT  *OSMutexCreate (INT8U prio, INT8U *err)
  123. {
  124.     OS_EVENT  *pevent;
  125. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  126.     OS_CPU_SR  cpu_sr;
  127.     cpu_sr = 0;                                            /* Prevent compiler warning                 */
  128. #endif    
  129.     if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  130.         *err = OS_ERR_CREATE_ISR;                          /* ... can't CREATE mutex from an ISR       */
  131.         return ((OS_EVENT *)0);
  132.     }
  133. #if OS_ARG_CHK_EN > 0
  134.     if (prio >= OS_LOWEST_PRIO) {                          /* Validate PIP                             */
  135.         *err = OS_PRIO_INVALID;
  136.         return ((OS_EVENT *)0);
  137.     }
  138. #endif
  139.     OS_ENTER_CRITICAL();
  140.     if (OSTCBPrioTbl[prio] != (OS_TCB *)0) {               /* Mutex priority must not already exist    */
  141.         OS_EXIT_CRITICAL();                                /* Task already exist at priority ...       */
  142.         *err = OS_PRIO_EXIST;                              /* ... inheritance priority                 */
  143.         return ((OS_EVENT *)0);                            
  144.     }
  145.     OSTCBPrioTbl[prio] = (OS_TCB *)1;                      /* Reserve the table entry                  */
  146.     pevent             = OSEventFreeList;                  /* Get next free event control block        */
  147.     if (pevent == (OS_EVENT *)0) {                         /* See if an ECB was available              */
  148.         OSTCBPrioTbl[prio] = (OS_TCB *)0;                  /* No, Release the table entry              */
  149.         OS_EXIT_CRITICAL();
  150.         *err               = OS_ERR_PEVENT_NULL;           /* No more event control blocks             */
  151.         return (pevent);
  152.     }
  153.     OSEventFreeList        = (OS_EVENT *)OSEventFreeList->OSEventPtr;   /* Adjust the free list        */
  154.     OS_EXIT_CRITICAL();
  155.     pevent->OSEventType    = OS_EVENT_TYPE_MUTEX;
  156.     pevent->OSEventCnt     = ((INT16U)prio << 8) | OS_MUTEX_AVAILABLE;  /* Resource is available       */
  157.     pevent->OSEventPtr     = (void *)0;                                 /* No task owning the mutex    */
  158. #if OS_EVENT_NAME_SIZE > 1
  159.     pevent->OSEventName[0] = '?';
  160.     pevent->OSEventName[1] = OS_ASCII_NUL;
  161. #endif
  162.     OS_EventWaitListInit(pevent);
  163.     *err                   = OS_NO_ERR;
  164.     return (pevent);
  165. }
  166. /*$PAGE*/
  167. /*
  168. *********************************************************************************************************
  169. *                                          DELETE A MUTEX
  170. *
  171. * Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it.
  172. *
  173. * Arguments  : pevent        is a pointer to the event control block associated with the desired mutex.
  174. *
  175. *              opt           determines delete options as follows:
  176. *                            opt == OS_DEL_NO_PEND   Delete mutex ONLY if no task pending
  177. *                            opt == OS_DEL_ALWAYS    Deletes the mutex even if tasks are waiting.
  178. *                                                    In this case, all the tasks pending will be readied.
  179. *
  180. *              err           is a pointer to an error code that can contain one of the following values:
  181. *                            OS_NO_ERR               The call was successful and the mutex was deleted
  182. *                            OS_ERR_DEL_ISR          If you attempted to delete the MUTEX from an ISR
  183. *                            OS_ERR_INVALID_OPT      An invalid option was specified
  184. *                            OS_ERR_TASK_WAITING     One or more tasks were waiting on the mutex
  185. *                            OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mutex
  186. *                            OS_ERR_PEVENT_NULL      If 'pevent' is a NULL pointer.
  187. *
  188. * Returns    : pevent        upon error
  189. *              (OS_EVENT *)0 if the mutex was successfully deleted.
  190. *
  191. * Note(s)    : 1) This function must be used with care.  Tasks that would normally expect the presence of
  192. *                 the mutex MUST check the return code of OSMutexPend().
  193. *              2) This call can potentially disable interrupts for a long time.  The interrupt disable
  194. *                 time is directly proportional to the number of tasks waiting on the mutex.
  195. *              3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the
  196. *                 resource(s) will no longer be guarded by the mutex.
  197. *********************************************************************************************************
  198. */
  199. #if OS_MUTEX_DEL_EN
  200. OS_EVENT  *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
  201. {
  202.     BOOLEAN    tasks_waiting;
  203.     INT8U      pip;
  204. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  205.     OS_CPU_SR  cpu_sr;
  206.     cpu_sr = 0;                                            /* Prevent compiler warning                 */
  207. #endif    
  208.     if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  209.         *err = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */
  210.         return (pevent);
  211.     }
  212. #if OS_ARG_CHK_EN > 0
  213.     if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  214.         *err = OS_ERR_PEVENT_NULL;
  215.         return ((OS_EVENT *)0);
  216.     }
  217. #endif
  218.     if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {      /* Validate event block type                */
  219.         *err = OS_ERR_EVENT_TYPE;
  220.         return (pevent);
  221.     }
  222.     OS_ENTER_CRITICAL();
  223.     if (pevent->OSEventGrp != 0x00) {                      /* See if any tasks waiting on mutex        */
  224.         tasks_waiting = TRUE;                              /* Yes                                      */
  225.     } else {
  226.         tasks_waiting = FALSE;                             /* No                                       */
  227.     }
  228.     switch (opt) {
  229.         case OS_DEL_NO_PEND:                               /* Delete mutex only if no task waiting     */
  230.              if (tasks_waiting == FALSE) {
  231. #if OS_EVENT_NAME_SIZE > 1
  232.                  pevent->OSEventName[0] = '?';             /* Unknown name                             */
  233.                  pevent->OSEventName[1] = OS_ASCII_NUL;
  234. #endif
  235.                  pip                 = (INT8U)(pevent->OSEventCnt >> 8);
  236.                  OSTCBPrioTbl[pip]   = (OS_TCB *)0;        /* Free up the PIP                          */
  237.                  pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  238.                  pevent->OSEventPtr  = OSEventFreeList;    /* Return Event Control Block to free list  */
  239.                  pevent->OSEventCnt  = 0;
  240.                  OSEventFreeList     = pevent;
  241.                  OS_EXIT_CRITICAL();
  242.                  *err                = OS_NO_ERR;
  243.                  return ((OS_EVENT *)0);                   /* Mutex has been deleted                   */
  244.              } else {
  245.                  OS_EXIT_CRITICAL();
  246.                  *err                = OS_ERR_TASK_WAITING;
  247.                  return (pevent);
  248.              }
  249.         case OS_DEL_ALWAYS:                                /* Always delete the mutex                  */
  250.              while (pevent->OSEventGrp != 0x00) {          /* Ready ALL tasks waiting for mutex        */
  251.                  (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX);
  252.              }
  253. #if OS_EVENT_NAME_SIZE > 1
  254.              pevent->OSEventName[0] = '?';                 /* Unknown name                             */
  255.              pevent->OSEventName[1] = OS_ASCII_NUL;
  256. #endif
  257.              pip                 = (INT8U)(pevent->OSEventCnt >> 8);
  258.              OSTCBPrioTbl[pip]   = (OS_TCB *)0;            /* Free up the PIP                          */
  259.              pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  260.              pevent->OSEventPtr  = OSEventFreeList;        /* Return Event Control Block to free list  */
  261.              pevent->OSEventCnt  = 0;
  262.              OSEventFreeList     = pevent;                 /* Get next free event control block        */
  263.              OS_EXIT_CRITICAL();
  264.              if (tasks_waiting == TRUE) {                  /* Reschedule only if task(s) were waiting  */
  265.                  OS_Sched();                               /* Find highest priority task ready to run  */
  266.              }
  267.              *err = OS_NO_ERR;
  268.              return ((OS_EVENT *)0);                       /* Mutex has been deleted                   */
  269.         default:
  270.              OS_EXIT_CRITICAL();
  271.              *err = OS_ERR_INVALID_OPT;
  272.              return (pevent);
  273.     }
  274. }
  275. #endif
  276. /*$PAGE*/
  277. /*
  278. *********************************************************************************************************
  279. *                                  PEND ON MUTUAL EXCLUSION SEMAPHORE
  280. *
  281. * Description: This function waits for a mutual exclusion semaphore.
  282. *
  283. * Arguments  : pevent        is a pointer to the event control block associated with the desired
  284. *                            mutex.
  285. *
  286. *              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
  287. *                            wait for the resource up to the amount of time specified by this argument.
  288. *                            If you specify 0, however, your task will wait forever at the specified
  289. *                            mutex or, until the resource becomes available.
  290. *
  291. *              err           is a pointer to where an error message will be deposited.  Possible error
  292. *                            messages are:
  293. *                               OS_NO_ERR          The call was successful and your task owns the mutex
  294. *                               OS_TIMEOUT         The mutex was not available within the specified time.
  295. *                               OS_ERR_EVENT_TYPE  If you didn't pass a pointer to a mutex
  296. *                               OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer
  297. *                               OS_ERR_PEND_ISR    If you called this function from an ISR and the result
  298. *                                                  would lead to a suspension.
  299. *
  300. * Returns    : none
  301. *
  302. * Note(s)    : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.
  303. *              2) You MUST NOT change the priority of the task that owns the mutex
  304. *********************************************************************************************************
  305. */
  306. void  OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
  307. {
  308.     INT8U      pip;                                        /* Priority Inheritance Priority (PIP)      */
  309.     INT8U      mprio;                                      /* Mutex owner priority                     */
  310.     BOOLEAN    rdy;                                        /* Flag indicating task was ready           */
  311.     OS_TCB    *ptcb;
  312.     OS_EVENT  *pevent2;
  313.     INT8U      y;
  314. #if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
  315.     OS_CPU_SR  cpu_sr;
  316.     cpu_sr = 0;                                            /* Prevent compiler warning                 */
  317. #endif    
  318.     if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  319.         *err = OS_ERR_PEND_ISR;                            /* ... can't PEND from an ISR               */
  320.         return;
  321.     }
  322. #if OS_ARG_CHK_EN > 0
  323.     if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  324.         *err = OS_ERR_PEVENT_NULL;
  325.         return;
  326.     }
  327. #endif
  328.     if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {      /* Validate event block type                */
  329.         *err = OS_ERR_EVENT_TYPE;
  330.         return;
  331.     }
  332.     OS_ENTER_CRITICAL();    /* Is Mutex available?                      */
  333.     if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
  334.         pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;       /* Yes, Acquire the resource                */
  335.         pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;         /*      Save priority of owning task        */
  336.         pevent->OSEventPtr  = (void *)OSTCBCur;            /*      Point to owning task's OS_TCB       */
  337.         OS_EXIT_CRITICAL();
  338.         *err  = OS_NO_ERR;
  339.         return;
  340.     }
  341.     pip   = (INT8U)(pevent->OSEventCnt >> 8);                     /* No, Get PIP from mutex            */
  342.     mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);  /*     Get priority of mutex owner   */
  343.     ptcb  = (OS_TCB *)(pevent->OSEventPtr);                       /*     Point to TCB of mutex owner   */
  344.     if (ptcb->OSTCBPrio != pip) {                                 /*     Need to promote prio of owner?*/
  345.         if (mprio > OSTCBCur->OSTCBPrio) {  
  346.             y = ptcb->OSTCBY;                          
  347.             if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0x00) {        /*     See if mutex owner is ready   */
  348.                 OSRdyTbl[y] &= ~ptcb->OSTCBBitX;                  /*     Yes, Remove owner from Rdy ...*/
  349.                 if (OSRdyTbl[y] == 0x00) {                        /*          ... list at current prio */
  350.                     OSRdyGrp &= ~ptcb->OSTCBBitY;
  351.                 }
  352.                 rdy = TRUE;
  353.             } else {
  354.                 pevent2 = ptcb->OSTCBEventPtr;
  355.                 if (pevent2 != (OS_EVENT *)0) {                   /* Remove from event wait list       */
  356.                     if ((pevent2->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
  357.                         pevent2->OSEventGrp &= ~ptcb->OSTCBBitY;
  358.                     }
  359.                 }
  360.                 rdy = FALSE;                               /* No                                       */
  361.             }
  362.             ptcb->OSTCBPrio = pip;                         /* Change owner task prio to PIP            */
  363.             ptcb->OSTCBY    = ptcb->OSTCBPrio >> 3;
  364.             ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
  365.             ptcb->OSTCBX    = ptcb->OSTCBPrio & 0x07;
  366.             ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
  367.             if (rdy == TRUE) {                             /* If task was ready at owner's priority ...*/
  368.                 OSRdyGrp               |= ptcb->OSTCBBitY; /* ... make it ready at new priority.       */
  369.                 OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  370.             } else {
  371.                 pevent2 = ptcb->OSTCBEventPtr;
  372.                 if (pevent2 != (OS_EVENT *)0) {            /* Remove from event wait list              */
  373.                     pevent2->OSEventGrp               |= ptcb->OSTCBBitY;
  374.                     pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  375.                 }
  376.             }
  377.             OSTCBPrioTbl[pip] = (OS_TCB *)ptcb;
  378.         }
  379.     }
  380.     OSTCBCur->OSTCBStat   |= OS_STAT_MUTEX;           /* Mutex not available, pend current task        */
  381.     OSTCBCur->OSTCBPendTO  = FALSE;
  382.     OSTCBCur->OSTCBDly     = timeout;                 /* Store timeout in current task's TCB           */
  383.     OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
  384.     OS_EXIT_CRITICAL();
  385.     OS_Sched();                                       /* Find next highest priority task ready         */
  386.     OS_ENTER_CRITICAL();
  387.     if (OSTCBCur->OSTCBPendTO == TRUE) {              /* See if we timed out during the pend           */
  388.         OS_EventTO(pevent);
  389.         OS_EXIT_CRITICAL();
  390.         *err = OS_TIMEOUT;                            /* Indicate that we didn't get mutex within TO   */
  391.         return;
  392.     }
  393.     OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
  394.     OS_EXIT_CRITICAL();
  395.     *err = OS_NO_ERR;
  396. }
  397. /*$PAGE*/
  398. /*
  399. *********************************************************************************************************
  400. *                                  POST TO A MUTUAL EXCLUSION SEMAPHORE
  401. *
  402. * Description: This function signals a mutual exclusion semaphore
  403. *
  404. * Arguments  : pevent              is a pointer to the event control block associated with the desired
  405. *                                  mutex.
  406. *
  407. * Returns    : OS_NO_ERR               The call was successful and the mutex was signaled.
  408. *              OS_ERR_EVENT_TYPE       If you didn't pass a pointer to a mutex
  409. *              OS_ERR_PEVENT_NULL      'pevent' is a NULL pointer
  410. *              OS_ERR_POST_ISR         Attempted to post from an ISR (not valid for MUTEXes)
  411. *              OS_ERR_NOT_MUTEX_OWNER  The task that did the post is NOT the owner of the MUTEX.
  412. *********************************************************************************************************
  413. */
  414. INT8U  OSMutexPost (OS_EVENT *pevent)
  415. {
  416.     INT8U      pip;                                   /* Priority inheritance priority                 */
  417.     INT8U      prio;
  418.     INT8U      y;
  419. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  420.     OS_CPU_SR  cpu_sr;
  421.     cpu_sr = 0;                                       /* Prevent compiler warning                      */
  422. #endif    
  423.     if (OSIntNesting > 0) {                           /* See if called from ISR ...                    */
  424.         return (OS_ERR_POST_ISR);                     /* ... can't POST mutex from an ISR              */
  425.     }
  426. #if OS_ARG_CHK_EN > 0
  427.     if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
  428.         return (OS_ERR_PEVENT_NULL);
  429.     }
  430. #endif
  431.     if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type                     */
  432.         return (OS_ERR_EVENT_TYPE);
  433.     }                                                 
  434.     OS_ENTER_CRITICAL();
  435.     pip  = (INT8U)(pevent->OSEventCnt >> 8);          /* Get priority inheritance priority of mutex    */
  436.     prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);  /* Get owner's original priority      */
  437.     if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr) {   /* See if posting task owns the MUTEX            */
  438.         OS_EXIT_CRITICAL();
  439.         return (OS_ERR_NOT_MUTEX_OWNER);
  440.     }
  441.     if (OSTCBCur->OSTCBPrio == pip) {                 /* Did we have to raise current task's priority? */
  442.         y            = OSTCBCur->OSTCBY;              /* Yes, Return to original priority              */
  443.         OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX;          /*      Remove owner from ready list at 'pip'    */
  444.         if (OSRdyTbl[y] == 0) {
  445.             OSRdyGrp &= ~OSTCBCur->OSTCBBitY;
  446.         }
  447.         OSTCBCur->OSTCBPrio         = prio;
  448.         OSTCBCur->OSTCBY            = prio >> 3;
  449.         OSTCBCur->OSTCBBitY         = OSMapTbl[OSTCBCur->OSTCBY];
  450.         OSTCBCur->OSTCBX            = prio & 0x07;
  451.         OSTCBCur->OSTCBBitX         = OSMapTbl[OSTCBCur->OSTCBX];
  452.         OSRdyGrp                   |= OSTCBCur->OSTCBBitY;
  453.         OSRdyTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX;
  454.         OSTCBPrioTbl[prio]          = (OS_TCB *)OSTCBCur;
  455.     }
  456.     OSTCBPrioTbl[pip] = (OS_TCB *)1;                  /* Reserve table entry                           */
  457.     if (pevent->OSEventGrp != 0x00) {                 /* Any task waiting for the mutex?               */
  458.                                                       /* Yes, Make HPT waiting for mutex ready         */
  459.         prio                = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX);
  460.         pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;  /*      Save priority of mutex's new owner       */
  461.         pevent->OSEventCnt |= prio;
  462.         pevent->OSEventPtr  = OSTCBPrioTbl[prio];     /*      Link to mutex owner's OS_TCB             */
  463.         OS_EXIT_CRITICAL();
  464.         OS_Sched();                                   /*      Find highest priority task ready to run  */
  465.         return (OS_NO_ERR);
  466.     }
  467.     pevent->OSEventCnt |= OS_MUTEX_AVAILABLE;         /* No,  Mutex is now available                   */
  468.     pevent->OSEventPtr  = (void *)0;
  469.     OS_EXIT_CRITICAL();
  470.     return (OS_NO_ERR);
  471. }
  472. /*$PAGE*/
  473. /*
  474. *********************************************************************************************************
  475. *                                     QUERY A MUTUAL EXCLUSION SEMAPHORE
  476. *
  477. * Description: This function obtains information about a mutex
  478. *
  479. * Arguments  : pevent          is a pointer to the event control block associated with the desired mutex
  480. *
  481. *              p_mutex_data    is a pointer to a structure that will contain information about the mutex
  482. *
  483. * Returns    : OS_NO_ERR            The call was successful and the message was sent
  484. *              OS_ERR_QUERY_ISR     If you called this function from an ISR
  485. *              OS_ERR_PEVENT_NULL   'pevent' is a NULL pointer
  486. *              OS_ERR_EVENT_TYPE    If you are attempting to obtain data from a non mutex.
  487. *********************************************************************************************************
  488. */
  489. #if OS_MUTEX_QUERY_EN > 0
  490. INT8U  OSMutexQuery (OS_EVENT *pevent, OS_MUTEX_DATA *p_mutex_data)
  491. {
  492.     INT8U     *psrc;
  493.     INT8U     *pdest;
  494. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  495.     OS_CPU_SR  cpu_sr;
  496.     cpu_sr = 0;                                            /* Prevent compiler warning                 */
  497. #endif    
  498.     if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
  499.         return (OS_ERR_QUERY_ISR);                         /* ... can't QUERY mutex from an ISR        */
  500.     }
  501. #if OS_ARG_CHK_EN > 0
  502.     if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
  503.         return (OS_ERR_PEVENT_NULL);
  504.     }
  505. #endif
  506.     if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {      /* Validate event block type                */
  507.         return (OS_ERR_EVENT_TYPE);
  508.     }
  509.     OS_ENTER_CRITICAL();
  510.     p_mutex_data->OSMutexPIP  = (INT8U)(pevent->OSEventCnt >> 8);
  511.     p_mutex_data->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);
  512.     if (p_mutex_data->OSOwnerPrio == 0xFF) {
  513.         p_mutex_data->OSValue = 1;
  514.     } else {
  515.         p_mutex_data->OSValue = 0;
  516.     }
  517.     p_mutex_data->OSEventGrp  = pevent->OSEventGrp;        /* Copy wait list                           */
  518.     psrc                      = &pevent->OSEventTbl[0];
  519.     pdest                     = &p_mutex_data->OSEventTbl[0];
  520. #if OS_EVENT_TBL_SIZE > 0
  521.     *pdest++ = *psrc++;
  522. #endif
  523. #if OS_EVENT_TBL_SIZE > 1
  524.     *pdest++ = *psrc++;
  525. #endif
  526. #if OS_EVENT_TBL_SIZE > 2
  527.     *pdest++ = *psrc++;
  528. #endif
  529. #if OS_EVENT_TBL_SIZE > 3
  530.     *pdest++ = *psrc++;
  531. #endif
  532. #if OS_EVENT_TBL_SIZE > 4
  533.     *pdest++ = *psrc++;
  534. #endif
  535. #if OS_EVENT_TBL_SIZE > 5
  536.     *pdest++ = *psrc++;
  537. #endif
  538. #if OS_EVENT_TBL_SIZE > 6
  539.     *pdest++ = *psrc++;
  540. #endif
  541. #if OS_EVENT_TBL_SIZE > 7
  542.     *pdest   = *psrc;
  543. #endif
  544.     OS_EXIT_CRITICAL();
  545.     return (OS_NO_ERR);
  546. }
  547. #endif                                                     /* OS_MUTEX_QUERY_EN                        */
  548. #endif                                                     /* OS_MUTEX_EN                              */