semEvLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:7k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* semEvLib.c - VxWorks events support for semaphores */
  2. /* Copyright 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01b,18oct01,bwa  Modified comment for options in semEvStart.() Added check for
  8.  current task in semEvStop().
  9. 01a,20sep01,bwa  written
  10. */
  11. /*
  12. DESCRIPTION
  13. This library is an extension to eventLib, the events library. Its purpose  
  14. is to support events for semaphores.
  15. The functions in this library are used to control registration of tasks on a
  16. semaphore. The routine semEvStart() registers a task and starts the
  17. notification process. The function semEvStop() un-registers the task, which 
  18. stops the notification mechanism.
  19. When a task is registered and the semaphore becomes available, the events
  20. specified are sent to that task. However, if a semTake() is to be done
  21. afterwards, there is no guarantee that the semaphore will still be available. 
  22. INCLUDE FILES: semEvLib.h
  23. SEE ALSO: eventLib, semLib,
  24. .pG "Basic OS"
  25. */
  26. #include "vxWorks.h"
  27. #include "taskLib.h"
  28. #include "errnoLib.h"
  29. #include "intLib.h"
  30. #include "semLib.h"
  31. #include "taskArchLib.h"
  32. #include "eventLib.h"
  33. #include "private/windLibP.h"
  34. #include "private/semLibP.h"
  35. /* prototypes (local functions) */
  36. LOCAL BOOL semEvBMIsFree (const SEM_ID semId);
  37. LOCAL BOOL semEvCIsFree  (const SEM_ID semId);
  38. /* externs */
  39. extern CLASS_ID semClassId;
  40. /* globals */
  41. FUNCPTR semEvIsFreeTbl [MAX_SEM_TYPE]  = {(FUNCPTR)semEvBMIsFree,
  42.   (FUNCPTR)semEvBMIsFree,
  43.   (FUNCPTR)semEvCIsFree,
  44.   (FUNCPTR)semEvBMIsFree,
  45.   (FUNCPTR)semInvalid,
  46.   (FUNCPTR)semInvalid,
  47.   (FUNCPTR)semInvalid,
  48.   (FUNCPTR)semInvalid};
  49. /*******************************************************************************
  50. *
  51. * semEvLibInit - dummy lib init function, used to pull lib in kernel
  52. *
  53. * NOMANUAL
  54. */
  55. void semEvLibInit (void)
  56.     {
  57.     }
  58. /*******************************************************************************
  59. *
  60. * semEvStart - start event notification process for a semaphore
  61. *
  62. * This routine turns on the event notification process for a given semaphore.
  63. * When the semaphore becomes available but no task is pending on it, the 
  64. * events specified will be sent to the task registered by this function.
  65. * A task can overwrite its own registration without first invoking semEvStop()
  66. * or specifying the ALLOW_OVERWRITE option.
  67. *
  68. * The <option> parameter is used for 3 user options:
  69. * - Specify if the events are to be sent only once or every time the semaphore 
  70. * is free until semEvStop() is called. The option 
  71. * .iP "EVENTS_SEND_ONCE (0x1)"
  72. * tells the semaphore to send the events one time only.
  73. * - Specify if another task can register itself while the current task is
  74. * still registered. If so, the current task registration is overwritten without
  75. * any warning. The option 
  76. * .iP "EVENTS_ALLOW_OVERWRITE (0x2)"
  77. * allows subsequent registrations to overwrite the current one.
  78. * - Specify if events are to be sent at the time of the registration in the
  79. * case the semaphore is free. The option
  80. * .iP "EVENTS_SEND_IF_FREE (0x4)"
  81. * tells the registration process to send events if the semaphore is free.
  82. * If none of these options are to be used, the option
  83. * .iP "EVENTS_OPTIONS_NONE" (0x0)
  84. * has to be passed to the <options> parameter.
  85. *
  86. * WARNING: This routine cannot be called from interrupt level.
  87. *
  88. * RETURNS: OK on success, or ERROR.
  89. *
  90. * ERRNO
  91. * .iP "S_objLib_OBJ_ID_ERROR"
  92. * The semaphore ID is invalid.
  93. * .iP "S_eventLib_ALREADY_REGISTERED"
  94. * A task is already registered on the semaphore.
  95. * .iP "S_intLib_NOT_ISR_CALLABLE"
  96. * Routine has been called from interrupt level.
  97. * .iP "S_eventLib_EVENTSEND_FAILED"
  98. * User chose to send events right away and that operation failed.
  99. * .iP "S_eventLib_ZERO_EVENTS"
  100. * User passed in a value of zero to the <events> parameter.
  101. *
  102. * SEE ALSO: eventLib, semLib, semEvStop()
  103. */
  104. STATUS semEvStart
  105.     (
  106.     SEM_ID semId, /* semaphore on which to register events */
  107.     UINT32 events,  /* 32 possible events to register        */
  108.     UINT8 options /* event-related semaphore options  */
  109.     )
  110.     {
  111.     FUNCPTR fcn; /* fcn that finds if the sem is free, passed to eventStart */
  112.     if (events == 0x0)
  113. {
  114. errnoSet (S_eventLib_ZERO_EVENTS);
  115. return (ERROR);
  116. }
  117.     if (INT_RESTRICT () != OK)
  118. return (ERROR);    /* errno set by INT_RESTRICT() */
  119.     TASK_LOCK (); /* to prevent sem from being deleted */
  120.     if (OBJ_VERIFY(semId,semClassId) != OK)
  121. {
  122. TASK_UNLOCK ();
  123. return (ERROR);    /* errno is set by OBJ_VERIFY */
  124. }
  125.     fcn = semEvIsFreeTbl [semId->semType & SEM_TYPE_MASK];
  126.     /* TASK_UNLOCK() will be done by eventStart() */
  127.     return (eventStart ((OBJ_ID)semId, &semId->events, fcn, events, options) );
  128.     }
  129. /*******************************************************************************
  130. *
  131. * semEvCIsFree - verify if a counting semaphore is free
  132. *
  133. * RETURNS: TRUE if semaphore is free, FALSE if not
  134. *
  135. * NOTE: the semId has to be validated before calling this function since it
  136. *       doesn't validate it itself before dereferencing the pointer.
  137. *
  138. * NOMANUAL
  139. */
  140. LOCAL BOOL semEvCIsFree
  141.     (
  142.     const SEM_ID semId
  143.     )
  144.     {
  145.     if (SEMC_IS_FREE (semId))
  146. return (TRUE);
  147.     return (FALSE);
  148.     }
  149. /*******************************************************************************
  150. *
  151. * semEvBMIsFree - verify if a mutex or binary semaphore is free
  152. *
  153. * RETURNS: TRUE if semaphore is free, FALSE if not
  154. *
  155. * NOTE: the semId has to be validated before calling this function since it
  156. *       doesn't validate it itself before dereferencing the pointer.
  157. *
  158. * NOMANUAL
  159. */
  160. LOCAL BOOL semEvBMIsFree
  161.     (
  162.     const SEM_ID semId
  163.     )
  164.     {
  165.     if (SEMBM_IS_FREE (semId))
  166. return (TRUE);
  167.     return (FALSE);
  168.     }
  169. /*******************************************************************************
  170. *
  171. * semEvStop - stop event notification process for a semaphore
  172. *
  173. * This routine turns off the event notification process for a given semaphore.
  174. * It thus allows another task to register itself for event notification on
  175. * that particular semaphore.
  176. * RETURNS: OK on success, or ERROR.
  177. *
  178. * ERRNO
  179. * .iP "S_objLib_OBJ_ID_ERROR"
  180. * The semaphore ID is invalid.
  181. * .iP "S_intLib_NOT_ISR_CALLABLE"
  182. * Routine has been called at interrupt level.
  183. * .iP "S_eventLib_TASK_NOT_REGISTERED"
  184. * Routine has not been called by the registered task.
  185. *
  186. * SEE ALSO: eventLib, semLib, semEvStart()
  187. */
  188. STATUS semEvStop
  189.     (
  190.     SEM_ID semId
  191.     )
  192.     {
  193.     int level;
  194.     if (INT_RESTRICT () != OK)
  195. return (ERROR);
  196.     /*
  197.      * intLock is used instead of TASK_LOCK because it is faster (since
  198.      * TASK_UNLOCK calls intLock anyway) and the time the ints are locked is
  199.      * really short
  200.      */
  201.     level = intLock ();
  202.     if (OBJ_VERIFY (semId,semClassId) != OK)
  203. {
  204. intUnlock (level);
  205. return (ERROR);    /* errno is set by OBJ_VERIFY */
  206. }
  207.     if (semId->events.taskId != (int)taskIdCurrent)
  208. {
  209. intUnlock (level);
  210. errnoSet (S_eventLib_TASK_NOT_REGISTERED);
  211. return (ERROR);
  212. }
  213.     semId->events.taskId = (int)NULL;
  214.     intUnlock (level);
  215.     return (OK);
  216.     }