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
;
64 mutex
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
65 mutex
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
67 mutex
->owner
= (pthread_t
)NULL
;
68 mutex
->next
= (pthread_mutex_t
*)NULL
;
69 mutex
->prev
= (pthread_mutex_t
*)NULL
;
70 mutex
->busy
= (pthread_cond_t
*)NULL
;
73 mutex
->sem
= MACH_PORT_NULL
;
78 * Manage a list of mutex variables owned by a thread
82 _pthread_mutex_add(pthread_mutex_t
*mutex
)
85 pthread_t self
= pthread_self();
86 if (self
!= (pthread_t
)0) {
88 if ((m
= self
->mutexes
) != (pthread_mutex_t
*)NULL
)
93 mutex
->prev
= (pthread_mutex_t
*)NULL
;
94 self
->mutexes
= mutex
;
99 _pthread_mutex_remove(pthread_mutex_t
*mutex
, pthread_t self
)
101 pthread_mutex_t
*n
, *prev
;
102 if ((n
= mutex
->next
) != (pthread_mutex_t
*)NULL
)
104 n
->prev
= mutex
->prev
;
106 if ((prev
= mutex
->prev
) != (pthread_mutex_t
*)NULL
)
108 prev
->next
= mutex
->next
;
110 { /* This is the first in the list */
111 if (self
!= (pthread_t
)0) {
115 mutex
->owner
= (pthread_t
)NULL
;
121 * TODO: Priority inheritance stuff
124 pthread_mutex_lock(pthread_mutex_t
*mutex
)
126 kern_return_t kern_res
;
128 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
131 if (res
= pthread_mutex_init(mutex
, NULL
))
134 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
135 return (EINVAL
); /* Not a mutex variable */
137 if (mutex
->waiters
|| (mutex
->owner
!= (pthread_t
)NULL
))
140 if (mutex
->sem
== MACH_PORT_NULL
) {
141 mutex
->sem
= new_sem_from_pool();
144 PTHREAD_MACH_CALL(semaphore_wait(mutex
->sem
), kern_res
);
147 if (mutex
->waiters
== 0) {
148 restore_sem_to_pool(mutex
->sem
);
149 mutex
->sem
= MACH_PORT_NULL
;
151 if (mutex
->cond_lock
) {
152 mutex
->cond_lock
= 0;
156 _pthread_mutex_add(mutex
);
158 mutex
->owner
= (pthread_t
)0x12141968;
165 * Attempt to lock a mutex, but don't block if this isn't possible.
168 pthread_mutex_trylock(pthread_mutex_t
*mutex
)
170 kern_return_t kern_res
;
172 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
175 if (res
= pthread_mutex_init(mutex
, NULL
))
178 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
179 return (EINVAL
); /* Not a mutex variable */
180 if (!TRY_LOCK(mutex
->lock
)) {
183 if (mutex
->waiters
||
184 ((mutex
->owner
!= (pthread_t
)NULL
) && (mutex
->cond_lock
== 0)))
191 _pthread_mutex_add(mutex
);
193 mutex
->owner
= (pthread_t
)0x12141968;
195 if (mutex
->cond_lock
) {
196 PTHREAD_MACH_CALL(semaphore_wait(mutex
->sem
), kern_res
);
197 mutex
->cond_lock
= 0;
198 restore_sem_to_pool(mutex
->sem
);
199 mutex
->sem
= MACH_PORT_NULL
;
208 * TODO: Priority inheritance stuff
211 pthread_mutex_unlock(pthread_mutex_t
*mutex
)
213 kern_return_t kern_res
;
215 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
218 if (res
= pthread_mutex_init(mutex
, NULL
))
221 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
222 return (EINVAL
); /* Not a mutex variable */
225 if (mutex
->owner
!= pthread_self())
234 _pthread_mutex_remove(mutex
, mutex
->owner
);
236 mutex
->owner
= (pthread_t
)NULL
;
238 waiters
= mutex
->waiters
;
242 PTHREAD_MACH_CALL(semaphore_signal(mutex
->sem
), kern_res
);
249 * Fetch the priority ceiling value from a mutex variable.
250 * Note: written as a 'helper' function to hide implementation details.
253 pthread_mutex_getprioceiling(const pthread_mutex_t
*mutex
,
256 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
258 *prioceiling
= mutex
->prioceiling
;
262 return (EINVAL
); /* Not an initialized 'attribute' structure */
267 * Set the priority ceiling for a mutex.
268 * Note: written as a 'helper' function to hide implementation details.
271 pthread_mutex_setprioceiling(pthread_mutex_t
*mutex
,
273 int *old_prioceiling
)
275 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
277 if ((prioceiling
>= -999) ||
278 (prioceiling
<= 999))
280 *old_prioceiling
= mutex
->prioceiling
;
281 mutex
->prioceiling
= prioceiling
;
285 return (EINVAL
); /* Invalid parameter */
289 return (EINVAL
); /* Not an initialized 'attribute' structure */
294 * Destroy a mutex attribute structure.
297 pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
299 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
304 * Get the priority ceiling value from a mutex attribute structure.
305 * Note: written as a 'helper' function to hide implementation details.
308 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t
*attr
,
311 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
313 *prioceiling
= attr
->prioceiling
;
317 return (EINVAL
); /* Not an initialized 'attribute' structure */
322 * Get the mutex 'protocol' value from a mutex attribute structure.
323 * Note: written as a 'helper' function to hide implementation details.
326 pthread_mutexattr_getprotocol(const pthread_mutexattr_t
*attr
,
329 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
331 *protocol
= attr
->protocol
;
335 return (EINVAL
); /* Not an initialized 'attribute' structure */
340 * Initialize a mutex attribute structure to system defaults.
343 pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
345 attr
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
346 attr
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
347 attr
->sig
= _PTHREAD_MUTEX_ATTR_SIG
;
352 * Set the priority ceiling value in a mutex attribute structure.
353 * Note: written as a 'helper' function to hide implementation details.
356 pthread_mutexattr_setprioceiling(pthread_mutexattr_t
*attr
,
359 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
361 if ((prioceiling
>= -999) ||
362 (prioceiling
<= 999))
364 attr
->prioceiling
= prioceiling
;
368 return (EINVAL
); /* Invalid parameter */
372 return (EINVAL
); /* Not an initialized 'attribute' structure */
377 * Set the mutex 'protocol' value in a mutex attribute structure.
378 * Note: written as a 'helper' function to hide implementation details.
381 pthread_mutexattr_setprotocol(pthread_mutexattr_t
*attr
,
384 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
386 if ((protocol
== PTHREAD_PRIO_NONE
) ||
387 (protocol
== PTHREAD_PRIO_INHERIT
) ||
388 (protocol
== PTHREAD_PRIO_PROTECT
))
390 attr
->protocol
= protocol
;
394 return (EINVAL
); /* Invalid parameter */
398 return (EINVAL
); /* Not an initialized 'attribute' structure */
402 int mutex_try_lock(int *x
) {
403 return _spin_lock_try((pthread_lock_t
*)x
);
406 void mutex_wait_lock(int *x
) {
408 if( _spin_lock_try((pthread_lock_t
*)x
)) {
415 void cthread_yield(void) {