2 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby granted,
7 * provided that the above copyright notice appears in all copies and
8 * that both the copyright notice and this permission notice appear in
9 * supporting documentation.
11 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
15 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 * POSIX Pthread Library
28 * -- Mutex variable support
31 #include "pthread_internals.h"
34 * Destroy a mutex variable.
37 pthread_mutex_destroy(pthread_mutex_t
*mutex
)
39 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
41 if ((mutex
->owner
!= (pthread_t
)NULL
) ||
42 (mutex
->busy
!= (pthread_cond_t
*)NULL
))
44 mutex
->sig
= _PTHREAD_NO_SIG
;
49 * Initialize a mutex variable, possibly with additional attributes.
52 pthread_mutex_init(pthread_mutex_t
*mutex
, const pthread_mutexattr_t
*attr
)
54 LOCK_INIT(mutex
->lock
);
55 mutex
->sig
= _PTHREAD_MUTEX_SIG
;
58 if (attr
->sig
!= _PTHREAD_MUTEX_ATTR_SIG
)
60 mutex
->prioceiling
= attr
->prioceiling
;
61 mutex
->protocol
= attr
->protocol
;
62 mutex
->type
= attr
->type
;
63 if ((mutex
->type
== PTHREAD_MUTEX_DEFAULT
) || (mutex
->type
== PTHREAD_MUTEX_NORMAL
))
68 mutex
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
69 mutex
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
70 mutex
->type
= PTHREAD_MUTEX_DEFAULT
;
73 mutex
->lock_count
= 0;
74 mutex
->owner
= (pthread_t
)NULL
;
75 mutex
->next
= (pthread_mutex_t
*)NULL
;
76 mutex
->prev
= (pthread_mutex_t
*)NULL
;
77 mutex
->busy
= (pthread_cond_t
*)NULL
;
80 mutex
->sem
= MACH_PORT_NULL
;
85 * Manage a list of mutex variables owned by a thread
89 _pthread_mutex_add(pthread_mutex_t
*mutex
, pthread_t self
)
92 if (self
!= (pthread_t
)0) {
93 if ((m
= self
->mutexes
) != (pthread_mutex_t
*)NULL
)
98 mutex
->prev
= (pthread_mutex_t
*)NULL
;
99 self
->mutexes
= mutex
;
104 _pthread_mutex_remove(pthread_mutex_t
*mutex
, pthread_t self
)
106 pthread_mutex_t
*n
, *prev
;
107 if ((n
= mutex
->next
) != (pthread_mutex_t
*)NULL
)
109 n
->prev
= mutex
->prev
;
111 if ((prev
= mutex
->prev
) != (pthread_mutex_t
*)NULL
)
113 prev
->next
= mutex
->next
;
115 { /* This is the first in the list */
116 if (self
!= (pthread_t
)0) {
125 * TODO: Priority inheritance stuff
128 pthread_mutex_lock(pthread_mutex_t
*mutex
)
130 kern_return_t kern_res
;
134 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
137 if (res
= pthread_mutex_init(mutex
, NULL
))
140 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
141 return (EINVAL
); /* Not a mutex variable */
146 self
= (pthread_t
)0x12141968;
151 self
= pthread_self();
156 if (mutex
->waiters
|| (mutex
->owner
!= (pthread_t
)NULL
))
158 if(slowpath
&& (mutex
->owner
== self
)) {
159 if(mutex
->type
== PTHREAD_MUTEX_ERRORCHECK
) {
162 } else if (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
) {
163 if (mutex
->lock_count
>= USHRT_MAX
){
173 if (mutex
->sem
== MACH_PORT_NULL
) {
174 mutex
->sem
= new_sem_from_pool();
178 PTHREAD_MACH_CALL(semaphore_wait(mutex
->sem
), kern_res
);
179 } while (kern_res
== KERN_ABORTED
);
182 if (mutex
->waiters
== 0) {
183 restore_sem_to_pool(mutex
->sem
);
184 mutex
->sem
= MACH_PORT_NULL
;
186 if (mutex
->cond_lock
) {
187 mutex
->cond_lock
= 0;
191 _pthread_mutex_add(mutex
, self
);
194 if (slowpath
&& (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
))
195 mutex
->lock_count
= 1;
201 * Attempt to lock a mutex, but don't block if this isn't possible.
204 pthread_mutex_trylock(pthread_mutex_t
*mutex
)
206 kern_return_t kern_res
;
210 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
213 if (res
= pthread_mutex_init(mutex
, NULL
))
216 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
217 return (EINVAL
); /* Not a mutex variable */
222 self
= (pthread_t
)0x12141968;
227 self
= pthread_self();
230 if (!TRY_LOCK(mutex
->lock
)) {
234 if(slowpath
&& (mutex
->owner
== self
) && (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
)) {
235 if (mutex
->lock_count
>= USHRT_MAX
) {
244 if (mutex
->waiters
||
245 ((mutex
->owner
!= (pthread_t
)NULL
) && (mutex
->cond_lock
== 0)))
251 _pthread_mutex_add(mutex
, self
);
253 mutex
->owner
= (pthread_t
)self
;
254 if (mutex
->cond_lock
) {
255 PTHREAD_MACH_CALL(semaphore_wait(mutex
->sem
), kern_res
);
256 mutex
->cond_lock
= 0;
257 restore_sem_to_pool(mutex
->sem
);
258 mutex
->sem
= MACH_PORT_NULL
;
260 if (slowpath
&& (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
))
261 mutex
->lock_count
= 1;
269 * TODO: Priority inheritance stuff
272 pthread_mutex_unlock(pthread_mutex_t
*mutex
)
274 kern_return_t kern_res
;
279 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
282 if (res
= pthread_mutex_init(mutex
, NULL
))
285 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
286 return (EINVAL
); /* Not a mutex variable */
291 self
= (pthread_t
)0x12141968;
296 self
= pthread_self();
302 if (mutex
->owner
!= self
)
305 && ((mutex
->type
== PTHREAD_MUTEX_ERRORCHECK
)
306 || (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
))
307 && (mutex
->owner
!= self
))
317 if (slowpath
&& (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
) && --mutex
->lock_count
) {
323 _pthread_mutex_remove(mutex
, mutex
->owner
);
325 waiters
= mutex
->waiters
;
326 mutex
->owner
= (pthread_t
)NULL
;
330 PTHREAD_MACH_CALL(semaphore_signal(mutex
->sem
), kern_res
);
338 * Fetch the priority ceiling value from a mutex variable.
339 * Note: written as a 'helper' function to hide implementation details.
342 pthread_mutex_getprioceiling(const pthread_mutex_t
*mutex
,
345 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
347 *prioceiling
= mutex
->prioceiling
;
351 return (EINVAL
); /* Not an initialized 'attribute' structure */
356 * Set the priority ceiling for a mutex.
357 * Note: written as a 'helper' function to hide implementation details.
360 pthread_mutex_setprioceiling(pthread_mutex_t
*mutex
,
362 int *old_prioceiling
)
364 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
366 if ((prioceiling
>= -999) ||
367 (prioceiling
<= 999))
369 *old_prioceiling
= mutex
->prioceiling
;
370 mutex
->prioceiling
= prioceiling
;
374 return (EINVAL
); /* Invalid parameter */
378 return (EINVAL
); /* Not an initialized 'attribute' structure */
383 * Destroy a mutex attribute structure.
386 pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
388 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
393 * Get the priority ceiling value from a mutex attribute structure.
394 * Note: written as a 'helper' function to hide implementation details.
397 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t
*attr
,
400 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
402 *prioceiling
= attr
->prioceiling
;
406 return (EINVAL
); /* Not an initialized 'attribute' structure */
411 * Get the mutex 'protocol' value from a mutex attribute structure.
412 * Note: written as a 'helper' function to hide implementation details.
415 pthread_mutexattr_getprotocol(const pthread_mutexattr_t
*attr
,
418 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
420 *protocol
= attr
->protocol
;
424 return (EINVAL
); /* Not an initialized 'attribute' structure */
428 * Get the mutex 'type' value from a mutex attribute structure.
429 * Note: written as a 'helper' function to hide implementation details.
432 pthread_mutexattr_gettype(const pthread_mutexattr_t
*attr
,
435 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
441 return (EINVAL
); /* Not an initialized 'attribute' structure */
449 pthread_mutexattr_getpshared(const pthread_mutexattr_t
*attr
, int *pshared
)
451 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
453 *pshared
= (int)PTHREAD_PROCESS_PRIVATE
;
457 return (EINVAL
); /* Not an initialized 'attribute' structure */
462 * Initialize a mutex attribute structure to system defaults.
465 pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
467 attr
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
468 attr
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
469 attr
->type
= PTHREAD_MUTEX_DEFAULT
;
470 attr
->sig
= _PTHREAD_MUTEX_ATTR_SIG
;
475 * Set the priority ceiling value in a mutex attribute structure.
476 * Note: written as a 'helper' function to hide implementation details.
479 pthread_mutexattr_setprioceiling(pthread_mutexattr_t
*attr
,
482 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
484 if ((prioceiling
>= -999) ||
485 (prioceiling
<= 999))
487 attr
->prioceiling
= prioceiling
;
491 return (EINVAL
); /* Invalid parameter */
495 return (EINVAL
); /* Not an initialized 'attribute' structure */
500 * Set the mutex 'protocol' value in a mutex attribute structure.
501 * Note: written as a 'helper' function to hide implementation details.
504 pthread_mutexattr_setprotocol(pthread_mutexattr_t
*attr
,
507 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
509 if ((protocol
== PTHREAD_PRIO_NONE
) ||
510 (protocol
== PTHREAD_PRIO_INHERIT
) ||
511 (protocol
== PTHREAD_PRIO_PROTECT
))
513 attr
->protocol
= protocol
;
517 return (EINVAL
); /* Invalid parameter */
521 return (EINVAL
); /* Not an initialized 'attribute' structure */
525 * Set the mutex 'type' value in a mutex attribute structure.
526 * Note: written as a 'helper' function to hide implementation details.
529 pthread_mutexattr_settype(pthread_mutexattr_t
*attr
,
532 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
534 if ((type
== PTHREAD_MUTEX_NORMAL
) ||
535 (type
== PTHREAD_MUTEX_ERRORCHECK
) ||
536 (type
== PTHREAD_MUTEX_RECURSIVE
) ||
537 (type
== PTHREAD_MUTEX_DEFAULT
))
543 return (EINVAL
); /* Invalid parameter */
547 return (EINVAL
); /* Not an initialized 'attribute' structure */
555 pthread_mutexattr_setpshared(pthread_mutexattr_t
*attr
, int pshared
)
557 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
559 if (pshared
== PTHREAD_PROCESS_PRIVATE
)
561 /* attr->pshared = protocol; */
565 return (EINVAL
); /* Invalid parameter */
569 return (EINVAL
); /* Not an initialized 'attribute' structure */
573 int mutex_try_lock(int *x
) {
574 return _spin_lock_try((pthread_lock_t
*)x
);
577 void mutex_wait_lock(int *x
) {
579 if( _spin_lock_try((pthread_lock_t
*)x
)) {
593 pthread_yield_np (void)