vxwSemLib.h
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:26k
源码类别:

VxWorks

开发平台:

C/C++

  1. // VXWSem/vxwSemLib.h - semaphore classes
  2. // Copyright 1995-1999 Wind River Systems, Inc.
  3. // modification history
  4. // --------------------
  5. // 01d,08mar99,jdi  doc: fixed wrong cross-references.
  6. // 01c,21feb99,jdi  added library section, checked in documentation.
  7. // 01b,02oct95,rhp  documented.
  8. // 01a,15jun95,srh  written.
  9. // DESCRIPTION
  10. // Semaphores are the basis for synchronization and mutual exclusion in
  11. // VxWorks.  They are powerful in their simplicity and form the foundation
  12. // for numerous VxWorks facilities.
  13. //
  14. // Different semaphore types serve different needs, and while the
  15. // behavior of the types differs, their basic interface is the same.
  16. // The VXWSem class provides semaphore routines common to all VxWorks
  17. // semaphore types.  For all types, the two basic operations are
  18. // VXWSem::take() and VXWSem::give(), the acquisition or relinquishing
  19. // of a semaphore.
  20. //
  21. // Semaphore creation and initialization is handled by the following classes,
  22. // which inherit the basic operations from `VXWSem':
  23. //
  24. //     `VXWBSem'  - binary semaphores
  25. //     `VXWCSem'  - counting semaphores
  26. //     `VXWMSem'  - mutual exclusion semaphores
  27. //
  28. // Two additional semaphore classes provide semaphores that operate
  29. // over shared memory (with the optional product VxMP).  These classes
  30. // also inherit from `VXWSmNameLib'; they are described in vxwSmLib.
  31. // The following are the class names for these shared-memory
  32. // semaphores:
  33. //
  34. //     `VXWSmBSem'  - shared-memory binary semaphores
  35. //     `VXWSmCSem'  - shared-memory counting semaphores
  36. //
  37. // Binary semaphores offer the greatest speed and the broadest applicability.
  38. //
  39. // The `VXWSem' class provides all other semaphore operations, including
  40. // routines for semaphore control, deletion, and information.
  41. //
  42. // SEMAPHORE CONTROL
  43. // The VXWSem::take() call acquires a specified semaphore, blocking the calling
  44. // task or making the semaphore unavailable.  All semaphore types support a
  45. // timeout on the VXWSem::take() operation.  The timeout is specified as the
  46. // number of ticks to remain blocked on the semaphore.  Timeouts of
  47. // WAIT_FOREVER and NO_WAIT codify common timeouts.  If a VXWSem::take() times
  48. // out, it returns ERROR.  Refer to the library of the specific semaphore
  49. // type for the exact behavior of this operation.
  50. //
  51. // The VXWSem::give() call relinquishes a specified semaphore,
  52. // unblocking a pended task or making the semaphore available.  Refer
  53. // to the library of the specific semaphore type for the exact
  54. // behavior of this operation.
  55. //
  56. // The VXWSem::flush() call may be used to atomically unblock all
  57. // tasks pended on a semaphore queue; that is, it unblocks all tasks
  58. // before any are allowed to run.  It may be thought of as a
  59. // broadcast operation in synchronization applications.  The state of
  60. // the semaphore is unchanged by the use of VXWSem::flush(); it is not
  61. // analogous to VXWSem::give().
  62. //
  63. // SEMAPHORE DELETION
  64. // The VXWSem::~VXWSem() destructor terminates a semaphore and
  65. // deallocates any associated memory.  The deletion of a semaphore
  66. // unblocks tasks pended on that semaphore; the routines which were
  67. // pended return ERROR.  Take care when deleting semaphores,
  68. // particularly those used for mutual exclusion, to avoid deleting a
  69. // semaphore out from under a task that already has taken (owns) that
  70. // semaphore.  Applications should adopt the protocol of only deleting
  71. // semaphores that the deleting task has successfully taken.
  72. //
  73. // SEMAPHORE INFORMATION
  74. // The VXWSem::info() call is a useful debugging aid, reporting all
  75. // tasks blocked on a specified semaphore.  It provides a snapshot of
  76. // the queue at the time of the call, but because semaphores are
  77. // dynamic, the information may be out of date by the time it is
  78. // available.  As with the current state of the semaphore, use of the
  79. // queue of pended tasks should be restricted to debugging uses only.
  80. //
  81. // INCLUDE FILES: vxwSemLib.h
  82. //
  83. // SEE ALSO: VXWTask, vxwSmLib,
  84. // .pG "Basic OS"
  85. //
  86. // SECTION: 1C
  87. //
  88. #ifndef vxwSemLib_h
  89. #define vxwSemLib_h
  90. #include "vxWorks.h"
  91. #include "semLib.h"
  92. #include "vxwObject.h"
  93. #include "vxwErr.h"
  94. #include "private/semLibP.h"
  95. class VXWSem : virtual public VXWIdObject
  96.     {
  97.   public:
  98. //_ VXWSem Public Constructors
  99. ///////////////////////////////////////////////////////////////////////////////
  100. //
  101. // VXWSem::VXWSem - build semaphore object from semaphore ID
  102. // 
  103. // Use this constructor to manipulate a semaphore that was not created
  104. // using C++ interfaces.  The argument <id> is the semaphore
  105. // identifier returned and used by the C interface to the VxWorks
  106. // semaphore facility.
  107. // 
  108. // RETURNS: N/A
  109. // 
  110. // SEE ALSO: semLib
  111.     VXWSem (SEM_ID id)
  112. : sem_ (id)
  113. {
  114. }
  115. ///////////////////////////////////////////////////////////////////////////////
  116. //
  117. // VXWSem::~VXWSem - delete a semaphore
  118. //
  119. // This destructor terminates and deallocates any memory associated with a
  120. // specified semaphore.  Any pended tasks unblock and return ERROR.
  121. //
  122. // WARNING
  123. // Take care when deleting semaphores, particularly those used for
  124. // mutual exclusion, to avoid deleting a semaphore out from under a
  125. // task that already has taken (owns) that semaphore.  Applications
  126. // should adopt the protocol of only deleting semaphores that the
  127. // deleting task has successfully taken.
  128. //
  129. // RETURNS: N/A
  130. // 
  131. // SEE ALSO
  132. // .pG "Basic OS"
  133.     virtual ~VXWSem ()
  134. {
  135. if (semDelete (sem_) != OK)
  136.     vxwThrowErrno ();
  137. }
  138. //_ VXWSem Public Member Functions
  139. ///////////////////////////////////////////////////////////////////////////////
  140. //
  141. // VXWSem::give - give a semaphore
  142. //
  143. // This routine performs the give operation on a specified semaphore.
  144. // Depending on the type of semaphore, the state of the semaphore and of the
  145. // pending tasks may be affected.  The behavior of VXWSem::give() is
  146. // discussed fully in the constructor description for the specific semaphore 
  147. // type being used.
  148. //
  149. // RETURNS: OK.
  150. //
  151. // SEE ALSO
  152. // VXWCSem::VXWCsem(), VXWBSem::VXWBsem(), VXWMSem::VXWMsem(),
  153. // .pG "Basic OS"
  154.     STATUS give ()
  155. {
  156. return semGive (sem_);
  157. }
  158. ///////////////////////////////////////////////////////////////////////////////
  159. //
  160. // VXWSem::take - take a semaphore
  161. //
  162. // This routine performs the take operation on a specified semaphore.
  163. // Depending on the type of semaphore, the state of the semaphore and
  164. // the calling task may be affected.  The behavior of VXWSem::take() is
  165. // discussed fully in the constructor description for the specific semaphore 
  166. // type being used.
  167. //
  168. // A timeout in ticks may be specified.  If a task times out, VXWSem::take()
  169. // returns ERROR.  Timeouts of WAIT_FOREVER and NO_WAIT indicate to wait
  170. // indefinitely or not to wait at all.
  171. //
  172. // When VXWSem::take() returns due to timeout, it sets the errno to
  173. // S_objLib_OBJ_TIMEOUT (defined in objLib.h).
  174. // 
  175. // The VXWSem::take() routine must not be called from interrupt
  176. // service routines.
  177. //
  178. // RETURNS: OK, or ERROR if the task timed out.
  179. // 
  180. // SEE ALSO
  181. // VXWCSem::VXWCsem(), VXWBSem::VXWBsem(), VXWMSem::VXWMsem(),
  182. // .pG "Basic OS"
  183.     STATUS take (int timeout)
  184. {
  185. return semTake (sem_, timeout);
  186. }
  187. ///////////////////////////////////////////////////////////////////////////////
  188. //
  189. // VXWSem::flush - unblock every task pended on a semaphore
  190. //
  191. // This routine atomically unblocks all tasks pended on a specified
  192. // semaphore; that is, all tasks are unblocked before any is allowed
  193. // to run.  The state of the underlying semaphore is unchanged.  All
  194. // pended tasks will enter the ready queue before having a chance to
  195. // execute.
  196. //
  197. // The flush operation is useful as a means of broadcast in
  198. // synchronization applications.  Its use is illegal for mutual-exclusion
  199. // semaphores created with VXWMSem::VXWMSem().
  200. //
  201. // RETURNS: OK, or ERROR if the operation is not supported.
  202. //
  203. // SEE ALSO
  204. // VXWCSem::VXWCsem(), VXWBSem::VXWBsem(), VXWMSem::VXWMsem(),
  205. // .pG "Basic OS"
  206.     STATUS flush ()
  207. {
  208. return semFlush (sem_);
  209. }
  210. ///////////////////////////////////////////////////////////////////////////////
  211. //
  212. // VXWSem::id - reveal underlying semaphore ID
  213. //
  214. // This routine returns the semaphore ID corresponding to a semaphore
  215. // object.  The semaphore ID is used by the C interface to VxWorks
  216. // semaphores.
  217. //
  218. // RETURNS: Semaphore ID.
  219. //
  220. // SEE ALSO: semLib
  221.     SEM_ID id () const
  222. {
  223. return sem_;
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////
  226. //
  227. // VXWSem::info - get a list of task IDs that are blocked on a semaphore
  228. //
  229. // This routine reports the tasks blocked on a specified semaphore.
  230. // Up to <maxTasks> task IDs are copied to the array specified by <idList>.
  231. // The array is unordered.
  232. //
  233. // WARNING:
  234. // There is no guarantee that all listed tasks are still valid or that new
  235. // tasks have not been blocked by the time VXWSem::info() returns.
  236. //
  237. // RETURNS: The number of blocked tasks placed in <idList>.
  238.     STATUS info (int idList[], int maxTasks) const
  239. {
  240. return semInfo (sem_, idList, maxTasks);
  241. }
  242. ///////////////////////////////////////////////////////////////////////////////
  243. //
  244. // VXWSem::show - show information about a semaphore
  245. //
  246. // This routine displays (on standard output) the state and optionally
  247. // the pended tasks of a semaphore.
  248. //
  249. // A summary of the state of the semaphore is displayed as follows:
  250. // .CS
  251. //     Semaphore Id        : 0x585f2
  252. //     Semaphore Type      : BINARY
  253. //     Task Queuing        : PRIORITY
  254. //     Pended Tasks        : 1
  255. //     State               : EMPTY {Count if COUNTING, Owner if MUTEX}
  256. // .CE
  257. //
  258. // If <level> is 1, more detailed information is displayed.
  259. // If tasks are blocked on the queue, they are displayed in the order
  260. // in which they will unblock, as follows:
  261. // .CS
  262. //        NAME      TID    PRI DELAY
  263. //     ---------- -------- --- -----
  264. //     tExcTask    3fd678   0    21
  265. //     tLogTask    3f8ac0   0   611
  266. // .CE
  267. //
  268. // RETURNS: OK or ERROR.
  269.     STATUS show (int level) const
  270. {
  271. return semShow (sem_, level);
  272. }
  273.   protected:
  274.     VXWSem ()
  275. {
  276. }
  277.     VXWSem & operator = (const VXWSem &)
  278. {
  279. return *this;
  280. }
  281.     VXWSem (const VXWSem &)
  282.   {
  283.   }
  284.     virtual void * myValue ();
  285.     SEM_ID sem_;
  286.     };
  287. class VXWCSem : public VXWSem
  288.     {
  289.   public:
  290. //_ VXWCSem Public Constructors
  291. ///////////////////////////////////////////////////////////////////////////////
  292. //
  293. // VXWCSem::VXWCSem - create and initialize a counting semaphore
  294. //
  295. // This routine allocates and initializes a counting semaphore.  The
  296. // semaphore is initialized to the specified initial count.
  297. //
  298. // The <opts> parameter specifies the queuing style for blocked tasks.
  299. // Tasks may be queued on a priority basis or a first-in-first-out basis.
  300. // These options are SEM_Q_PRIORITY and SEM_Q_FIFO, respectively.
  301. //
  302. // A counting semaphore may be viewed as a cell in memory whose contents
  303. // keep track of a count.  When a task takes a counting semaphore, using
  304. // VXWSem::take(), subsequent action depends on the state of the count:
  305. // .IP (1) 4
  306. // If the count is non-zero, it is decremented and the calling task
  307. // continues executing.
  308. // .IP (2)
  309. // If the count is zero, the task is blocked, pending the availability
  310. // of the semaphore.  If a timeout is specified and the timeout expires, the
  311. // pended task is removed from the queue of pended tasks and enters the
  312. // ready state with an ERROR status.  A pended task is ineligible for CPU
  313. // allocation.  Any number of tasks may be pended simultaneously on the same
  314. // counting semaphore.
  315. // .LP
  316. // When a task gives a semaphore, using VXWSem::give(), the next
  317. // available task in the pend queue is unblocked.  If no task is
  318. // pending on this semaphore, the semaphore count is incremented.
  319. // Note that if a semaphore is given, and a task is unblocked that is
  320. // of higher priority than the task that called VXWSem::give(), the
  321. // unblocked task preempts the calling task. 
  322. // 
  323. // A VXWSem::flush() on a counting semaphore atomically unblocks all pended
  324. // tasks in the semaphore queue.  Thus, all tasks are made ready before any
  325. // task actually executes.  The count of the semaphore remains unchanged.
  326. // 
  327. // INTERRUPT USAGE
  328. // Counting semaphores may be given but not taken from interrupt level.
  329. // 
  330. // CAVEATS
  331. // There is no mechanism to give back or reclaim semaphores automatically when
  332. // tasks are suspended or deleted.  Such a mechanism, though desirable, is not
  333. // currently feasible.  Without explicit knowledge of the state of the guarded
  334. // resource or region, reckless automatic reclamation of a semaphore could
  335. // leave the resource in a partial state.  Thus, if a task ceases execution
  336. // unexpectedly, as with a bus error, currently owned semaphores are not 
  337. // given back, effectively leaving a resource permanently unavailable.  The
  338. // mutual-exclusion semaphores provided by `VXWMSem' offer protection from
  339. // unexpected task deletion.
  340. // 
  341. // RETURNS: N/A
  342.     VXWCSem (int opts, int count)
  343. : VXWSem (semCCreate (opts, count))
  344. {
  345. if (sem_ == 0)
  346.     vxwThrowErrno ();
  347. }
  348.   protected:
  349.     VXWCSem ()
  350. {
  351. }
  352.     VXWCSem (const VXWCSem &)
  353. {
  354. }
  355.     VXWCSem & operator = (const VXWCSem &)
  356. {
  357. return *this;
  358. }
  359.     };
  360. class VXWBSem : public VXWSem
  361.     {
  362.   public:
  363. //_ VXWBSem Public Constructors
  364. ///////////////////////////////////////////////////////////////////////////////
  365. //
  366. // VXWBSem::VXWBSem - create and initialize a binary semaphore
  367. // 
  368. // This routine allocates and initializes a binary semaphore.  The
  369. // semaphore is initialized to the state <iState>:  either SEM_FULL
  370. // (1) or SEM_EMPTY (0).
  371. //
  372. // The <opts> parameter specifies the queuing style for blocked tasks.
  373. // Tasks can be queued on a priority basis or a first-in-first-out basis.
  374. // These options are SEM_Q_PRIORITY and SEM_Q_FIFO, respectively.
  375. //
  376. // Binary semaphores are the most versatile, efficient, and conceptually
  377. // simple type of semaphore.  They can be used to: (1) control mutually
  378. // exclusive access to shared devices or data structures, or (2) synchronize
  379. // multiple tasks, or task-level and interrupt-level processes.  Binary
  380. // semaphores form the foundation of numerous VxWorks facilities.
  381. // 
  382. // A binary semaphore can be viewed as a cell in memory whose contents
  383. // are in one of two states, full or empty.  When a task takes a
  384. // binary semaphore, using VXWSem::take(), subsequent action depends
  385. // on the state of the semaphore:
  386. // .IP (1) 4
  387. // If the semaphore is full, the semaphore is made empty, and the calling task
  388. // continues executing.
  389. // .IP (2)
  390. // If the semaphore is empty, the task is blocked, pending the
  391. // availability of the semaphore.  If a timeout is specified and the timeout
  392. // expires, the pended task is removed from the queue of pended tasks
  393. // and enters the ready state with an ERROR status.  A pended task
  394. // is ineligible for CPU allocation.  Any number of tasks may be pended
  395. // simultaneously on the same binary semaphore.
  396. // .LP
  397. // When a task gives a binary semaphore, using VXWSem::give(), the
  398. // next available task in the pend queue is unblocked.  If no task is
  399. // pending on this semaphore, the semaphore becomes full.  Note that
  400. // if a semaphore is given, and a task is unblocked that is of higher
  401. // priority than the task that called VXWSem::give(), the unblocked
  402. // task preempts the calling task.
  403. // 
  404. // MUTUAL EXCLUSION
  405. // To use a binary semaphore as a means of mutual exclusion, first create it
  406. // with an initial state of full.
  407. // 
  408. // Then guard a critical section or resource by taking the semaphore with
  409. // VXWSem::take(), and exit the section or release the resource by giving
  410. // the semaphore with VXWSem::give().
  411. // 
  412. // While there is no restriction on the same semaphore being given,
  413. // taken, or flushed by multiple tasks, it is important to ensure the
  414. // proper functionality of the mutual-exclusion construct.  While
  415. // there is no danger in any number of processes taking a semaphore,
  416. // the giving of a semaphore should be more carefully controlled.  If
  417. // a semaphore is given by a task that did not take it, mutual
  418. // exclusion could be lost.
  419. // 
  420. // SYNCHRONIZATION
  421. // To use a binary semaphore as a means of synchronization, create it
  422. // with an initial state of empty.  A task blocks by taking a
  423. // semaphore at a synchronization point, and it remains blocked until
  424. // the semaphore is given by another task or interrupt service
  425. // routine.
  426. // 
  427. // Synchronization with interrupt service routines is a particularly
  428. // common need.  Binary semaphores can be given, but not taken, from
  429. // interrupt level.  Thus, a task can block at a synchronization point
  430. // with VXWSem::take(), and an interrupt service routine can unblock
  431. // that task with VXWSem::give().
  432. // 
  433. // A semFlush() on a binary semaphore atomically unblocks all pended
  434. // tasks in the semaphore queue; that is, all tasks are unblocked at once,
  435. // before any actually execute.
  436. // 
  437. // CAVEATS
  438. // There is no mechanism to give back or reclaim semaphores automatically when
  439. // tasks are suspended or deleted.  Such a mechanism, though desirable, is not
  440. // currently feasible.  Without explicit knowledge of the state of the guarded
  441. // resource or region, reckless automatic reclamation of a semaphore could
  442. // leave the resource in a partial state.  Thus, if a task ceases execution
  443. // unexpectedly, as with a bus error, currently owned semaphores will not be
  444. // given back, effectively leaving a resource permanently unavailable.  The
  445. // mutual-exclusion semaphores provided by `VXWMSem' offer protection from
  446. // unexpected task deletion.
  447. // 
  448. // RETURNS: N/A
  449.     VXWBSem (int opts, SEM_B_STATE iState)
  450. : VXWSem (semBCreate (opts, iState))
  451. {
  452. if (sem_ == 0)
  453.     vxwThrowErrno ();
  454. }
  455.   protected:
  456.     VXWBSem ()
  457. {
  458. }
  459.     VXWBSem (const VXWBSem &)
  460. {
  461. }
  462.     VXWBSem & operator = (const VXWBSem &)
  463. {
  464. return *this;
  465. }
  466.     };
  467. class VXWMSem : public VXWSem
  468.     {
  469.   public:
  470. //_ VXWMSem Public Constructors
  471. ///////////////////////////////////////////////////////////////////////////////
  472. //
  473. // VXWMSem::VXWMSem - create and initialize a mutual-exclusion semaphore
  474. //
  475. // This routine allocates and initializes a mutual-exclusion semaphore.  The
  476. // semaphore state is initialized to full.
  477. //
  478. // Semaphore options include the following:
  479. // .iP SEM_Q_PRIORITY 8
  480. // Queue pended tasks on the basis of their priority.
  481. // .iP SEM_Q_FIFO
  482. // Queue pended tasks on a first-in-first-out basis.
  483. // .iP SEM_DELETE_SAFE
  484. // Protect a task that owns the semaphore from unexpected deletion.
  485. // This option enables an implicit taskSafe() for each VXWSem::take(),
  486. // and an implicit taskUnsafe() for each VXWSem::give().
  487. // .iP SEM_INVERSION_SAFE
  488. // Protect the system from priority inversion.  With this option, the
  489. // task owning the semaphore executes at the highest priority of the
  490. // tasks pended on the semaphore, if that is higher than its current
  491. // priority.  This option must be accompanied by the SEM_Q_PRIORITY
  492. // queuing mode.
  493. // .LP
  494. // 
  495. // Mutual-exclusion semaphores offer convenient options suited for
  496. // situations that require mutually exclusive access to resources.
  497. // Typical applications include sharing devices and protecting data
  498. // structures.  Mutual-exclusion semaphores are used by many
  499. // higher-level VxWorks facilities.
  500. // 
  501. // The mutual-exclusion semaphore is a specialized version of the
  502. // binary semaphore, designed to address issues inherent in mutual
  503. // exclusion, such as recursive access to resources, priority
  504. // inversion, and deletion safety.  The fundamental behavior of the
  505. // mutual-exclusion semaphore is identical to the binary semaphore as
  506. // described for VXWBSem::VXWBSem(), except for the following
  507. // restrictions:
  508. // 
  509. // .iP
  510. // It can only be used for mutual exclusion.
  511. // .iP
  512. // It can only be given by the task that took it.
  513. // .iP
  514. // It may not be taken or given from interrupt level.
  515. // .iP
  516. // The VXWSem::flush() operation is illegal.
  517. // .LP
  518. // 
  519. // These last two operations have no meaning in mutual-exclusion situations.
  520. // 
  521. // RECURSIVE RESOURCE ACCESS
  522. // 
  523. // A special feature of the mutual-exclusion semaphore is that it may
  524. // be taken "recursively;" that is, it can be taken more than once by
  525. // the task that owns it before finally being released.  Recursion is
  526. // useful for a set of routines that need mutually exclusive access to
  527. // a resource, but may need to call each other.
  528. // 
  529. // Recursion is possible because the system keeps track of which task
  530. // currently owns a mutual-exclusion semaphore.  Before being
  531. // released, a mutual-exclusion semaphore taken recursively must be
  532. // given the same number of times it has been taken; this is tracked
  533. // by means of a count which increments with each VXWSem::take()
  534. // and decrements with each VXWSem::give().
  535. // 
  536. // PRIORITY-INVERSION SAFETY
  537. // If the option SEM_INVERSION_SAFE is selected, the library adopts a
  538. // priority-inheritance protocol to resolve potential occurrences of
  539. // "priority inversion," a problem stemming from the use semaphores for
  540. // mutual exclusion.  Priority inversion arises when a higher-priority task
  541. // is forced to wait an indefinite period of time for the completion of a
  542. // lower-priority task.
  543. // 
  544. // Consider the following scenario: T1, T2, and T3 are tasks of high,
  545. // medium, and low priority, respectively.  T3 has acquired some
  546. // resource by taking its associated semaphore.  When T1 preempts T3
  547. // and contends for the resource by taking the same semaphore, it
  548. // becomes blocked.  If we could be assured that T1 would be blocked
  549. // no longer than the time it normally takes T3 to finish with the
  550. // resource, the situation would not be problematic.  However, the
  551. // low-priority task is vulnerable to preemption by medium-priority
  552. // tasks; a preempting task, T2, could inhibit T3 from relinquishing
  553. // the resource.  This condition could persist, blocking T1 for an
  554. // indefinite period of time.
  555. // 
  556. // The priority-inheritance protocol solves the problem of priority
  557. // inversion by elevating the priority of T3 to the priority of T1
  558. // during the time T1 is blocked on T3.  This protects T3, and
  559. // indirectly T1, from preemption by T2.  Stated more generally, the
  560. // priority-inheritance protocol assures that a task which owns a
  561. // resource executes at the priority of the highest priority task
  562. // blocked on that resource.  When execution is complete, the task
  563. // gives up the resource and returns to its normal, or standard,
  564. // priority.  Hence, the "inheriting" task is protected from
  565. // preemption by any intermediate-priority tasks.
  566. // 
  567. // The priority-inheritance protocol also takes into consideration a task's
  568. // ownership of more than one mutual-exclusion semaphore at a time.  Such a
  569. // task will execute at the priority of the highest priority task blocked on
  570. // any of the resources it owns.  The task returns to its normal priority
  571. // only after relinquishing all of its mutual-exclusion semaphores that have
  572. // the inversion-safety option enabled.
  573. // 
  574. // SEMAPHORE DELETION
  575. // The VXWSem::~VXWSem() destructor terminates a semaphore and deallocates any
  576. // associated memory.  The deletion of a semaphore unblocks tasks pended
  577. // on that semaphore; the routines which were pended return ERROR.  Take
  578. // special care when deleting mutual-exclusion semaphores to avoid
  579. // deleting a semaphore out from under a task that already owns (has
  580. // taken) that semaphore.  Applications should adopt the protocol of only
  581. // deleting semaphores that the deleting task owns.
  582. // 
  583. // TASK-DELETION SAFETY
  584. // If the option SEM_DELETE_SAFE is selected, the task owning the semaphore
  585. // is protected from deletion as long as it owns the semaphore.  This
  586. // solves another problem endemic to mutual exclusion.  Deleting a task
  587. // executing in a critical region can be catastrophic.  The resource could be
  588. // left in a corrupted state and the semaphore guarding the resource would be
  589. // unavailable, effectively shutting off all access to the resource.
  590. // 
  591. // As discussed in taskLib, the primitives taskSafe() and taskUnsafe()
  592. // offer one solution, but as this type of protection goes hand in
  593. // hand with mutual exclusion, the mutual-exclusion semaphore provides
  594. // the option SEM_DELETE_SAFE, which enables an implicit taskSafe()
  595. // with each VXWSem::take(), and a taskUnsafe() with each
  596. // VXWSem::give().  This convenience is also more efficient, as the
  597. // resulting code requires fewer entrances to the kernel.
  598. // 
  599. // CAVEATS
  600. // There is no mechanism to give back or reclaim semaphores automatically when
  601. // tasks are suspended or deleted.  Such a mechanism, though desirable, is not
  602. // currently feasible.  Without explicit knowledge of the state of the guarded
  603. // resource or region, reckless automatic reclamation of a semaphore could
  604. // leave the resource in a partial state.  Thus if a task ceases execution
  605. // unexpectedly, as with a bus error, currently owned semaphores will not be
  606. // given back, effectively leaving a resource permanently unavailable.  The
  607. // SEM_DELETE_SAFE option partially protects an application, to the extent
  608. // that unexpected deletions will be deferred until the resource is released.
  609. // 
  610. // RETURNS: N/A
  611. //
  612. // SEE ALSO: taskSafe(), taskUnsafe()
  613.     VXWMSem (int opts)
  614. : VXWSem (semMCreate (opts))
  615. {
  616. if (sem_ == 0)
  617.     vxwThrowErrno ();
  618. }
  619. //_ VXWMSem Public Member Functions
  620. //////////////////////////////////////////////////////////////////////////////
  621. //
  622. // VXWMSem::giveForce - give a mutual-exclusion semaphore without restrictions
  623. //
  624. // This routine gives a mutual-exclusion semaphore, regardless of semaphore
  625. // ownership.  It is intended as a debugging aid only.
  626. //
  627. // The routine is particularly useful when a task dies while holding some
  628. // mutual-exclusion semaphore, because the semaphore can be resurrected.  The
  629. // routine gives the semaphore to the next task in the pend queue, or makes
  630. // the semaphore full if no tasks are pending.  In effect, execution 
  631. // continues as if the task owning the semaphore had actually given the
  632. // semaphore.
  633. //
  634. // CAVEATS
  635. // Use this routine should only as a debugging aid, when the condition of
  636. // the semaphore is known.
  637. //
  638. // RETURNS: OK.
  639. //
  640. // SEE ALSO: VXWSem::give()
  641.     STATUS giveForce ()
  642. {
  643. return semMGiveForce (sem_);
  644. }
  645.   protected:
  646.     VXWMSem ()
  647. {
  648. }
  649.     VXWMSem (const VXWMSem &)
  650. {
  651. }
  652.     VXWMSem & operator = (const VXWMSem &)
  653. {
  654. return *this;
  655. }
  656.     };
  657. #endif /* ifndef vxwSemLib_h */