2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
29 * Permission to use, copy, modify, and distribute this software and
30 * its documentation for any purpose and without fee is hereby granted,
31 * provided that the above copyright notice appears in all copies and
32 * that both the copyright notice and this permission notice appear in
33 * supporting documentation.
35 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
37 * FOR A PARTICULAR PURPOSE.
39 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
40 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
41 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
42 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
43 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 * POSIX Pthread Library
52 * -- Mutex variable support
55 #include "pthread_internals.h"
58 * Destroy a mutex variable.
61 pthread_mutex_destroy(pthread_mutex_t
*mutex
)
66 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
68 if (mutex
->owner
== (pthread_t
)NULL
&&
69 mutex
->busy
== (pthread_cond_t
*)NULL
)
71 mutex
->sig
= _PTHREAD_NO_SIG
;
84 * Initialize a mutex variable, possibly with additional attributes.
87 _pthread_mutex_init(pthread_mutex_t
*mutex
, const pthread_mutexattr_t
*attr
)
91 if (attr
->sig
!= _PTHREAD_MUTEX_ATTR_SIG
)
93 mutex
->prioceiling
= attr
->prioceiling
;
94 mutex
->protocol
= attr
->protocol
;
95 mutex
->type
= attr
->type
;
97 mutex
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
98 mutex
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
99 mutex
->type
= PTHREAD_MUTEX_DEFAULT
;
101 mutex
->lock_count
= 0;
102 mutex
->owner
= (pthread_t
)NULL
;
103 mutex
->next
= (pthread_mutex_t
*)NULL
;
104 mutex
->prev
= (pthread_mutex_t
*)NULL
;
105 mutex
->busy
= (pthread_cond_t
*)NULL
;
107 mutex
->sem
= SEMAPHORE_NULL
;
108 mutex
->order
= SEMAPHORE_NULL
;
109 mutex
->sig
= _PTHREAD_MUTEX_SIG
;
114 * Initialize a mutex variable, possibly with additional attributes.
115 * Public interface - so don't trust the lock - initialize it first.
118 pthread_mutex_init(pthread_mutex_t
*mutex
, const pthread_mutexattr_t
*attr
)
120 LOCK_INIT(mutex
->lock
);
121 return (_pthread_mutex_init(mutex
, attr
));
125 * Manage a list of mutex variables owned by a thread
129 _pthread_mutex_add(pthread_mutex_t
*mutex
, pthread_t self
)
132 if (self
!= (pthread_t
)0)
134 if ((m
= self
->mutexes
) != (pthread_mutex_t
*)NULL
)
139 mutex
->prev
= (pthread_mutex_t
*)NULL
;
140 self
->mutexes
= mutex
;
144 __private_extern__
void
145 _pthread_mutex_remove(pthread_mutex_t
*mutex
, pthread_t self
)
147 pthread_mutex_t
*n
, *prev
;
148 if ((n
= mutex
->next
) != (pthread_mutex_t
*)NULL
)
150 n
->prev
= mutex
->prev
;
152 if ((prev
= mutex
->prev
) != (pthread_mutex_t
*)NULL
)
154 prev
->next
= mutex
->next
;
156 { /* This is the first in the list */
157 if (self
!= (pthread_t
)0) {
166 * TODO: Priority inheritance stuff
169 pthread_mutex_lock(pthread_mutex_t
*mutex
)
171 kern_return_t kern_res
;
173 int sig
= mutex
->sig
;
175 /* To provide backwards compat for apps using mutex incorrectly */
176 if ((sig
!= _PTHREAD_MUTEX_SIG
) && (sig
!= _PTHREAD_MUTEX_SIG_init
))
179 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
181 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG_init
)
186 _pthread_mutex_init(mutex
, NULL
);
187 self
= _PTHREAD_MUTEX_OWNER_SELF
;
189 else if (mutex
->type
!= PTHREAD_MUTEX_NORMAL
)
191 self
= pthread_self();
192 if (mutex
->owner
== self
)
196 if (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
)
198 if (mutex
->lock_count
< USHRT_MAX
)
204 } else /* PTHREAD_MUTEX_ERRORCHECK */
210 self
= _PTHREAD_MUTEX_OWNER_SELF
;
212 if (mutex
->owner
!= (pthread_t
)NULL
) {
213 if (mutex
->waiters
|| mutex
->owner
!= _PTHREAD_MUTEX_OWNER_SWITCHING
)
215 semaphore_t sem
, order
;
217 if (++mutex
->waiters
== 1)
219 mutex
->sem
= sem
= new_sem_from_pool();
220 mutex
->order
= order
= new_sem_from_pool();
225 order
= mutex
->order
;
227 PTHREAD_MACH_CALL(semaphore_wait(order
), kern_res
);
228 } while (kern_res
== KERN_ABORTED
);
232 PTHREAD_MACH_CALL(semaphore_wait_signal(sem
, order
), kern_res
);
233 while (kern_res
== KERN_ABORTED
)
235 PTHREAD_MACH_CALL(semaphore_wait(sem
), kern_res
);
239 if (--mutex
->waiters
== 0)
241 PTHREAD_MACH_CALL(semaphore_wait(order
), kern_res
);
242 mutex
->sem
= mutex
->order
= SEMAPHORE_NULL
;
243 restore_sem_to_pool(order
);
244 restore_sem_to_pool(sem
);
247 else if (mutex
->owner
== _PTHREAD_MUTEX_OWNER_SWITCHING
)
249 semaphore_t sem
= mutex
->sem
;
251 PTHREAD_MACH_CALL(semaphore_wait(sem
), kern_res
);
252 } while (kern_res
== KERN_ABORTED
);
253 mutex
->sem
= SEMAPHORE_NULL
;
254 restore_sem_to_pool(sem
);
258 mutex
->lock_count
= 1;
261 _pthread_mutex_add(mutex
, self
);
268 * Attempt to lock a mutex, but don't block if this isn't possible.
271 pthread_mutex_trylock(pthread_mutex_t
*mutex
)
273 kern_return_t kern_res
;
277 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
279 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG_init
)
284 _pthread_mutex_init(mutex
, NULL
);
285 self
= _PTHREAD_MUTEX_OWNER_SELF
;
287 else if (mutex
->type
!= PTHREAD_MUTEX_NORMAL
)
289 self
= pthread_self();
290 if (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
)
292 if (mutex
->owner
== self
)
296 if (mutex
->lock_count
< USHRT_MAX
)
307 self
= _PTHREAD_MUTEX_OWNER_SELF
;
309 if (mutex
->owner
!= (pthread_t
)NULL
)
311 if (mutex
->waiters
|| mutex
->owner
!= _PTHREAD_MUTEX_OWNER_SWITCHING
)
316 else if (mutex
->owner
== _PTHREAD_MUTEX_OWNER_SWITCHING
)
318 semaphore_t sem
= mutex
->sem
;
321 PTHREAD_MACH_CALL(semaphore_wait(sem
), kern_res
);
322 } while (kern_res
== KERN_ABORTED
);
323 restore_sem_to_pool(sem
);
324 mutex
->sem
= SEMAPHORE_NULL
;
328 mutex
->lock_count
= 1;
331 _pthread_mutex_add(mutex
, self
);
339 * TODO: Priority inheritance stuff
342 pthread_mutex_unlock(pthread_mutex_t
*mutex
)
344 kern_return_t kern_res
;
346 int sig
= mutex
->sig
;
348 /* To provide backwards compat for apps using mutex incorrectly */
350 if ((sig
!= _PTHREAD_MUTEX_SIG
) && (sig
!= _PTHREAD_MUTEX_SIG_init
))
353 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG
)
355 if (mutex
->sig
!= _PTHREAD_MUTEX_SIG_init
)
358 return (EINVAL
); /* Not a mutex variable */
360 _pthread_mutex_init(mutex
, NULL
);
364 if (mutex
->type
!= PTHREAD_MUTEX_NORMAL
)
367 pthread_t self
= pthread_self();
368 if (mutex
->owner
!= self
)
375 } else if (mutex
->type
== PTHREAD_MUTEX_RECURSIVE
&&
383 mutex
->lock_count
= 0;
385 _pthread_mutex_remove(mutex
, mutex
->owner
);
388 waiters
= mutex
->waiters
;
391 mutex
->owner
= _PTHREAD_MUTEX_OWNER_SWITCHING
;
393 PTHREAD_MACH_CALL(semaphore_signal(mutex
->sem
), kern_res
);
397 mutex
->owner
= (pthread_t
)NULL
;
404 * Fetch the priority ceiling value from a mutex variable.
405 * Note: written as a 'helper' function to hide implementation details.
408 pthread_mutex_getprioceiling(const pthread_mutex_t
*mutex
,
414 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
416 *prioceiling
= mutex
->prioceiling
;
419 res
= EINVAL
; /* Not an initialized 'attribute' structure */
425 * Set the priority ceiling for a mutex.
426 * Note: written as a 'helper' function to hide implementation details.
429 pthread_mutex_setprioceiling(pthread_mutex_t
*mutex
,
431 int *old_prioceiling
)
436 if (mutex
->sig
== _PTHREAD_MUTEX_SIG
)
438 if ((prioceiling
>= -999) ||
439 (prioceiling
<= 999))
441 *old_prioceiling
= mutex
->prioceiling
;
442 mutex
->prioceiling
= prioceiling
;
445 res
= EINVAL
; /* Invalid parameter */
447 res
= EINVAL
; /* Not an initialized 'attribute' structure */
453 * Destroy a mutex attribute structure.
456 pthread_mutexattr_destroy(pthread_mutexattr_t
*attr
)
458 attr
->sig
= _PTHREAD_NO_SIG
; /* Uninitialized */
463 * Get the priority ceiling value from a mutex attribute structure.
464 * Note: written as a 'helper' function to hide implementation details.
467 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t
*attr
,
470 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
472 *prioceiling
= attr
->prioceiling
;
476 return (EINVAL
); /* Not an initialized 'attribute' structure */
481 * Get the mutex 'protocol' value from a mutex attribute structure.
482 * Note: written as a 'helper' function to hide implementation details.
485 pthread_mutexattr_getprotocol(const pthread_mutexattr_t
*attr
,
488 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
490 *protocol
= attr
->protocol
;
494 return (EINVAL
); /* Not an initialized 'attribute' structure */
498 * Get the mutex 'type' value from a mutex attribute structure.
499 * Note: written as a 'helper' function to hide implementation details.
502 pthread_mutexattr_gettype(const pthread_mutexattr_t
*attr
,
505 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
511 return (EINVAL
); /* Not an initialized 'attribute' structure */
519 pthread_mutexattr_getpshared(const pthread_mutexattr_t
*attr
, int *pshared
)
521 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
523 *pshared
= (int)PTHREAD_PROCESS_PRIVATE
;
527 return (EINVAL
); /* Not an initialized 'attribute' structure */
532 * Initialize a mutex attribute structure to system defaults.
535 pthread_mutexattr_init(pthread_mutexattr_t
*attr
)
537 attr
->prioceiling
= _PTHREAD_DEFAULT_PRIOCEILING
;
538 attr
->protocol
= _PTHREAD_DEFAULT_PROTOCOL
;
539 attr
->type
= PTHREAD_MUTEX_DEFAULT
;
540 attr
->sig
= _PTHREAD_MUTEX_ATTR_SIG
;
545 * Set the priority ceiling value in a mutex attribute structure.
546 * Note: written as a 'helper' function to hide implementation details.
549 pthread_mutexattr_setprioceiling(pthread_mutexattr_t
*attr
,
552 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
554 if ((prioceiling
>= -999) ||
555 (prioceiling
<= 999))
557 attr
->prioceiling
= prioceiling
;
561 return (EINVAL
); /* Invalid parameter */
565 return (EINVAL
); /* Not an initialized 'attribute' structure */
570 * Set the mutex 'protocol' value in a mutex attribute structure.
571 * Note: written as a 'helper' function to hide implementation details.
574 pthread_mutexattr_setprotocol(pthread_mutexattr_t
*attr
,
577 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
579 if ((protocol
== PTHREAD_PRIO_NONE
) ||
580 (protocol
== PTHREAD_PRIO_INHERIT
) ||
581 (protocol
== PTHREAD_PRIO_PROTECT
))
583 attr
->protocol
= protocol
;
587 return (EINVAL
); /* Invalid parameter */
591 return (EINVAL
); /* Not an initialized 'attribute' structure */
595 * Set the mutex 'type' value in a mutex attribute structure.
596 * Note: written as a 'helper' function to hide implementation details.
599 pthread_mutexattr_settype(pthread_mutexattr_t
*attr
,
602 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
604 if ((type
== PTHREAD_MUTEX_NORMAL
) ||
605 (type
== PTHREAD_MUTEX_ERRORCHECK
) ||
606 (type
== PTHREAD_MUTEX_RECURSIVE
) ||
607 (type
== PTHREAD_MUTEX_DEFAULT
))
613 return (EINVAL
); /* Invalid parameter */
617 return (EINVAL
); /* Not an initialized 'attribute' structure */
625 pthread_mutexattr_setpshared(pthread_mutexattr_t
*attr
, int pshared
)
627 if (attr
->sig
== _PTHREAD_MUTEX_ATTR_SIG
)
629 if (pshared
== PTHREAD_PROCESS_PRIVATE
)
631 /* attr->pshared = protocol; */
635 return (EINVAL
); /* Invalid parameter */
639 return (EINVAL
); /* Not an initialized 'attribute' structure */
643 int mutex_try_lock(int *x
) {
644 return _spin_lock_try((pthread_lock_t
*)x
);
647 void mutex_wait_lock(int *x
) {
649 if( _spin_lock_try((pthread_lock_t
*)x
)) {
663 pthread_yield_np (void)