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();
145 PTHREAD_MACH_CALL(semaphore_wait(mutex
->sem
), kern_res
);
146 } while (kern_res
== KERN_ABORTED
);
149 if (mutex
->waiters
== 0) {
150 restore_sem_to_pool(mutex
->sem
);
151 mutex
->sem
= MACH_PORT_NULL
;
153 if (mutex
->cond_lock
) {
154 mutex
->cond_lock
= 0;
158 _pthread_mutex_add(mutex
);
160 mutex
->owner
= (pthread_t
)0x12141968;
167 * Attempt to lock a mutex, but don't block if this isn't possible.
170 pthread_mutex_trylock(pthread_mutex_t
*mutex
)
172 kern_return_t kern_res
;
174 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
177 if (res
= pthread_mutex_init(mutex
, NULL
))
180 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
181 return (EINVAL
); /* Not a mutex variable */
182 if (!TRY_LOCK(mutex
->lock
)) {
185 if (mutex
->waiters
||
186 ((mutex
->owner
!= (pthread_t
)NULL
) && (mutex
->cond_lock
== 0)))
193 _pthread_mutex_add(mutex
);
195 mutex
->owner
= (pthread_t
)0x12141968;
197 if (mutex
->cond_lock
) {
198 PTHREAD_MACH_CALL(semaphore_wait(mutex
->sem
), kern_res
);
199 mutex
->cond_lock
= 0;
200 restore_sem_to_pool(mutex
->sem
);
201 mutex
->sem
= MACH_PORT_NULL
;
210 * TODO: Priority inheritance stuff
213 pthread_mutex_unlock(pthread_mutex_t
*mutex
)
215 kern_return_t kern_res
;
217 if (mutex
->sig
== _PTHREAD_MUTEX_SIG_init
)
220 if (res
= pthread_mutex_init(mutex
, NULL
))
223 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
224 return (EINVAL
); /* Not a mutex variable */
227 if (mutex
->owner
!= pthread_self())
236 _pthread_mutex_remove(mutex
, mutex
->owner
);
238 mutex
->owner
= (pthread_t
)NULL
;
240 waiters
= mutex
->waiters
;
244 PTHREAD_MACH_CALL(semaphore_signal(mutex
->sem
), kern_res
);
251 * Fetch the priority ceiling value from a mutex variable.
252 * Note: written as a 'helper' function to hide implementation details.
255 pthread_mutex_getprioceiling(const pthread_mutex_t
*mutex
,
258 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
260 *prioceiling
= mutex
->prioceiling
;
264 return (EINVAL
); /* Not an initialized 'attribute' structure */
269 * Set the priority ceiling for a mutex.
270 * Note: written as a 'helper' function to hide implementation details.
273 pthread_mutex_setprioceiling(pthread_mutex_t
*mutex
,
275 int *old_prioceiling
)
277 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
279 if ((prioceiling
>= -999) ||
280 (prioceiling
<= 999))
282 *old_prioceiling
= mutex
->prioceiling
;
283 mutex
->prioceiling
= prioceiling
;
287 return (EINVAL
); /* Invalid parameter */
291 return (EINVAL
); /* Not an initialized 'attribute' structure */
296 * Destroy a mutex attribute structure.
299 pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
301 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
306 * Get the priority ceiling value from a mutex attribute structure.
307 * Note: written as a 'helper' function to hide implementation details.
310 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t
*attr
,
313 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
315 *prioceiling
= attr
->prioceiling
;
319 return (EINVAL
); /* Not an initialized 'attribute' structure */
324 * Get the mutex 'protocol' value from a mutex attribute structure.
325 * Note: written as a 'helper' function to hide implementation details.
328 pthread_mutexattr_getprotocol(const pthread_mutexattr_t
*attr
,
331 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
333 *protocol
= attr
->protocol
;
337 return (EINVAL
); /* Not an initialized 'attribute' structure */
342 * Initialize a mutex attribute structure to system defaults.
345 pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
347 attr
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
348 attr
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
349 attr
->sig
= _PTHREAD_MUTEX_ATTR_SIG
;
354 * Set the priority ceiling value in a mutex attribute structure.
355 * Note: written as a 'helper' function to hide implementation details.
358 pthread_mutexattr_setprioceiling(pthread_mutexattr_t
*attr
,
361 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
363 if ((prioceiling
>= -999) ||
364 (prioceiling
<= 999))
366 attr
->prioceiling
= prioceiling
;
370 return (EINVAL
); /* Invalid parameter */
374 return (EINVAL
); /* Not an initialized 'attribute' structure */
379 * Set the mutex 'protocol' value in a mutex attribute structure.
380 * Note: written as a 'helper' function to hide implementation details.
383 pthread_mutexattr_setprotocol(pthread_mutexattr_t
*attr
,
386 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
388 if ((protocol
== PTHREAD_PRIO_NONE
) ||
389 (protocol
== PTHREAD_PRIO_INHERIT
) ||
390 (protocol
== PTHREAD_PRIO_PROTECT
))
392 attr
->protocol
= protocol
;
396 return (EINVAL
); /* Invalid parameter */
400 return (EINVAL
); /* Not an initialized 'attribute' structure */
404 int mutex_try_lock(int *x
) {
405 return _spin_lock_try((pthread_lock_t
*)x
);
408 void mutex_wait_lock(int *x
) {
410 if( _spin_lock_try((pthread_lock_t
*)x
)) {
417 void cthread_yield(void) {