semPxLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:26k
开发平台:

MultiPlatform

  1. /* semPxLib.c - semaphore synchronization library (POSIX) */
  2. /* Copyright 1984-2002 Wind River Systems, Inc.  */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01l,17jul00,jgn  merge DOT-4 pthreads changes
  8. 01k,03feb95,rhp  strengthen warning re semaphore deletion
  9. 01j,25jan95,rhp  restructure library man page, other doc tweaks.
  10.     19jan95,jdi  doc cleanup.
  11. 01i,08apr94,dvs  changed semClass to semPxClass (SCD #3119).
  12. 01h,08apr94,dvs  fixed error in args when calling symFindByName (SCD #3091).
  13. 01g,01feb94,dvs  documentation cleanup.
  14. 01f,12jan94,kdl  changed semaphoreInit() to semPxLibInit().
  15. 01e,05jan94,kdl  changed param names to match POSIX spec; changed sem_t
  16.  "close" field to "refCnt"; general cleanup.
  17. 01d,21dec93,kdl  made sem_destroy() return error if sem has tasks blocked.
  18. 01c,13dec93,dvs  added initialization of posix name tbl in semaphoreInit().
  19.    +rrr  fixed sem_open bug
  20. 01b,15nov93,dvs  initial cleanup
  21. 01a,06apr93,smb  created
  22. */
  23. /*
  24. DESCRIPTION:
  25. This library implements the POSIX 1003.1b semaphore interface.  For
  26. alternative semaphore routines designed expressly for VxWorks, see
  27. the manual page for semLib and other semaphore libraries
  28. mentioned there.  POSIX semaphores are counting semaphores; as
  29. such they are most similar to the semCLib VxWorks-specific semaphores.
  30. The main advantage of POSIX semaphores is portability (to the extent
  31. that alternative operating systems also provide these POSIX
  32. interfaces).  However, VxWorks-specific semaphores provide
  33. the following features absent from the semaphores implemented in this
  34. library: priority inheritance, task-deletion safety, the ability for a
  35. single task to take a semaphore multiple times, ownership of
  36. mutual-exclusion semaphores, semaphore timeout, and the choice of
  37. queuing mechanism.
  38. POSIX defines both named and unnamed semaphores; semPxLib includes
  39. separate routines for creating and deleting each kind.  For other
  40. operations, applications use the same routines for both kinds of
  41. semaphore.
  42. TERMINOLOGY
  43. The POSIX standard uses the terms f2waitf1 or f2lockf1 where
  44. f2takef1 is normally used in VxWorks, and the terms f2postf1 or
  45. f2unlockf1 where f2givef1 is normally used in VxWorks.  VxWorks
  46. documentation that is specific to the POSIX interfaces (such as the
  47. remainder of this manual entry, and the manual entries for subroutines
  48. in this library) uses the POSIX terminology, in order to make it
  49. easier to read in conjunction with other references on POSIX.
  50. SEMAPHORE DELETION
  51. The sem_destroy() call terminates an unnamed semaphore and deallocates
  52. any associated memory; the combination of sem_close() and sem_unlink()
  53. has the same effect for named semaphores.  Take care when deleting
  54. semaphores, particularly those used for mutual exclusion, to avoid
  55. deleting a semaphore out from under a task that has already locked
  56. that semaphore.  Applications should adopt the protocol of only
  57. deleting semaphores that the deleting task has successfully locked.
  58. (Similarly, for named semaphores, applications should take care to
  59. only close semaphores that the closing task has opened.)
  60. If there are tasks blocked waiting for the semaphore, sem_destroy()
  61. fails and sets `errno' to EBUSY.
  62. INTERNAL:
  63. POSIX indicates that semaphores may be implemented using a file
  64. descriptor.  I have chosen not to include this functionality in this
  65. implementation of semaphores.  POSIX specs do not insist on a file descriptor 
  66. implementation.
  67. There is an attempt to deal with the issues of a task connecting to a 
  68. semaphore and the persistence of that semaphore.  Persistence implies that
  69. a semaphore and its associated state remains valid until the reference is
  70. released.  Ref.  sem_close() and sem_unlink().
  71. Detection of deadlock is not considered in this implementation.  POSIX
  72. considers the issue but does not require it to be addressed for POSIX.
  73. The routines in this library are compliant to POSIX 1003.4 draft 14.
  74. INCLUDE FILES: semaphore.h
  75. SEE ALSO: POSIX 1003.1b document, semLib, 
  76. .pG "Basic OS"
  77. */
  78. #include "vxWorks.h"
  79. #include "errno.h"
  80. #include "semaphore.h"
  81. #include "semLib.h"
  82. #include "symLib.h"
  83. #include "posixName.h"
  84. #include "fcntl.h"
  85. #include "taskLib.h"
  86. #include "stdarg.h"
  87. #include "symSync.h"
  88. #include "string.h"
  89. #include "objLib.h"
  90. #include "qLib.h"
  91. #define __PTHREAD_SRC
  92. #include "pthread.h"
  93.  /* defines */
  94. #define MAX_TASKS 100
  95. /* locals */
  96. LOCAL OBJ_CLASS semPxClass;                        /* sem object class */
  97. LOCAL BOOL semInitialized;
  98. CLASS_ID semPxClassId = &semPxClass;               /* sem class id */
  99. /*******************************************************************************
  100. *
  101. * semPxLibInit - initialize POSIX semaphore support
  102. *
  103. * This routine must be called before using POSIX semaphores.
  104. *
  105. * RETURNS: OK, or ERROR if there is an error installing the semaphore library.
  106. */
  107. STATUS semPxLibInit (void)
  108.     {
  109.     if ((!semInitialized) &&
  110.         (classInit (semPxClassId, sizeof (struct sem_des), 
  111.     OFFSET (struct sem_des, objCore),
  112.                     (FUNCPTR) NULL, (FUNCPTR) NULL, (FUNCPTR) NULL) == OK))
  113.         {
  114. /* initialize the posix name table */
  115. posixNameTblInit (0); /* use default hashing */
  116. /* init counting semaphore library */
  117.         if (semCLibInit () == ERROR)
  118.             {
  119.             return (ERROR);
  120.             }
  121.         semInitialized = TRUE;        /* we've finished the initialization */
  122.         }
  123.     return (OK);
  124.     }
  125. /*******************************************************************************
  126. *
  127. * sem_init - initialize an unnamed semaphore (POSIX)
  128. *
  129. * This routine is used to initialize the unnamed semaphore <sem>.
  130. * The value of the initialized semaphore is <value>.  Following a successful
  131. * call to sem_init() the semaphore may be used in subsequent calls to
  132. * sem_wait(), sem_trywait(), and sem_post().  This semaphore remains usable
  133. * until the semaphore is destroyed.
  134. *
  135. * The <pshared> parameter currently has no effect.
  136. *
  137. * Only <sem> itself may be used for synchronization.
  138. *
  139. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  140. *
  141. * ERRNO:
  142. *  EINVAL
  143. *     - <value> exceeds SEM_VALUE_MAX.
  144. *  ENOSPC 
  145. *     - unable to initialize semaphore due to resource constraints.
  146. *
  147. * SEE ALSO: sem_wait(), sem_trywait(), sem_post()
  148. *
  149. */
  150. int sem_init 
  151.     (
  152.     sem_t *      sem,  /* semaphore to be initialized */
  153.     int          pshared,  /* process sharing */
  154.     unsigned int value /* semaphore initialization value */
  155.     )
  156.     {
  157.     /* validate value */
  158.     if (value > SEM_VALUE_MAX)
  159. {
  160. errno = EINVAL;
  161. return (ERROR);
  162. }
  163.     /* initialize the semaphore library */
  164.     if (semPxLibInit () == OK)
  165.         {
  166. /* create semaphore */
  167.         if ((sem->semId = semCCreate (SEM_Q_PRIORITY, value)) == NULL)
  168.     {
  169.     errno = ENOSPC;
  170.     return (ERROR);
  171.     }
  172.         sem->sem_name = NULL;             /* init the structure */
  173.         objCoreInit (&sem->objCore, semPxClassId); /* validate object */
  174.         }
  175.     else
  176. {
  177. errno = ENOSPC;
  178.         return (ERROR);
  179.         }
  180.     return (OK);
  181.     }
  182. /*******************************************************************************
  183. *
  184. * sem_destroy - destroy an unnamed semaphore (POSIX)
  185. *
  186. * This routine is used to destroy the unnamed semaphore indicated by <sem>.
  187. *
  188. * The sem_destroy() call can only destroy a semaphore created by sem_init().
  189. * Calling sem_destroy() with a named semaphore will cause a EINVAL error.
  190. * Subsequent use of the <sem> semaphore will cause an EINVAL error in the
  191. * calling function.
  192. *
  193. * If one or more tasks is blocked on the semaphore, the semaphore is not
  194. * destroyed.
  195. * WARNING
  196. * Take care when deleting semaphores, particularly those used for
  197. * mutual exclusion, to avoid deleting a semaphore out from under a
  198. * task that has already locked that semaphore.  Applications should
  199. * adopt the protocol of only deleting semaphores that the deleting
  200. * task has successfully locked.
  201. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  202. *
  203. * ERRNO:
  204. *  EINVAL 
  205. *     - invalid semaphore descriptor.
  206. *  EBUSY
  207. *     - one or more tasks is blocked on the semaphore.
  208. *
  209. * SEE ALSO: sem_init()
  210. *
  211. */
  212. int sem_destroy 
  213.     (
  214.     sem_t * sem /* semaphore descriptor */
  215.     )
  216.     {
  217.     taskLock ();                                /* TASK LOCK */
  218.     if (OBJ_VERIFY (sem, semPxClassId) != OK)
  219.         {
  220.         taskUnlock ();                          /* TASK UNLOCK */
  221.         errno = EINVAL;
  222.         return (ERROR);                         /* invalid object */
  223.         }
  224.     if (sem->sem_name != NULL) /* close via sem_close/unlink */
  225. {
  226.         taskUnlock ();                          /* TASK UNLOCK */
  227. errno = EINVAL;
  228. return (ERROR);
  229. }
  230.     if (qFirst (&(sem->semId->qHead)) != NULL) 
  231. {
  232.         taskUnlock ();                          /* TASK UNLOCK */
  233. errno = EBUSY;
  234. return (ERROR); /* someone waiting on sem */
  235. }
  236.     objCoreTerminate (&sem->objCore);   /* terminate object */
  237.     semDelete (sem->semId);
  238.     taskUnlock (); /* TASK UNLOCK */
  239.     return (OK);
  240.     }
  241. /*******************************************************************************
  242. *
  243. * sem_open - initialize/open a named semaphore (POSIX)
  244. *
  245. * This routine establishes a connection between a named semaphore and
  246. * a task.  Following a call to sem_open() with a semaphore name <name>,
  247. * the task may reference the semaphore associated with <name> using
  248. * the address returned by this call.  This semaphore may be used in 
  249. * subsequent calls to sem_wait(), sem_trywait(), and sem_post().  The 
  250. * semaphore remains usable until the semaphore is closed by a successful
  251. * call to sem_close().  
  252. *
  253. * The <oflag> argument controls whether the semaphore is created or merely
  254. * accessed by the call to sem_open().  The following flag bits may be set
  255. * in <oflag>:
  256. *
  257. * .iP O_CREAT
  258. * Use this flag to create a semaphore if it does not already exist.  If
  259. * O_CREAT is set and the semaphore already exists, O_CREAT has no effect
  260. * except as noted below under O_EXCL.  Otherwise, sem_open() creats a
  261. * semaphore.  O_CREAT requires a third and fourth argument: <mode>, which is
  262. * of type mode_t, and <value>, which is of type unsigned int.  <mode> has no
  263. * effect in this implementation.  The semaphore is created with an initial
  264. * value of <value>.  Valid initial values for semaphores must be less than
  265. * or equal to SEM_VALUE_MAX.
  266. *
  267. * .iP O_EXCL
  268. * If O_EXCL and O_CREAT are set, sem_open() will fail if the semaphore name
  269. * exists.  If O_EXCL is set and O_CREAT is not set, the named semaphore 
  270. * is not created.
  271. * .LP
  272. * To determine whether a named semaphore already exists in the system,
  273. * call sem_open() with the flags `O_CREAT | O_EXCL'.  If the
  274. * sem_open() call fails, the semaphore exists.
  275. * If a task makes multiple calls to sem_open() with the same value
  276. * for <name>, then the same semaphore address is returned for each such
  277. * call, provided that there have been no calls to sem_unlink()
  278. * for this semaphore.
  279. *
  280. * References to copies of the semaphore will produce undefined results.
  281. *
  282. * NOTE
  283. * The current implementation has the following limitations:
  284. *
  285. *     - A semaphore cannot be closed with calls to _exit() or exec().
  286. *     - A semaphore cannot be implemented as a file.
  287. *     - Semaphore names will not appear in the file system.  
  288. *
  289. * RETURNS: A pointer to sem_t, or  -1 (ERROR) if unsuccessful.  
  290. *
  291. * ERRNO:
  292. *  EEXIST
  293. *     - O_CREAT | O_EXCL are set and the semaphore already exists.
  294. *  EINVAL
  295. *     - <value> exceeds SEM_VALUE_MAX or the semaphore name is invalid.
  296. *  ENAMETOOLONG
  297. *     - the semaphore name is too long.
  298. *  ENOENT
  299. *     - the named semaphore does not exist and O_CREAT is not set.
  300. *  ENOSPC
  301. *     - the semaphore could not be initialized due to resource constraints.
  302. *
  303. * SEE ALSO: sem_unlink()
  304. *
  305. * INTERNAL:
  306. * Note that if the sem already exists and O_CREAT is not set then this call
  307. * has no effect.  If the sem does not exist and only the O_EXCL flag
  308. * is set then ENOENT is set and an -1 returned.  These are not clear from the 
  309. * POSIX specifications.
  310. *
  311. */
  312. sem_t * sem_open 
  313.     (
  314.     const char * name,  /* semaphore name */
  315.     int   oflag,  /* semaphore creation flags */
  316.     ... /* extra optional parameters */
  317.     )
  318.     {
  319.     va_list   vaList;       /* traverses argument list */
  320.     mode_t    mode;  /* mode of semaphore */
  321.     unsigned int value;  /* initial value of semaphore */
  322.     sem_t *      pSemDesc;  /* semaphore descriptor */
  323.     BOOL  found = FALSE;  /* find named object */
  324.     void *       pPool = NULL;   /* area for name */
  325.     SYM_TYPE   dummy;  /* dummy var for calling symFindByName */
  326.     
  327. #if _POSIX_NO_TRUNC
  328.     /* check name length */
  329.     if (strlen (name) > NAME_MAX)
  330.         {
  331.         errno = ENAMETOOLONG;
  332.         return ((sem_t *) ERROR);
  333.         }
  334. #endif
  335.     /* Initialize semaphore library */
  336.     if (semPxLibInit () == ERROR)
  337.         {
  338.         errno = ENOSPC;
  339.         return ((sem_t *) ERROR);
  340.         }
  341.     /* The following symTblLock is used to insure that no other task
  342.      * can create a semaphore of the same name as this one. This
  343.      * could have occurred if another task tried to access the name table
  344.      * between symFindByName returning not found and the name being
  345.      * added to the name table via symAdd.
  346.      */
  347.     symTblLock (posixNameTbl); /* LOCK NAME TABLE */
  348.     if (symFindByName (posixNameTbl, (char *) name, (char **) &pSemDesc, 
  349.        &dummy) == OK)
  350. {
  351.      found = TRUE;
  352. }
  353.     if (found)  /* found */
  354. {
  355. if (O_EXCL & oflag)
  356.             {
  357.          symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  358.             errno = EEXIST;
  359.             return ((sem_t *) ERROR);
  360.             }
  361.         else 
  362.     {
  363.          symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  364.     /* validate semaphore descriptor */
  365.     if (OBJ_VERIFY (pSemDesc, semPxClassId) != 0)
  366. {
  367. errno = EINVAL;
  368. return ((sem_t *) ERROR);
  369. }
  370.     pSemDesc->refCnt++; /* attach */
  371.             return (pSemDesc);
  372.     }
  373. }
  374.     else  /* not found */
  375. if (!(O_CREAT & oflag)) /* if not creating */
  376.             {
  377.          symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  378.             errno = ENOENT;
  379.             return ((sem_t *) ERROR);
  380.             }
  381.     /* retrieve optional parameters */
  382.     va_start (vaList, oflag);
  383.     mode = va_arg (vaList, mode_t);
  384.     value = va_arg (vaList, uint_t);
  385.     va_end (vaList);
  386.     /* validate parameter */
  387.     if (value > SEM_VALUE_MAX)
  388.         {
  389.         symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  390.         errno = EINVAL;
  391.         return ((sem_t *) ERROR);
  392.         }
  393.     if ((pSemDesc = (sem_t *) objAllocExtra (semPxClassId,
  394.                                              strlen (name) + 1,
  395.                                              &pPool)) == NULL)
  396.         {
  397.         symTblUnlock (posixNameTbl);            /* UNLOCK NAME TABLE */
  398.         errno = ENOSPC;
  399.         return ((sem_t *) ERROR);
  400.         }
  401.     strcpy ((char *) pPool, name); /* initialize name */
  402.     /* create a semaphore & initialize semaphore structure */
  403.     if ((pSemDesc->semId = semCCreate (SEM_Q_PRIORITY, value)) == NULL)
  404.         {
  405.         symTblUnlock (posixNameTbl);            /* UNLOCK NAME TABLE */
  406.         objFree (semPxClassId, (char *) pSemDesc);
  407.         errno = ENOSPC;
  408.         return ((sem_t *) ERROR);
  409.         }
  410.     objCoreInit (&pSemDesc->objCore, semPxClassId); /* validate file object */
  411.     pSemDesc->refCnt = 1;     /* first opening */
  412.     pSemDesc->sem_name = pPool;        /* initialize object name */
  413.     /* add name to name table */
  414.     if ((symAdd (posixNameTbl, (char *) name, 
  415. (char *) pSemDesc, 0, 0)) == ERROR)
  416.         {
  417.         symTblUnlock (posixNameTbl);            /* UNLOCK NAME TABLE */
  418.         semDelete (pSemDesc->semId);
  419.         objFree (semPxClassId, (char *) pSemDesc);
  420.         errno = EINVAL;
  421.         return ((sem_t *) ERROR);
  422.         }
  423.     symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  424.     return (pSemDesc);
  425.     }
  426. /*******************************************************************************
  427. * sem_close - close a named semaphore (POSIX)
  428. *
  429. * This routine is called to indicate that the calling task is finished with
  430. * the specified named semaphore, <sem>.  Do not call this routine
  431. * with an unnamed semaphore (i.e., one created by sem_init()); the
  432. * effects are undefined.  The sem_close() call deallocates any system
  433. * resources allocated by the system for use by this task for this semaphore.
  434. *
  435. * If the semaphore has not been removed with a call to sem_unlink(),
  436. * then sem_close() has no effect on the state of the semaphore.
  437. * However, if the semaphore has been unlinked, the semaphore vanishes
  438. * when the last task closes it.
  439. *
  440. * WARNING
  441. * Take care to avoid risking the deletion of a semaphore that another
  442. * task has already locked.  Applications should only close semaphores
  443. * that the closing task has opened.
  444. *
  445. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  446. *
  447. * ERRNO:
  448. *  EINVAL
  449. *     - invalid semaphore descriptor.
  450. *
  451. * SEE ALSO: sem_unlink(), sem_open(), sem_init()
  452. *
  453. */
  454. int sem_close 
  455.     (
  456.     sem_t * sem /* semaphore descriptor */
  457.     )
  458.     {
  459.     taskLock ();                                        /* TASK LOCK */
  460.     /* validate semaphore */
  461.     if (OBJ_VERIFY (sem, semPxClassId) != 0)
  462.         {
  463.         taskUnlock ();                                  /* TASK UNLOCK */
  464.         errno = EINVAL;
  465.         return (ERROR);                                 /* invalid object */
  466.         }
  467.     /* semaphore already closed */
  468.     if (sem->refCnt != 0)
  469. {
  470.         sem->refCnt--;
  471. }
  472.     /* No effect unless the name has been unlinked from name table */
  473.     if ((sem->sem_name == NULL) && (sem->refCnt == 0))
  474. {
  475.         /* release semaphore descriptor  */
  476.         objCoreTerminate (&sem->objCore);   /* terminate object */
  477.         taskUnlock ();                                  /* TASK UNLOCK */
  478. semDelete (sem->semId);
  479.         objFree (semPxClassId, (char *) sem);
  480. }
  481.     else
  482. {
  483.         taskUnlock (); /* TASK UNLOCK */
  484. }
  485.     return (OK);
  486.     }
  487. /*******************************************************************************
  488. *
  489. * sem_unlink - remove a named semaphore (POSIX)
  490. *
  491. * This routine removes the string <name> from the semaphore name
  492. * table, and marks the corresponding semaphore for destruction.  An
  493. * unlinked semaphore is destroyed when the last task closes it with
  494. * sem_close().  After a particular name is removed from the table,
  495. * calls to sem_open() using the same name cannot connect to the same
  496. * semaphore, even if other tasks are still using it.  Instead, such
  497. * calls refer to a new semaphore with the same name.
  498. *
  499. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  500. *
  501. * ERRNO:
  502. *  ENAMETOOLONG
  503. *     - semaphore name too long.
  504. *  ENOENT
  505. *     - named semaphore does not exist.
  506. *
  507. * SEE ALSO: sem_open(), sem_close()
  508. *
  509. * INTERNAL:
  510. * This routine should have no immediate effect if  the semaphore is
  511. * currently referenced by other tasks.
  512. *
  513. */
  514. int sem_unlink 
  515.     (
  516.     const char * name /* semaphore name */
  517.     )
  518.     {
  519.     sem_t *  pSemDesc = NULL;
  520.     SYM_TYPE dummy;  /* dummy var for calling symFindByName */
  521. #if _POSIX_NO_TRUNC
  522.     if (strlen (name) > NAME_MAX)  /* check name length */
  523.         {
  524.         errno = ENAMETOOLONG;
  525.         return (ERROR);
  526.         }
  527. #endif
  528.     symTblLock (posixNameTbl); /* LOCK NAME TABLE */
  529.     /* find name in the name table */
  530.     if (symFindByName (posixNameTbl, (char *)name, 
  531.        (char **) &pSemDesc, &dummy) == ERROR)
  532. {
  533. symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  534. errno = ENOENT; /* name not found */
  535. return (ERROR);
  536. }
  537.     /* remove name from table*/
  538.     symRemove (posixNameTbl, (char *) name, 0);
  539.     symTblUnlock (posixNameTbl); /* UNLOCK NAME TABLE */
  540.     /* The following taskLock is used to insure that sem_close cannot
  541.      * destroy pSemDesc between unlinking the semaphore name and
  542.      * going on to invalidate the semaphore descriptor.
  543.      */
  544.     taskLock (); /* TASK LOCK */
  545.     /* release semaphore descriptor  */
  546.     if (OBJ_VERIFY (pSemDesc, semPxClassId) != 0)
  547.         {
  548.         taskUnlock ();                                  /* TASK UNLOCK */
  549.         errno = ENOENT;
  550.         return (ERROR);                          /* invalid object */
  551.         }
  552.     /* initialize name string */
  553.     pSemDesc->sem_name = NULL;
  554.     if (pSemDesc->refCnt == 0)
  555. {
  556.         /* invalidate semaphore descriptor  */
  557.         objCoreTerminate (&pSemDesc->objCore);
  558.         taskUnlock ();                                  /* TASK UNLOCK */
  559. semDelete (pSemDesc->semId);
  560.         objFree (semPxClassId, (char *) pSemDesc);
  561. }
  562.     else
  563. {
  564.         taskUnlock (); /* TASK UNLOCK */
  565. }
  566.     return (OK);
  567.     }
  568. /*******************************************************************************
  569. *
  570. * sem_wait - lock (take) a semaphore, blocking if not available (POSIX)
  571. *
  572. * This routine locks the semaphore referenced by <sem> by performing the
  573. * semaphore lock operation on that semaphore.  If the semaphore value is
  574. * currently zero, the calling task will not return from the call
  575. * to sem_wait() until it either locks the semaphore or the call is
  576. * interrupted by a signal.  
  577. *
  578. * On return, the state of the semaphore is locked and will remain locked
  579. * until sem_post() is executed and returns successfully.
  580. *
  581. * Deadlock detection is not implemented.
  582. *
  583. * Note that the POSIX term f2lockf1 corresponds to the term f2takef1 used
  584. * in other VxWorks documentation regarding semaphores.
  585. *
  586. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  587. *
  588. * ERRNO:
  589. *  EINVAL
  590. *     - invalid semaphore descriptor, or semaphore destroyed while task waiting.
  591. *
  592. * SEE ALSO: sem_trywait(), sem_post()
  593. *
  594. */
  595. int sem_wait 
  596.     (
  597.     sem_t * sem /* semaphore descriptor */
  598.     )
  599.     {
  600.     int savtype;
  601.     /* validate the semaphore */
  602.     if (OBJ_VERIFY (sem, semPxClassId) != OK)
  603.         {
  604.         errno = EINVAL;
  605.         return (ERROR);                              /* invalid object */
  606.         }
  607.     /* Link to pthreads support code */
  608.     if (_func_pthread_setcanceltype != NULL)
  609.         {
  610.         _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);
  611.         }
  612.     /* lock the semaphore */
  613.     if (semTake (sem->semId, WAIT_FOREVER) == ERROR)
  614. {
  615. /* Link to pthreads support code */
  616.         if (_func_pthread_setcanceltype != NULL)
  617.             {
  618.             _func_pthread_setcanceltype(savtype, NULL);
  619.             }
  620. errno = EINVAL;
  621. return (ERROR);
  622. }
  623.     /* Link to pthreads support code */
  624.     if (_func_pthread_setcanceltype != NULL)
  625.         {
  626.         _func_pthread_setcanceltype(savtype, NULL);
  627.         }
  628.      return (OK);
  629.     }
  630. /*******************************************************************************
  631. *
  632. * sem_trywait - lock (take) a semaphore, returning error if unavailable (POSIX)
  633. *
  634. * This routine locks the semaphore referenced by <sem> only if the 
  635. * semaphore is currently not locked; that is, if the semaphore value is
  636. * currently positive.  Otherwise, it does not lock the semaphore.
  637. * In either case, this call returns immediately without blocking.
  638. *
  639. * Upon return, the state of the semaphore is always locked (either 
  640. * as a result of this call or by a previous sem_wait() or sem_trywait()).
  641. * The semaphore will remain locked until sem_post() is executed and returns
  642. * successfully.
  643. *
  644. * Deadlock detection is not implemented.
  645. *
  646. * Note that the POSIX term f2lockf1 corresponds to the term f2takef1 used
  647. * in other VxWorks semaphore documentation.
  648. *
  649. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  650. *
  651. * ERRNO:
  652. *  EAGAIN
  653. *     - semaphore is already locked.
  654. *  EINVAL
  655. *     - invalid semaphore descriptor.
  656. *   
  657. * SEE ALSO: sem_wait(), sem_post()
  658. *
  659. */
  660. int sem_trywait 
  661.     (
  662.     sem_t * sem /* semaphore descriptor */
  663.     )
  664.     {
  665.     /* validate the semaphore */
  666.     if (OBJ_VERIFY (sem, semPxClassId) != OK)
  667.         {
  668.         errno = EINVAL;
  669.         return (ERROR);                              /* invalid object */
  670.         }
  671.     /* lock the semaphore */
  672.     if (semTake (sem->semId, NO_WAIT) == ERROR)
  673. {
  674. errno = EAGAIN;
  675. return (ERROR);
  676. }
  677.     return (OK);
  678.     }
  679. /*******************************************************************************
  680. *
  681. * sem_post - unlock (give) a semaphore (POSIX)
  682. *
  683. * This routine unlocks the semaphore referenced by <sem> by performing
  684. * the semaphore unlock operation on that semaphore.
  685. *
  686. * If the semaphore value resulting from the operation is positive, then no
  687. * tasks were blocked waiting for the semaphore to become unlocked;
  688. * the semaphore value is simply incremented.
  689. *
  690. * If the value of the semaphore resulting from this semaphore is zero, then
  691. * one of the tasks blocked waiting for the semaphore will
  692. * return successfully from its call to sem_wait().  
  693. *
  694. * NOTE
  695. * The _POSIX_PRIORITY_SCHEDULING functionality is not yet supported.
  696. *
  697. * Note that the POSIX terms f2unlockf1 and f2postf1 correspond to
  698. * the term f2givef1 used in other VxWorks semaphore documentation.
  699. *
  700. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  701. *
  702. * ERRNO:
  703. *  EINVAL
  704. *     - invalid semaphore descriptor.
  705. *
  706. * SEE ALSO: sem_wait(), sem_trywait()
  707. *
  708. */
  709. int sem_post 
  710.     (
  711.     sem_t * sem /* semaphore descriptor */
  712.     )
  713.     {
  714.     /* validate the semaphore */
  715.     if (OBJ_VERIFY (sem, semPxClassId) != OK)
  716.         {
  717.         errno = EINVAL;
  718.         return (ERROR);                              /* invalid object */
  719.         }
  720.     /* unlock the semaphore */
  721.     if (semGive (sem->semId) == ERROR)
  722. {
  723. errno = EINVAL;
  724. return (ERROR);
  725. }
  726.     return (OK);
  727.     }
  728. /*******************************************************************************
  729. *
  730. * sem_getvalue - get the value of a semaphore (POSIX)
  731. *
  732. * This routine updates the location referenced by the <sval> argument
  733. * to have the value of the semaphore referenced by <sem> without affecting
  734. * the state of the semaphore.  The updated value represents an actual semaphore
  735. * value that occurred at some unspecified time during the call, but may
  736. * not be the actual value of the semaphore when it is returned to the calling 
  737. * task.
  738. *
  739. * If <sem> is locked, the value returned by sem_getvalue() will either be 
  740. * zero or a negative number whose absolute value represents the number 
  741. * of tasks waiting for the semaphore at some unspecified time during the call.
  742. *
  743. * RETURNS: 0 (OK), or -1 (ERROR) if unsuccessful.
  744. *
  745. * ERRNO:
  746. *  EINVAL
  747. *     - invalid semaphore descriptor.
  748. *
  749. * SEE ALSO: sem_post(), sem_trywait(), sem_trywait()
  750. *
  751. */
  752. int sem_getvalue 
  753.     (
  754.     sem_t *       sem,  /* semaphore descriptor */
  755.     int *     sval /* buffer by which the value is returned */
  756.     )
  757.     {
  758.     int         taskIdList [MAX_TASKS];
  759.     int count;
  760.     SEM_ID temp;
  761.     /* validate the semaphore */
  762.     if (OBJ_VERIFY (sem, semPxClassId) != OK)
  763.         {
  764.         errno = EINVAL;
  765.         return (ERROR);                         /* invalid object */
  766.         }
  767.     /* determine semaphore count */
  768.     temp  = sem->semId;
  769.     count = temp->semCount;
  770.     if (count == 0)
  771. {
  772. /* number of tasks waiting */
  773. *sval = -semInfo (sem->semId, &taskIdList[0], MAX_TASKS);
  774.         return (OK);
  775. }
  776.     *sval = count;
  777.     return (OK);
  778.     }