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

VxWorks

开发平台:

C/C++

  1. /* semLib.c - general semaphore library */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02j,09nov01,dee  add CPU_FAMILY != COLDFIRE in portable test
  8. 02i,26oct01,bwa  Added semEvLib and eventLib to the list of 'SEE ALSO'
  9.                  modules.
  10. 02h,12oct01,cjj  Added documentation regarding S_eventLib_EVENTSEND_FAILED
  11.                  error
  12. 02g,06sep01,bwa  Added VxWorks events support.
  13. 02f,16nov98,cdp  make ARM CPUs with ARM_THUMB==TRUE use portable routines.
  14. 02f,03mar00,zl   merged SH support into T2
  15. 02e,05oct98,jmp  doc: cleanup.
  16. 02d,17feb98,cdp  undo 02c: put ARM back in list of optimised CPUs.
  17. 02c,21oct97,kkk  undo 02d, take out ARM from list of optimized CPUs.
  18. 02d,19may97,jpd  added ARM to list of optimised CPUs.
  19. 02c,17oct96,dgp  doc: add errnos for user-visible routines per SPR 6893
  20. 02b,13jun96,ms   conditionally compiled the windview instrumentation 
  21. 02a,22oct95,jdi  doc: added bit values for semTake() timeout param (SPR 4276).
  22. 01z,19mar95,dvs  removed tron references.
  23. 01y,03feb95,rhp  edit SEMAPHORE DELETION manpage text, duplicate under semDelete()
  24. 01x,18jan95,rhp  Doc errno value on semTake() return due to timeout (SPR#1930)
  25. 01w,09jun93,hdn  added a support for I80X86
  26. 01z,14apr94,smb  fixed class dereferencing for instrumentation macros
  27. 01y,15mar94,smb  modified instrumentation macros
  28. 01x,24jan94,smb  added instrumentation macros
  29. 01w,10dec93,smb  added instrumentation
  30. 01v,29jan93,pme  added little endian support for shared sempahores.
  31. 01u,20jan93,jdi  documentation cleanup for 5.1.
  32. 01t,13nov92,dnw  added include of smObjLib.h
  33. 01s,02oct92,pme  added reference to shared semaphores documentation.
  34. 01r,22jul92,pme  made semDestroy return S_smObjLib_NO_OBJECT_DESTROY when
  35.  trying to destroy a shared semaphore.
  36. 01q,19jul92,pme  added shared memory semaphores support.
  37. 01p,04jul92,jcf  tables now initialized to null to reduce coupling.
  38. 01o,26may92,rrr  the tree shuffle
  39. 01n,15sep91,ajm  added MIPS to list of optimized CPU's
  40. 01m,04oct91,rrr  passed through the ansification filter
  41.                   -changed functions to ansi style
  42.   -changed includes to have absolute path from h/
  43.   -fixed #else and #endif
  44.   -changed VOID to void
  45.   -changed copyright notice
  46. 01l,26sep91,hdn  added conditional flag for TRON optimized code.
  47. 01k,15aug91,del  changed interface to qInit to pass all "optional" args.
  48. 01j,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  49.  doc review by jcf.
  50. 01i,24mar91,jdi  documentation cleanup.
  51. 01h,05oct90,dnw  made semTerminate() be NOMANUAL.
  52. 01g,28aug90,jcf  documentation.
  53. 01f,10aug90,dnw  corrected forward declaration of semQFlushDefer().
  54. 01e,03aug90,jcf  documentation.
  55. 01d,05jul90,jcf  optimized version now available.
  56. 01c,26jun90,jcf  merged into one semaphore class.
  57.  added semFlush ()
  58. 01b,11may90,jcf  fixed up PORTABLE definition.
  59. 01a,20oct89,jcf  written based on v1g of semLib.
  60. */
  61. /*
  62. DESCRIPTION
  63. Semaphores are the basis for synchronization and mutual exclusion in
  64. VxWorks.  They are powerful in their simplicity and form the foundation
  65. for numerous VxWorks facilities.
  66. Different semaphore types serve different needs, and while the behavior
  67. of the types differs, their basic interface is the same.  This library
  68. provides semaphore routines common to all VxWorks semaphore types.  For
  69. all types, the two basic operations are semTake() and semGive(), the
  70. acquisition or relinquishing of a semaphore.
  71. Semaphore creation and initialization is handled by other libraries,
  72. depending on the type of semaphore used.  These libraries contain
  73. full functional descriptions of the semaphore types:
  74.     semBLib  - binary semaphores
  75.     semCLib  - counting semaphores
  76.     semMLib  - mutual exclusion semaphores
  77.     semSmLib - shared memory semaphores
  78. Binary semaphores offer the greatest speed and the broadest applicability.
  79. The semLib library provides all other semaphore operations, including
  80. routines for semaphore control, deletion, and information.  Semaphores
  81. must be validated before any semaphore operation can be undertaken.  An
  82. invalid semaphore ID results in ERROR, and an appropriate `errno' is set.
  83. SEMAPHORE CONTROL
  84. The semTake() call acquires a specified semaphore, blocking the calling
  85. task or making the semaphore unavailable.  All semaphore types support a
  86. timeout on the semTake() operation.  The timeout is specified as the
  87. number of ticks to remain blocked on the semaphore.  Timeouts of
  88. WAIT_FOREVER and NO_WAIT codify common timeouts.  If a semTake() times
  89. out, it returns ERROR.  Refer to the library of the specific semaphore 
  90. type for the exact behavior of this operation.
  91. The semGive() call relinquishes a specified semaphore, unblocking a pended
  92. task or making the semaphore available.  Refer to the library of the
  93. specific semaphore type for the exact behavior of this operation.
  94. The semFlush() call may be used to atomically unblock all tasks pended on
  95. a semaphore queue, i.e., all tasks will be unblocked before any are allowed
  96. to run.  It may be thought of as a broadcast operation in
  97. synchronization applications.  The state of the semaphore is unchanged by
  98. the use of semFlush(); it is not analogous to semGive().
  99. SEMAPHORE DELETION
  100. The semDelete() call terminates a semaphore and deallocates any
  101. associated memory.  The deletion of a semaphore unblocks tasks pended
  102. on that semaphore; the routines which were pended return ERROR.  Take
  103. care when deleting semaphores, particularly those used for mutual
  104. exclusion, to avoid deleting a semaphore out from under a task that
  105. already has taken (owns) that semaphore.  Applications should adopt
  106. the protocol of only deleting semaphores that the deleting task has
  107. successfully taken.
  108. SEMAPHORE INFORMATION
  109. The semInfo() call is a useful debugging aid, reporting all tasks
  110. blocked on a specified semaphore.  It provides a snapshot of the queue at
  111. the time of the call, but because semaphores are dynamic, the information
  112. may be out of date by the time it is available.  As with the current state of
  113. the semaphore, use of the queue of pended tasks should be restricted to
  114. debugging uses only.
  115. VXWORKS EVENTS
  116. If a task has registered for receiving events with a semaphore, events will be
  117. sent when that semaphore becomes available. By becoming available, it is
  118. implied that there is a change of state. For a binary semaphore, there is only 
  119. a change of state when a semGive() is done on a semaphore that was taken. 
  120. For a counting semaphore, there is always a change of state when the semaphore 
  121. is available, since the count is incremented each time. For a mutex, a 
  122. semGive() can only be performed if the current task is the owner, implying that 
  123. the semaphore has been taken; thus, there is always a change of state.
  124. INTERNAL:
  125. WINDVIEW INSTRUMENTATION
  126. Level 1:
  127. semGive() causes EVENT_SEMGIVE (portable only)
  128. semTake() causes EVENT_SEMTAKE (portable only)
  129. semFlush() causes EVENT_SEMFLUSH
  130. semDestroy() causes EVENT_SEMDELETE
  131. Level 2:
  132. semGive() causes EVENT_OBJ_SEMGIVE (portable only)
  133. semTake() causes EVENT_OBJ_SEMTAKE (portable only)
  134. semFlush() causes EVENT_OBJ_SEMFLUSH
  135. Level 3:
  136. N/A
  137. INCLUDE FILES: semLib.h
  138. SEE ALSO: taskLib, semBLib, semCLib, semMLib, semSmLib, semEvLib, eventLib,
  139. .pG "Basic OS"
  140. */
  141. #include "vxWorks.h"
  142. #include "taskLib.h"
  143. #include "qLib.h"
  144. #include "intLib.h"
  145. #include "errno.h"
  146. #include "smObjLib.h"
  147. #include "private/eventLibP.h"
  148. #include "private/classLibP.h"
  149. #include "private/eventP.h"
  150. #include "private/objLibP.h"
  151. #include "private/semLibP.h"
  152. #include "private/windLibP.h"
  153. #include "private/workQLibP.h"
  154. #include "private/semSmLibP.h"
  155. /* optimized version available for 680X0, MIPS, i86, SH, */
  156. /* COLDFIRE and ARM (excluding Thumb) */
  157. #if (defined(PORTABLE) || 
  158.      ((CPU_FAMILY != MC680X0) && 
  159.       (CPU_FAMILY != MIPS) && 
  160.       (CPU_FAMILY != I80X86) && 
  161.       (CPU_FAMILY != SH) && 
  162.       (CPU_FAMILY != COLDFIRE) && 
  163.       (CPU_FAMILY != ARM)) || 
  164.      ((CPU_FAMILY == ARM) && ARM_THUMB))
  165. #define semLib_PORTABLE
  166. #endif
  167. /* locals */
  168. LOCAL BOOL semLibInstalled; /* protect from muliple inits */
  169. /* globals */
  170. OBJ_CLASS semClass; /* semaphore object class */
  171. CLASS_ID  semClassId = &semClass; /* semaphore class ID */
  172. #ifdef WV_INSTRUMENTATION
  173. OBJ_CLASS semInstClass; /* semaphore object class */
  174. CLASS_ID  semInstClassId = &semInstClass; /* semaphore class ID */
  175. #endif
  176. FUNCPTR semGiveTbl [MAX_SEM_TYPE] = /* semGive() methods by type */
  177.     {
  178.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid, (FUNCPTR) semInvalid,
  179.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid, (FUNCPTR) semInvalid,
  180.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid
  181.     };
  182. FUNCPTR semTakeTbl [MAX_SEM_TYPE] = /* semTake() methods by type */
  183.     {
  184.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid, (FUNCPTR) semInvalid,
  185.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid, (FUNCPTR) semInvalid,
  186.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid
  187.     };
  188. FUNCPTR semFlushTbl [MAX_SEM_TYPE] = /* semFlush() methods by type */
  189.     {
  190.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid, (FUNCPTR) semInvalid,
  191.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid, (FUNCPTR) semInvalid,
  192.     (FUNCPTR) semInvalid, (FUNCPTR) semInvalid
  193.     };
  194. FUNCPTR semGiveDeferTbl [MAX_SEM_TYPE] = /* semGiveDefer() methods */
  195.     {
  196.     (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL,
  197.     (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL
  198.     };
  199. FUNCPTR semFlushDeferTbl [MAX_SEM_TYPE] = /* semFlushDefer() methods */
  200.     {
  201.     (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL,
  202.     (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL
  203.     };
  204. /*******************************************************************************
  205. *
  206. * semLibInit - initialize the semaphore management package
  207. *
  208. * This routine initializes the semaphore object class.  No semaphore
  209. * operation will work until this is called.  This routine is called during
  210. * system configuration within kernelInit().  This routine should only be
  211. * called once.
  212. *
  213. * SEE ALSO: classLib
  214. * NOMANUAL
  215. */
  216. STATUS semLibInit (void)
  217.     {
  218.     if ((!semLibInstalled) &&
  219. (classInit (semClassId, sizeof(SEMAPHORE), OFFSET(SEMAPHORE,objCore),
  220.          (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) semDestroy) == OK))
  221. {
  222. #ifdef WV_INSTRUMENTATION
  223. /* initialise instrumented class for semaphores */
  224. semClassId->initRtn = semInstClassId;
  225.         classInstrument (semClassId, semInstClassId);
  226. #endif
  227. semEvLibInit (); /* pull semaphore-related events lib in kernel */
  228. semLibInstalled = TRUE;
  229. }
  230.     return ((semLibInstalled) ? OK : ERROR);
  231.     }
  232. #ifdef semLib_PORTABLE
  233. /*******************************************************************************
  234. *
  235. * semGive - give a semaphore
  236. *
  237. * This routine performs the give operation on a specified semaphore.
  238. * Depending on the type of semaphore, the state of the semaphore and of the
  239. * pending tasks may be affected.  If no tasks are pending on the sempahore and
  240. * a task has previously registered to receive events from the semaphore, these
  241. * events are sent in the context of this call.  This may result in the
  242. * unpending of the task waiting for the events.  If the semaphore fails to
  243. * send events and if it was created using the SEM_EVENTSEND_ERR_NOTIFY 
  244. * option, ERROR is returned even though the give operation was successful.
  245. * The behavior of semGive() is discussed fully in the library description 
  246. * of the specific semaphore type being used.
  247. *
  248. * RETURNS: OK on success or ERROR otherwise
  249. *
  250. * ERRNO:
  251. * .iP "S_intLib_NOT_ISR_CALLABLE"
  252. * Routine was called from an ISR for a mutex semaphore.
  253. * .iP "S_objLib_OBJ_ID_ERROR"
  254. * Semaphore ID is invalid.
  255. * .iP "S_semLib_INVALID_OPERATION"
  256. * Current task not owner of mutex semaphore.
  257. * .iP "S_eventLib_EVENTSEND_FAILED"
  258. * Semaphore failed to send events to the registered task.  This errno 
  259. * value can only exist if the semaphore was created with the 
  260. * SEM_EVENTSEND_ERR_NOTIFY option.
  261. * .LP
  262. *
  263. * SEE ALSO: semBLib, semCLib, semMLib, semSmLib, semEvStart
  264. */
  265. STATUS semGive
  266.     (
  267.     SEM_ID semId        /* semaphore ID to give */
  268.     )
  269.     {
  270.     SM_SEM_ID  smObjSemId; /* shared semaphore ID */
  271.     /* check if semaphore is shared */
  272.     if (ID_IS_SHARED (semId))  
  273. {
  274. smObjSemId = (SM_SEM_ID) SM_OBJ_ID_TO_ADRS(semId);
  275. return ((*semGiveTbl[ntohl (smObjSemId->objType) & SEM_TYPE_MASK])
  276. (smObjSemId));
  277. }
  278.     /* otherwise the semaphore is local */
  279. #ifdef WV_INSTRUMENTATION
  280.     /* windview - level 1 event logging */
  281.     EVT_OBJ_3 (OBJ, semId, semClassId, EVENT_SEMGIVE, semId, 
  282. semId->state, semId->recurse);
  283. #endif
  284.     if (kernelState)
  285. return (semGiveDefer (semId));      /* defer semaphore give */
  286.     else
  287. return((* semGiveTbl[semId->semType & SEM_TYPE_MASK]) (semId));
  288.     }
  289. /*******************************************************************************
  290. *
  291. * semTake - take a semaphore
  292. *
  293. * This routine performs the take operation on a specified semaphore.
  294. * Depending on the type of semaphore, the state of the semaphore and
  295. * the calling task may be affected.  The behavior of semTake() is
  296. * discussed fully in the library description of the specific semaphore 
  297. * type being used.
  298. *
  299. * A timeout in ticks may be specified.  If a task times out, semTake() will
  300. * return ERROR.  Timeouts of WAIT_FOREVER (-1) and NO_WAIT (0) indicate to wait
  301. * indefinitely or not to wait at all.
  302. *
  303. * When semTake() returns due to timeout, it sets the errno to
  304. * S_objLib_OBJ_TIMEOUT (defined in objLib.h).
  305. * The semTake() routine is not callable from interrupt service routines.
  306. *
  307. * RETURNS: OK, or ERROR if the semaphore ID is invalid or the task timed out.
  308. *
  309. * ERRNO: S_intLib_NOT_ISR_CALLABLE, S_objLib_OBJ_ID_ERROR,
  310. *        S_objLib_OBJ_UNAVAILABLE
  311. *
  312. * SEE ALSO: semBLib, semCLib, semMLib, semSmLib
  313. */
  314. STATUS semTake
  315.     (
  316.     SEM_ID semId,       /* semaphore ID to take */
  317.     int timeout         /* timeout in ticks */
  318.     )
  319.     {
  320.     SM_SEM_ID  smObjSemId;      /* shared semaphore ID */
  321.     /* check if semaphore is global (shared) */
  322.     if (ID_IS_SHARED (semId))
  323. {
  324. smObjSemId = (SM_SEM_ID) SM_OBJ_ID_TO_ADRS(semId);
  325.         return ((* semTakeTbl[ntohl (smObjSemId->objType) & SEM_TYPE_MASK ]) 
  326.  (smObjSemId, timeout));
  327. }
  328.     /* otherwise sempahore is local */
  329. #ifdef WV_INSTRUMENTATION
  330.     /* windview - level 1 event logging */
  331.     EVT_OBJ_3 (OBJ, semId, semClassId, EVENT_SEMTAKE, semId, 
  332. semId->state, semId->recurse);
  333. #endif
  334.     return ((* (semTakeTbl[semId->semType & SEM_TYPE_MASK])) (semId, timeout));
  335.     }
  336. #endif /* semLib_PORTABLE */
  337. /*******************************************************************************
  338. *
  339. * semFlush - unblock every task pended on a semaphore
  340. *
  341. * This routine atomically unblocks all tasks pended on a specified
  342. * semaphore, i.e., all tasks will be unblocked before any is allowed
  343. * to run.  The state of the underlying semaphore is unchanged.  All
  344. * pended tasks will enter the ready queue before having a chance to
  345. * execute.
  346. *
  347. * The flush operation is useful as a means of broadcast in
  348. * synchronization applications.  Its use is illegal for mutual-exclusion
  349. * semaphores created with semMCreate().
  350. *
  351. * RETURNS: OK, or ERROR if the semaphore ID is invalid
  352. * or the operation is not supported.
  353. *
  354. * ERRNO: S_objLib_OBJ_ID_ERROR
  355. *
  356. * SEE ALSO: semBLib, semCLib, semMLib, semSmLib
  357. */
  358. STATUS semFlush
  359.     (
  360.     SEM_ID semId        /* semaphore ID to unblock everyone for */
  361.     )
  362.     {
  363.     SM_SEM_ID  smObjSemId;      /* shared semaphore ID */
  364.     /* check if semaphore is global (shared) */
  365.     if (ID_IS_SHARED (semId))
  366. {
  367.         smObjSemId = (SM_SEM_ID) SM_OBJ_ID_TO_ADRS(semId);
  368.         return ((*semFlushTbl[ntohl (smObjSemId->objType) &SEM_TYPE_MASK])
  369. (smObjSemId));
  370. }
  371.     /* otherwise semaphore is local */
  372.     
  373. #ifdef WV_INSTRUMENTATION
  374.     /* windview - level 1 event logging */
  375.     EVT_OBJ_4 (OBJ, semId, semClassId, EVENT_SEMFLUSH, semId, 
  376. semId->state, semId->recurse, &semId->qHead);
  377. #endif
  378.     if (kernelState)
  379. return (semFlushDefer (semId));
  380.     else
  381. return((* semFlushTbl[semId->semType & SEM_TYPE_MASK]) (semId));
  382.     }
  383. /*******************************************************************************
  384. *
  385. * semDelete - delete a semaphore
  386. *
  387. * This routine terminates and deallocates any memory associated with a
  388. * specified semaphore.  All tasks pending on the semaphore or pending
  389. * for the reception of events meant to be sent from the semaphore
  390. * will unblock and return ERROR.
  391. *
  392. * WARNING
  393. * Take care when deleting semaphores, particularly those used for
  394. * mutual exclusion, to avoid deleting a semaphore out from under a
  395. * task that already has taken (owns) that semaphore.  Applications
  396. * should adopt the protocol of only deleting semaphores that the
  397. * deleting task has successfully taken.
  398. *
  399. * RETURNS: OK, or ERROR if the semaphore ID is invalid.
  400. *
  401. * ERRNO:
  402. * .iP "S_intLib_NOT_ISR_CALLABLE"
  403. * Routine cannot be called from ISR.
  404. * .iP "S_objLib_OBJ_ID_ERROR"
  405. * Semaphore ID is invalid.
  406. * .iP "S_smObjLib_NO_OBJECT_DESTROY"
  407. * Deleting a shared semaphore is not permitted
  408. *
  409. * SEE ALSO: semBLib, semCLib, semMLib, semSmLib
  410. */
  411. STATUS semDelete
  412.     (
  413.     SEM_ID semId        /* semaphore ID to delete */
  414.     )
  415.     {
  416.     return (semDestroy (semId, TRUE));
  417.     }
  418. /******************************************************************************
  419. *
  420. * semTerminate - terminate a semaphore
  421. *
  422. * This routine terminates a semaphore.  Any pended tasks will be unblocked
  423. * and returned ERROR.  Unlike semDelete(), this routine does not free any
  424. * associated memory.
  425. *
  426. * RETURNS: OK, or ERROR if invalid semaphore ID.
  427. *
  428. * SEE ALSO: semDelete, semBLib, semCLib, semMLib
  429. *
  430. * NOMANUAL
  431. */
  432. STATUS semTerminate
  433.     (
  434.     SEM_ID semId        /* semaphore ID to initialize */
  435.     )
  436.     {
  437.     return (semDestroy (semId, FALSE));
  438.     }
  439. /*******************************************************************************
  440. *
  441. * semDestroy - destroy a semaphore
  442. *
  443. * This routine underlies semDelete() and semTerminate() as the function that
  444. * terminates the semaphore and optionally deallocates memory.
  445. *
  446. * RETURNS: OK, or ERROR if invalid semaphore ID.
  447. *
  448. * ERRNO: S_smObjLib_NO_OBJECT_DESTROY
  449. *
  450. * NOMANUAL
  451. */
  452. STATUS semDestroy
  453.     (
  454.     SEM_ID semId,       /* binary semaphore to destroy */
  455.     BOOL   dealloc      /* deallocate memory associated with semaphore */
  456.     )
  457.     {
  458.     int level;
  459.     if (INT_RESTRICT () != OK) /* restrict isr use */
  460. return (ERROR);
  461.     if (ID_IS_SHARED (semId))            /* if semaphore is shared */
  462. {
  463. errno = S_smObjLib_NO_OBJECT_DESTROY;
  464.         return (ERROR); /* cannot delete shared sem. */
  465. }
  466. #ifdef WV_INSTRUMENTATION
  467.     /* windview - level 1 event logging */
  468.     EVT_OBJ_4 (OBJ, semId, semClassId, EVENT_SEMDELETE, 
  469.        semId, semId->state, semId->recurse, &semId->qHead);
  470. #endif
  471.     level = intLock (); /* LOCK INTERRUPTS */
  472.     if (OBJ_VERIFY (semId, semClassId) != OK) /* validate semaphore ID */
  473. {
  474. intUnlock (level); /* UNLOCK INTERRUPTS */
  475. return (ERROR);
  476. }
  477.     objCoreTerminate (&semId->objCore); /* INVALIDATE */
  478.     kernelState = TRUE; /* KERNEL ENTER */
  479.     intUnlock (level); /* UNLOCK INTERRUPTS */
  480.     windSemDelete (semId); /* unblock any pending tasks */
  481.     eventTerminate (&semId->events);      /* unblock task waiting for events*/
  482.  
  483.     TASK_SAFE (); /* TASK SAFE */
  484.     windExit (); /* EXIT KERNEL */
  485.     if (dealloc) /* dealloc memory if selected */
  486. objFree (semClassId, (char *) semId);
  487.     TASK_UNSAFE (); /* TASK UNSAFE */
  488.     return (OK);
  489.     }
  490. /*******************************************************************************
  491. *
  492. * semGiveDefer - add appropriate semGive routine to kernel work q
  493. *
  494. * This routine defers the work of giving a semaphore by adding the work to the
  495. * kernel work queue.  If the semaphore ID is invalid or the semaphore type is
  496. * is inheritance this routine will return ERROR, otherwise OK.
  497. *
  498. * ERRNO: S_intLib_NOT_ISR_CALLABLE
  499. *
  500. * NOMANUAL
  501. */
  502. STATUS semGiveDefer
  503.     (
  504.     SEM_ID semId        /* semaphore ID to give */
  505.     )
  506.     {
  507.     if (OBJ_VERIFY (semId, semClassId) != OK) /* verify semaphore */
  508. return (ERROR);
  509.     if (semGiveDeferTbl [semId->semType] == NULL)
  510. {
  511. errno = S_intLib_NOT_ISR_CALLABLE;
  512. return (ERROR);
  513. }
  514.     workQAdd1 (semGiveDeferTbl [semId->semType], (int) semId);
  515.     return (OK);
  516.     }
  517. /*******************************************************************************
  518. *
  519. * semFlushDefer - add appropriate semFlush routine to kernel work q
  520. *
  521. * This routine defers the work of giving a semaphore by adding the work to the
  522. * kernel work queue.  If the semaphore ID is invalid or the semaphore type is
  523. * is inheritance this routine will return ERROR, otherwise OK.
  524. *
  525. * RETURNS: OK or ERROR
  526. *
  527. * ERRNO: S_intLib_NOT_ISR_CALLABLE
  528. *
  529. * NOMANUAL
  530. */
  531. STATUS semFlushDefer
  532.     (
  533.     SEM_ID semId        /* semaphore ID to give */
  534.     )
  535.     {
  536.     if (OBJ_VERIFY (semId, semClassId) != OK) /* verify semaphore */
  537. return (ERROR);
  538.     if (semFlushDeferTbl [semId->semType] == NULL)
  539. {
  540. errno = S_intLib_NOT_ISR_CALLABLE;
  541. return (ERROR);
  542. }
  543.     workQAdd1 (semFlushDeferTbl [semId->semType], (int) semId);
  544.     return (OK);
  545.     }
  546. /******************************************************************************
  547. *
  548. * semInvalid - invalid semaphore ID or operation
  549. *
  550. * RETURNS: ERROR with appropriate errno.
  551. *
  552. * ERROR: S_semLib_INVALID_OPERATION
  553. * NOMANUAL
  554. */
  555. STATUS semInvalid
  556.     (
  557.     SEM_ID semId        /* semId of invalid operation */
  558.     )
  559.     {
  560.     if (OBJ_VERIFY (semId, semClassId) != OK) /* verify semaphore */
  561. return (ERROR);
  562.     errno = S_semLib_INVALID_OPERATION; /* set errno */
  563.     return (ERROR);
  564.     }
  565. /******************************************************************************
  566. *
  567. * semIntRestrict - operation restricted from ISR use
  568. *
  569. * NOMANUAL
  570. * ARGSUSED
  571. */
  572. STATUS semIntRestrict
  573.     (
  574.     SEM_ID semId        /* semId of invalid operation */
  575.     )
  576.     {
  577.     return (INT_RESTRICT ()); /* restrict ISR use */
  578.     }
  579. /******************************************************************************
  580. *
  581. * semQInit - inialize the semaphore queue to the specified queue type
  582. *
  583. * This routine initialized the semaphore queue to the specified type.
  584. *
  585. * RETURNS: OK, or ERROR if queue type not supported.
  586. *
  587. * ERRNO S_semLib_INVALID_QUEUE_TYPE
  588. *
  589. * NOMANUAL
  590. */
  591. STATUS semQInit
  592.     (
  593.     SEMAPHORE   *pSemaphore,    /* semphore core to initialize queue for */
  594.     int         options         /* semphore options */
  595.     )
  596.     {
  597.     STATUS status = OK;
  598.     switch (options & SEM_Q_MASK)
  599. {
  600. case SEM_Q_FIFO:
  601.     qInit (&pSemaphore->qHead, Q_FIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  602.     break;
  603. case SEM_Q_PRIORITY:
  604.     qInit (&pSemaphore->qHead, Q_PRI_LIST, 0, 0, 0, 0, 0, 0, 0, 0, 0,0);
  605.     break;
  606. default:
  607.          errno  = S_semLib_INVALID_QUEUE_TYPE; /* set errno */
  608.     status = ERROR;
  609.     break;
  610. }
  611.     return (status);
  612.     }
  613. /*******************************************************************************
  614. *
  615. * semQFlush - unblock all tasks pending on this semaphore
  616. *
  617. * Unblock pending tasks. If a higher priority task has already taken
  618. * the semaphore (so that it is now pended waiting for it), that task
  619. * will now become ready to run, and preempt the task that does the semGive().
  620. * If the semaphore is already full (it has been given but not taken) this
  621. * call is essentially a no-op.
  622. *
  623. * NOMANUAL
  624. */
  625. STATUS semQFlush
  626.     (
  627.     SEM_ID semId        /* semaphore ID to give */
  628.     )
  629.     {
  630.     int level = intLock (); /* LOCK INTERRUPTS */
  631.     if (OBJ_VERIFY (semId, semClassId) != OK)
  632. {
  633. intUnlock (level); /* UNLOCK INTERRUPTS */
  634. return (ERROR);
  635. }
  636.     if (Q_FIRST (&semId->qHead) == NULL)
  637. {
  638. intUnlock (level); /* UNLOCK INTERRUPTS */
  639. }
  640.     else
  641. {
  642. kernelState = TRUE; /* KERNEL ENTER */
  643. intUnlock (level); /* UNLOCK INTERRUPTS */
  644. #ifdef WV_INSTRUMENTATION
  645. /* windview - level 2 event logging */
  646. EVT_TASK_1 (EVENT_OBJ_SEMFLUSH, semId);
  647. #endif
  648. windPendQFlush (&semId->qHead); /* flush blocked tasks */
  649. windExit (); /* KERNEL EXIT */
  650. }
  651.     return (OK);
  652.     }
  653. /*******************************************************************************
  654. *
  655. * semQFlushDefer - unblock pending tasks as deferred work
  656. *
  657. * Unblock pending tasks. If a higher priority task has already taken
  658. * the semaphore (so that it is now pended waiting for it), that task
  659. * will now become ready to run, and preempt the task that does the semGive().
  660. * If the semaphore is already full (it has been given but not taken) this
  661. * call is essentially a no-op.
  662. *
  663. * NOMANUAL
  664. */
  665. void semQFlushDefer
  666.     (
  667.     SEM_ID semId        /* semaphore ID to give */
  668.     )
  669.     {
  670.     if (Q_FIRST (&semId->qHead) != NULL)
  671. {
  672. #ifdef WV_INSTRUMENTATION
  673. /* windview - level 2 event logging */
  674. EVT_TASK_1 (EVENT_OBJ_SEMFLUSH, semId);
  675. #endif
  676. windPendQFlush (&semId->qHead); /* flush blocked tasks */
  677. }
  678.     }