home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / threads / src / mutex.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  10KB  |  456 lines

  1. /* Copyright (C) 1992, the Florida State University
  2.    Distributed by the Florida State University under the terms of the
  3.    GNU Library General Public License.
  4.  
  5. This file is part of Pthreads.
  6.  
  7. Pthreads is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public
  9. License as published by the Free Software Foundation (version 2).
  10.  
  11. Pthreads is distributed "AS IS" in the hope that it will be
  12. useful, but WITHOUT ANY WARRANTY; without even the implied
  13. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. See the GNU Library General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Library General Public
  17. License along with Pthreads; see the file COPYING.  If not, write
  18. to the Free Software Foundation, 675 Mass Ave, Cambridge,
  19. MA 02139, USA.
  20.  
  21. Report problems and direct all questions to:
  22.  
  23.   pthreads-bugs@ada.cs.fsu.edu
  24.  
  25.   @(#)mutex.c    2.5 4/12/95
  26.  
  27. */
  28.  
  29. /* 
  30.  * Functions for the support of mutual exclusion - mutexes and their 
  31.  * attributes.  
  32.  */
  33.  
  34. #include "pthread_internals.h"
  35. #include "mutex.h"
  36.  
  37. /*------------------------------------------------------------*/
  38. /*
  39.  * pthread_mutex_lock - Checks are made to see if the mutex is 
  40.  * currently in use or not.  If the mutex is not in use, then its 
  41.  * locked. Otherwise the currently executing thread is put in the 
  42.  * wait queue and a new thread is selected. (Fast mutex_lock without
  43.  * error checks can be found in pthread_sched.S.)
  44.  */
  45. #ifdef NOERR_CHECK
  46. int slow_mutex_lock(mutex)
  47. #else
  48. int pthread_mutex_lock(mutex)
  49. #endif
  50.      pthread_mutex_t *mutex;
  51. {
  52.   register pthread_t p = mac_pthread_self();
  53.  
  54. #ifndef NOERR_CHECK
  55.   if (mutex == NO_MUTEX) {
  56.     set_errno(EINVAL);
  57.     return(-1);
  58.   }
  59.  
  60.   if (mutex->owner == p){
  61.     set_errno(EDEADLK);
  62.     return(-1);
  63.   }
  64.  
  65. #ifdef _POSIX_THREADS_PRIO_PROTECT
  66.   if (mutex->protocol == PRIO_PROTECT && p->attr.prio > mutex->prio_ceiling) {
  67.     set_errno(EINVAL);
  68.     return(-1);
  69.   }
  70. #endif _POSIX_THREADS_PRIO_PROTECT
  71. #endif !NOERR_CHECK
  72.  
  73.   SET_KERNEL_FLAG;
  74.   SIM_SYSCALL(mutex->lock);
  75.   mac_mutex_lock(mutex, p);
  76.   CLEAR_KERNEL_FLAG;
  77.   return(0);
  78. }
  79.  
  80. /*------------------------------------------------------------*/
  81. /*
  82.  * pthread_mutex_trylock - Just try to lock the mutex. If 
  83.  * lock succeeds return. Otherwise return right away without 
  84.  * getting the lock. (Fast mutex_trylock without
  85.  * error checks can be found in pthread_sched.S.)
  86.  */
  87. #ifdef NOERR_CHECK
  88. int slow_mutex_trylock(mutex)
  89. #else
  90. int pthread_mutex_trylock(mutex)
  91. #endif
  92.      pthread_mutex_t *mutex;
  93. {
  94.  
  95. pthread_t p = mac_pthread_self();
  96.  
  97. #ifndef NOERR_CHECK
  98.   if (mutex == NO_MUTEX) {
  99.     set_errno(EINVAL);
  100.     return(-1);
  101.   }
  102.  
  103. #ifdef _POSIX_THREADS_PRIO_PROTECT
  104.   if (mutex->protocol == PRIO_PROTECT && p->attr.prio > mutex->prio_ceiling) {
  105.     set_errno(EINVAL);
  106.     return(-1);
  107.   }
  108. #endif _POSIX_THREADS_PRIO_PROTECT
  109. #endif !NOERR_CHECK
  110.  
  111.   SET_KERNEL_FLAG;
  112.   if (mutex->lock) {
  113.     CLEAR_KERNEL_FLAG;
  114.     set_errno(EBUSY);
  115.     return(-1);
  116.   }
  117.  
  118.   mutex->lock = TRUE;
  119.   mutex->owner = p;
  120. #ifdef NOERR_CHECK 
  121.   mac_change_lock_prio(mutex, p); 
  122. #else 
  123. #ifdef _POSIX_THREADS_PRIO_PROTECT 
  124.  if (mutex->protocol == PRIO_PROTECT) 
  125.    mac_change_lock_prio(mutex, p);
  126. #endif                  
  127. #endif
  128.  
  129.   CLEAR_KERNEL_FLAG;
  130.   return(0);
  131. }
  132.  
  133. /*------------------------------------------------------------*/
  134. /*
  135.  * pthread_mutex_unlock - Called by the owner of mutex to release
  136.  * the mutex. (Fast mutex_unlock without
  137.  * error checks can be found in pthread_sched.S.)
  138.  */
  139. #ifdef NOERR_CHECK
  140. int slow_mutex_unlock(mutex)
  141. #else
  142. int pthread_mutex_unlock(mutex)
  143. #endif
  144.      pthread_mutex_t *mutex;
  145. {
  146. pthread_t p = mac_pthread_self();
  147.  
  148. #ifndef NOERR_CHECK
  149.   if (mutex == NO_MUTEX || mutex->owner != mac_pthread_self()) {
  150.     set_errno(EINVAL);
  151.     return(-1);
  152.   }
  153. #endif
  154.  
  155.   SET_KERNEL_FLAG;
  156.   SIM_SYSCALL(mutex->queue.head != mutex->queue.tail);
  157.   mac_mutex_unlock(mutex, p,  /* NULL */);
  158.   CLEAR_KERNEL_FLAG;
  159.   return(0);
  160. }
  161.  
  162. /*------------------------------------------------------------*/
  163. /*
  164.  * pthread_mutex_init - Initialize the mutex and at the same time 
  165.  * ensure that it's usaable.  Set the attribute values from attr 
  166.  * specified. No check is made to see if the attributes are right 
  167.  * as yet.
  168.  */
  169. int pthread_mutex_init(mutex, attr)
  170.      pthread_mutex_t *mutex;
  171.      pthread_mutexattr_t *attr;
  172. {
  173.   if (mutex == NO_MUTEX) {
  174.     set_errno(EINVAL);
  175.     return(-1);
  176.   }
  177.  
  178.   if (!attr)
  179.     attr = &pthread_mutexattr_default;
  180.  
  181.   mutex->owner = NO_PTHREAD;
  182.   mutex->flags = attr->flags;
  183.   pthread_queue_init(&mutex->queue);
  184. #ifdef _POSIX_THREADS_PRIO_PROTECT
  185.   mutex->prio_ceiling = attr->prio_ceiling;
  186.   mutex->protocol = attr->protocol;
  187. #endif
  188.   mutex->lock = FALSE;
  189.   return(0);
  190. }  
  191.  
  192. /*------------------------------------------------------------*/
  193. /*
  194.  * pthread_mutex_destroy - Destroys the mutex.
  195.  */
  196. int pthread_mutex_destroy(mutex) 
  197.      pthread_mutex_t *mutex;
  198. {
  199.   if (mutex == NO_MUTEX) {
  200.     set_errno(EINVAL);
  201.     return(-1);
  202.   }
  203.  
  204.   /*
  205.    * free mutex only if not locked and not associated with any cond var
  206.    */
  207. #ifdef NOERR_CHECK
  208.   if (pthread_test_and_set(&mutex->lock)) {
  209.     set_errno(EBUSY);
  210.     return(-1);
  211.   }
  212. #else !NOERR_CHECK
  213.   SET_KERNEL_FLAG;
  214.   if (mutex->lock) {
  215.     CLEAR_KERNEL_FLAG;
  216.     set_errno(EBUSY);
  217.     return(-1);
  218.   }
  219.   CLEAR_KERNEL_FLAG;
  220. #endif !NOERR_CHECK
  221.  
  222.   mutex->flags = 0;
  223.   return(0);
  224. }
  225.  
  226. /*------------------------------------------------------------*/
  227. /*
  228.  * pthread_mutex_setprio_ceiling - locks the mutex, changes the
  229.  * mutex's priority ceiling and releases the mutex.
  230.  */
  231. int pthread_mutex_setprio_ceiling(mutex, prio_ceiling)
  232. pthread_mutex_t *mutex;
  233. int prio_ceiling;
  234. {
  235. int oldprio;
  236.  
  237.   if (mutex == NO_MUTEX || !mutex->flags) {
  238.     set_errno(ESRCH);
  239.     return(-1);
  240.   }
  241. #ifdef _POSIX_THREADS_PRIO_PROTECT
  242.   if (prio_ceiling >= MIN_PRIORITY && prio_ceiling <= MAX_PRIORITY) {
  243.     if (pthread_mutex_trylock(mutex)) {
  244.       oldprio = mutex->prio_ceiling;
  245.       mutex->prio_ceiling = prio_ceiling;
  246.       pthread_mutex_unlock(mutex);
  247.       return(oldprio);
  248.     }
  249.     else {
  250.       set_errno(EPERM);
  251.       return(-1);
  252.     }
  253.   }
  254.   else {
  255.     set_errno(EINVAL);
  256.     return(-1);
  257.   }
  258. #else
  259.   set_errno(ENOTSUP);
  260.   return(-1);
  261. #endif
  262. }
  263.  
  264. /*------------------------------------------------------------*/
  265. /*
  266.  * pthread_mutex_getprio_ceiling - Returns the current priority
  267.  * ceiling of the mutex.
  268.  */
  269. int pthread_mutex_getprio_ceiling(mutex)
  270. pthread_mutex_t mutex;
  271. {
  272.  
  273.   if (!mutex.flags) {
  274.     set_errno(ESRCH);
  275.     return(-1);
  276.   }
  277.   
  278. #ifdef _POSIX_THREADS_PRIO_PROTECT
  279.   if (mutex.prio_ceiling >= MIN_PRIORITY &&
  280.       mutex.prio_ceiling <= MAX_PRIORITY)
  281.     return(mutex.prio_ceiling);
  282.   else {
  283.     set_errno(EINVAL);
  284.     return(-1);
  285.   }
  286. #else
  287.   set_errno(ENOTSUP);
  288.   return(-1);
  289. #endif
  290. }
  291.  
  292. /*------------------------------------------------------------*/
  293. /*
  294.  * pthread_mutexattr_init - Initializes the mutex attribute object
  295.  * with default values.
  296.  */
  297. int pthread_mutexattr_init(attr)
  298. pthread_mutexattr_t *attr;
  299. {
  300.   if (!attr)
  301.   {
  302.     set_errno(EINVAL);
  303.     return(-1);
  304.   }
  305.  
  306.   attr->flags = TRUE;
  307. #ifdef _POSIX_THREADS_PRIO_PROTECT
  308.   attr->prio_ceiling = DEFAULT_PRIORITY;
  309.   attr->protocol = NO_PRIO_INHERIT;
  310. #endif
  311.   return(0);
  312. }
  313.  
  314. /*------------------------------------------------------------*/
  315. /*
  316.  * pthread_mutexattr_destroy - Destroys the mutex attribute object.
  317.  */
  318. int pthread_mutexattr_destroy(attr)
  319. pthread_mutexattr_t *attr;
  320. {
  321.  
  322.   if (!attr || !attr->flags) {
  323.     set_errno(EINVAL);
  324.     return(-1);
  325.   }
  326.   attr->flags = FALSE;
  327. #ifdef _POSIX_THREADS_PRIO_PROTECT
  328.   attr->prio_ceiling = DEFAULT_PRIORITY;
  329.   attr->protocol = NO_PRIO_INHERIT;
  330. #endif  
  331.   return(0);
  332. }
  333.  
  334. /*------------------------------------------------------------*/
  335. /*
  336.  * pthread_mutexattr_setprotocol - Sets the protocol (value can be
  337.  * NO_PRIO_INHERIT, PRIO_INHERIT or PRIO_PROTECT) for the mutex attr.
  338.  */
  339. int pthread_mutexattr_setprotocol(attr,protocol)
  340. pthread_mutexattr_t *attr;
  341. pthread_protocol_t protocol;
  342. {
  343.   
  344.   if (!attr || !attr->flags) {
  345.     set_errno(EINVAL);
  346.     return(-1);
  347.   }
  348. #ifndef _POSIX_THREADS_PRIO_PROTECT
  349.   set_errno(ENOSYS);
  350.   return(-1);
  351. #else
  352.   if (protocol < NO_PRIO_INHERIT || protocol > PRIO_PROTECT) {
  353.     set_errno(EINVAL);
  354.     return(-1);
  355.   }
  356.   if (protocol == PRIO_INHERIT) {
  357.     set_errno(ENOTSUP);
  358.     return (-1);
  359.   }
  360.   attr->protocol = protocol;
  361.   return(0);
  362. #endif
  363. }
  364.  
  365. /*------------------------------------------------------------*/
  366. /*
  367.  * pthread_mutexattr_getprotocol - Gets the current protcol.
  368.  */
  369. pthread_protocol_t pthread_mutexattr_getprotocol(attr)
  370. pthread_mutexattr_t attr;
  371. {
  372.   if (!attr.flags) {
  373.     set_errno(EINVAL);
  374.     return(-1);
  375.   }
  376. #ifdef _POSIX_THREADS_PRIO_PROTECT
  377.   return(attr.protocol);
  378. #else
  379.   set_errno(ENOSYS);
  380.   return(-1);
  381. #endif
  382. }
  383.  
  384. /*------------------------------------------------------------*/
  385. /*
  386.  * pthread_mutexattr_setprio_ceiling - Sets the priority ceiling
  387.  * for the mutex attribute object.
  388.  */
  389. int pthread_mutexattr_setprio_ceiling(attr,prio_ceiling)
  390. pthread_mutexattr_t *attr;
  391. int prio_ceiling;
  392. {
  393.  
  394.   if (!attr || !attr->flags) {
  395.     set_errno(EINVAL);
  396.     return(-1);
  397.   }
  398. #ifndef _POSIX_THREADS_PRIO_PROTECT
  399.   set_errno(ENOSYS);
  400.   return(-1);
  401. #else
  402.   if (prio_ceiling > MAX_PRIORITY || prio_ceiling < MIN_PRIORITY) {
  403.     set_errno(EINVAL);
  404.     return(-1);
  405.   }
  406.   attr->prio_ceiling = prio_ceiling;
  407.   return(0);
  408. #endif
  409. }
  410.  
  411. /*------------------------------------------------------------*/
  412. /*
  413.  * pthread_mutexattr_getprio_ceiling - Gets the current priority
  414.  * ceiling of the mutex attribute object.
  415.  */
  416. int pthread_mutexattr_getprio_ceiling(attr)
  417. pthread_mutexattr_t attr;
  418. {
  419.   if (!attr.flags) {
  420.     set_errno(EINVAL);
  421.     return(-1);
  422.   }
  423. #ifdef _POSIX_THREADS_PRIO_PROTECT
  424.   return(attr.prio_ceiling);
  425. #else
  426.   set_errno(ENOSYS);
  427.   return(-1);
  428. #endif
  429. }
  430.  
  431. /*------------------------------------------------------------*/
  432. /*
  433.  * pthread_mutexattr_getpshared - Not Implemented. Returns ENOSYS.
  434.  */
  435.  
  436. int pthread_mutexattr_getpshared(attr, pshared)
  437. pthread_mutexattr_t *attr;
  438. int *pshared;
  439. {
  440.   set_errno(ENOSYS);
  441.   return(-1);
  442. }
  443.  
  444. /*------------------------------------------------------------*/
  445. /*
  446.  * pthread_mutexattr_setpshared - Not Implemented. Returns ENOSYS.
  447.  */
  448.  
  449. int pthread_mutexattr_setpshared(attr, pshared)
  450. pthread_mutexattr_t *attr;
  451. int pshared;
  452. {
  453.   set_errno(ENOSYS);
  454.   return(-1);
  455. }
  456.