]> git.saurik.com Git - apple/libc.git/blob - pthreads/pthread_mutex.c
Libc-498.1.5.tar.gz
[apple/libc.git] / pthreads / pthread_mutex.c
1 /*
2 * Copyright (c) 2000-2003, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
25 * All Rights Reserved
26 *
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby granted,
29 * provided that the above copyright notice appears in all copies and
30 * that both the copyright notice and this permission notice appear in
31 * supporting documentation.
32 *
33 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
36 *
37 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42 *
43 */
44 /*
45 * MkLinux
46 */
47
48 /*
49 * POSIX Pthread Library
50 * -- Mutex variable support
51 */
52
53 #include "pthread_internals.h"
54
55 #ifdef PLOCKSTAT
56 #include "plockstat.h"
57 #else /* !PLOCKSTAT */
58 #define PLOCKSTAT_MUTEX_SPIN(x)
59 #define PLOCKSTAT_MUTEX_SPUN(x, y, z)
60 #define PLOCKSTAT_MUTEX_ERROR(x, y)
61 #define PLOCKSTAT_MUTEX_BLOCK(x)
62 #define PLOCKSTAT_MUTEX_BLOCKED(x, y)
63 #define PLOCKSTAT_MUTEX_ACQUIRE(x, y, z)
64 #define PLOCKSTAT_MUTEX_RELEASE(x, y)
65 #endif /* PLOCKSTAT */
66
67 extern int __unix_conforming;
68
69 #ifndef BUILDING_VARIANT /* [ */
70
71 #define BLOCK_FAIL_PLOCKSTAT 0
72 #define BLOCK_SUCCESS_PLOCKSTAT 1
73
74 /* This function is never called and exists to provide never-fired dtrace
75 * probes so that user d scripts don't get errors.
76 */
77 __private_extern__ void _plockstat_never_fired(void)
78 {
79 PLOCKSTAT_MUTEX_SPIN(NULL);
80 PLOCKSTAT_MUTEX_SPUN(NULL, 0, 0);
81 }
82
83 /*
84 * Destroy a mutex variable.
85 */
86 int
87 pthread_mutex_destroy(pthread_mutex_t *mutex)
88 {
89 int res;
90
91 LOCK(mutex->lock);
92 if (mutex->sig == _PTHREAD_MUTEX_SIG)
93 {
94 if (mutex->owner == (pthread_t)NULL &&
95 mutex->busy == (pthread_cond_t *)NULL)
96 {
97 mutex->sig = _PTHREAD_NO_SIG;
98 res = 0;
99 }
100 else
101 res = EBUSY;
102 } else if (mutex->sig == _PTHREAD_KERN_MUTEX_SIG) {
103 int mutexid = mutex->_pthread_mutex_kernid;
104 UNLOCK(mutex->lock);
105 if( __pthread_mutex_destroy(mutexid) == -1)
106 return(errno);
107 mutex->sig = _PTHREAD_NO_SIG;
108 return(0);
109 } else
110 res = EINVAL;
111 UNLOCK(mutex->lock);
112 return (res);
113 }
114
115 #ifdef PR_5243343
116 /* 5243343 - temporary hack to detect if we are running the conformance test */
117 extern int PR_5243343_flag;
118 #endif /* PR_5243343 */
119 /*
120 * Initialize a mutex variable, possibly with additional attributes.
121 */
122 static int
123 _pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
124 {
125 if (attr)
126 {
127 if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG)
128 return (EINVAL);
129 mutex->prioceiling = attr->prioceiling;
130 mutex->protocol = attr->protocol;
131 mutex->type = attr->type;
132 mutex->pshared = attr->pshared;
133 if (attr->pshared == PTHREAD_PROCESS_SHARED) {
134 mutex->lock_count = 0;
135 mutex->owner = (pthread_t)NULL;
136 mutex->next = (pthread_mutex_t *)NULL;
137 mutex->prev = (pthread_mutex_t *)NULL;
138 mutex->busy = (pthread_cond_t *)NULL;
139 mutex->waiters = 0;
140 mutex->sem = SEMAPHORE_NULL;
141 mutex->order = SEMAPHORE_NULL;
142 mutex->sig = 0;
143 if( __pthread_mutex_init(mutex, attr) == -1)
144 return(errno);
145 mutex->sig = _PTHREAD_KERN_MUTEX_SIG;
146 return(0);
147 }
148 } else {
149 mutex->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
150 mutex->protocol = _PTHREAD_DEFAULT_PROTOCOL;
151 mutex->type = PTHREAD_MUTEX_DEFAULT;
152 mutex->pshared = _PTHREAD_DEFAULT_PSHARED;
153 }
154 mutex->lock_count = 0;
155 mutex->owner = (pthread_t)NULL;
156 mutex->next = (pthread_mutex_t *)NULL;
157 mutex->prev = (pthread_mutex_t *)NULL;
158 mutex->busy = (pthread_cond_t *)NULL;
159 mutex->waiters = 0;
160 mutex->sem = SEMAPHORE_NULL;
161 mutex->order = SEMAPHORE_NULL;
162 mutex->sig = _PTHREAD_MUTEX_SIG;
163 return (0);
164 }
165
166 /*
167 * Initialize a mutex variable, possibly with additional attributes.
168 * Public interface - so don't trust the lock - initialize it first.
169 */
170 int
171 pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
172 {
173 #if 0
174 /* conformance tests depend on not having this behavior */
175 /* The test for this behavior is optional */
176 if (mutex->sig == _PTHREAD_MUTEX_SIG)
177 return EBUSY;
178 #endif
179 LOCK_INIT(mutex->lock);
180 return (_pthread_mutex_init(mutex, attr));
181 }
182
183 /*
184 * Manage a list of mutex variables owned by a thread
185 */
186 #if defined(DEBUG)
187 static void
188 _pthread_mutex_add(pthread_mutex_t *mutex, pthread_t self)
189 {
190 pthread_mutex_t *m;
191 if (self != (pthread_t)0)
192 {
193 if ((m = self->mutexes) != (pthread_mutex_t *)NULL)
194 { /* Add to list */
195 m->prev = mutex;
196 }
197 mutex->next = m;
198 mutex->prev = (pthread_mutex_t *)NULL;
199 self->mutexes = mutex;
200 }
201 }
202
203 __private_extern__ void
204 _pthread_mutex_remove(pthread_mutex_t *mutex, pthread_t self)
205 {
206 pthread_mutex_t *n, *prev;
207 if ((n = mutex->next) != (pthread_mutex_t *)NULL)
208 {
209 n->prev = mutex->prev;
210 }
211 if ((prev = mutex->prev) != (pthread_mutex_t *)NULL)
212 {
213 prev->next = mutex->next;
214 } else
215 { /* This is the first in the list */
216 if (self != (pthread_t)0) {
217 self->mutexes = n;
218 }
219 }
220 }
221 #endif
222
223 /*
224 * Lock a mutex.
225 * TODO: Priority inheritance stuff
226 */
227 int
228 pthread_mutex_lock(pthread_mutex_t *mutex)
229 {
230 kern_return_t kern_res;
231 pthread_t self;
232 int sig = mutex->sig;
233
234 /* To provide backwards compat for apps using mutex incorrectly */
235 if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init) && (sig != _PTHREAD_KERN_MUTEX_SIG)) {
236 PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
237 return(EINVAL);
238 }
239 LOCK(mutex->lock);
240 if (mutex->sig != _PTHREAD_MUTEX_SIG)
241 {
242 if (mutex->sig != _PTHREAD_MUTEX_SIG_init)
243 {
244 if (mutex->sig == _PTHREAD_KERN_MUTEX_SIG) {
245 int mutexid = mutex->_pthread_mutex_kernid;
246 UNLOCK(mutex->lock);
247
248 PLOCKSTAT_MUTEX_BLOCK(mutex);
249 if( __pthread_mutex_lock(mutexid) == -1) {
250 PLOCKSTAT_MUTEX_BLOCKED(mutex, BLOCK_FAIL_PLOCKSTAT);
251 PLOCKSTAT_MUTEX_ERROR(mutex, errno);
252 return(errno);
253 }
254
255 PLOCKSTAT_MUTEX_BLOCKED(mutex, BLOCK_SUCCESS_PLOCKSTAT);
256 PLOCKSTAT_MUTEX_ACQUIRE(mutex, 0, 0);
257 return(0);
258 } else {
259 UNLOCK(mutex->lock);
260 PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
261 return (EINVAL);
262 }
263 }
264 _pthread_mutex_init(mutex, NULL);
265 self = _PTHREAD_MUTEX_OWNER_SELF;
266 }
267 else if (mutex->type != PTHREAD_MUTEX_NORMAL)
268 {
269 self = pthread_self();
270 if (mutex->owner == self)
271 {
272 int res;
273
274 if (mutex->type == PTHREAD_MUTEX_RECURSIVE)
275 {
276 if (mutex->lock_count < USHRT_MAX)
277 {
278 mutex->lock_count++;
279 PLOCKSTAT_MUTEX_ACQUIRE(mutex, 1, 0);
280 res = 0;
281 } else {
282 res = EAGAIN;
283 PLOCKSTAT_MUTEX_ERROR(mutex, res);
284 }
285 } else { /* PTHREAD_MUTEX_ERRORCHECK */
286 res = EDEADLK;
287 PLOCKSTAT_MUTEX_ERROR(mutex, res);
288 }
289 UNLOCK(mutex->lock);
290 return (res);
291 }
292 } else
293 self = _PTHREAD_MUTEX_OWNER_SELF;
294
295 if (mutex->owner != (pthread_t)NULL) {
296 if (mutex->waiters || mutex->owner != _PTHREAD_MUTEX_OWNER_SWITCHING)
297 {
298 semaphore_t sem, order;
299
300 if (++mutex->waiters == 1)
301 {
302 mutex->sem = sem = new_sem_from_pool();
303 mutex->order = order = new_sem_from_pool();
304 }
305 else
306 {
307 sem = mutex->sem;
308 order = mutex->order;
309 do {
310 PTHREAD_MACH_CALL(semaphore_wait(order), kern_res);
311 } while (kern_res == KERN_ABORTED);
312 }
313 UNLOCK(mutex->lock);
314
315 PLOCKSTAT_MUTEX_BLOCK(mutex);
316 PTHREAD_MACH_CALL(semaphore_wait_signal(sem, order), kern_res);
317 while (kern_res == KERN_ABORTED)
318 {
319 PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
320 }
321
322 PLOCKSTAT_MUTEX_BLOCKED(mutex, BLOCK_SUCCESS_PLOCKSTAT);
323
324 LOCK(mutex->lock);
325 if (--mutex->waiters == 0)
326 {
327 PTHREAD_MACH_CALL(semaphore_wait(order), kern_res);
328 mutex->sem = mutex->order = SEMAPHORE_NULL;
329 restore_sem_to_pool(order);
330 restore_sem_to_pool(sem);
331 }
332 }
333 else if (mutex->owner == _PTHREAD_MUTEX_OWNER_SWITCHING)
334 {
335 semaphore_t sem = mutex->sem;
336 do {
337 PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
338 } while (kern_res == KERN_ABORTED);
339 mutex->sem = SEMAPHORE_NULL;
340 restore_sem_to_pool(sem);
341 }
342 }
343
344 mutex->lock_count = 1;
345 mutex->owner = self;
346 #if defined(DEBUG)
347 _pthread_mutex_add(mutex, self);
348 #endif
349 UNLOCK(mutex->lock);
350 PLOCKSTAT_MUTEX_ACQUIRE(mutex, 0, 0);
351 return (0);
352 }
353
354 /*
355 * Attempt to lock a mutex, but don't block if this isn't possible.
356 */
357 int
358 pthread_mutex_trylock(pthread_mutex_t *mutex)
359 {
360 kern_return_t kern_res;
361 pthread_t self;
362
363 LOCK(mutex->lock);
364 if (mutex->sig != _PTHREAD_MUTEX_SIG)
365 {
366 if (mutex->sig != _PTHREAD_MUTEX_SIG_init)
367 {
368
369 if (mutex->sig == _PTHREAD_KERN_MUTEX_SIG) {
370 int mutexid = mutex->_pthread_mutex_kernid;
371 UNLOCK(mutex->lock);
372 if( __pthread_mutex_trylock(mutexid) == -1) {
373 PLOCKSTAT_MUTEX_ERROR(mutex, errno);
374 return(errno);
375 }
376 PLOCKSTAT_MUTEX_ACQUIRE(mutex, 0, 0);
377 return(0);
378 } else {
379 PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
380 UNLOCK(mutex->lock);
381 return (EINVAL);
382 }
383 }
384 _pthread_mutex_init(mutex, NULL);
385 self = _PTHREAD_MUTEX_OWNER_SELF;
386 }
387 else if (mutex->type != PTHREAD_MUTEX_NORMAL)
388 {
389 self = pthread_self();
390 if (mutex->type == PTHREAD_MUTEX_RECURSIVE)
391 {
392 if (mutex->owner == self)
393 {
394 int res;
395
396 if (mutex->lock_count < USHRT_MAX)
397 {
398 mutex->lock_count++;
399 PLOCKSTAT_MUTEX_ACQUIRE(mutex, 1, 0);
400 res = 0;
401 } else {
402 res = EAGAIN;
403 PLOCKSTAT_MUTEX_ERROR(mutex, res);
404 }
405 UNLOCK(mutex->lock);
406 return (res);
407 }
408 }
409 } else
410 self = _PTHREAD_MUTEX_OWNER_SELF;
411
412 if (mutex->owner != (pthread_t)NULL)
413 {
414 if (mutex->waiters || mutex->owner != _PTHREAD_MUTEX_OWNER_SWITCHING)
415 {
416 PLOCKSTAT_MUTEX_ERROR(mutex, EBUSY);
417 UNLOCK(mutex->lock);
418 return (EBUSY);
419 }
420 else if (mutex->owner == _PTHREAD_MUTEX_OWNER_SWITCHING)
421 {
422 semaphore_t sem = mutex->sem;
423
424 do {
425 PTHREAD_MACH_CALL(semaphore_wait(sem), kern_res);
426 } while (kern_res == KERN_ABORTED);
427 restore_sem_to_pool(sem);
428 mutex->sem = SEMAPHORE_NULL;
429 }
430 }
431
432 mutex->lock_count = 1;
433 mutex->owner = self;
434 #if defined(DEBUG)
435 _pthread_mutex_add(mutex, self);
436 #endif
437 UNLOCK(mutex->lock);
438 PLOCKSTAT_MUTEX_ACQUIRE(mutex, 0, 0);
439 return (0);
440 }
441
442 /*
443 * Unlock a mutex.
444 * TODO: Priority inheritance stuff
445 */
446 int
447 pthread_mutex_unlock(pthread_mutex_t *mutex)
448 {
449 kern_return_t kern_res;
450 int waiters;
451 int sig = mutex->sig;
452
453 /* To provide backwards compat for apps using mutex incorrectly */
454
455 if ((sig != _PTHREAD_MUTEX_SIG) && (sig != _PTHREAD_MUTEX_SIG_init) && (sig != _PTHREAD_KERN_MUTEX_SIG)) {
456 PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
457 return(EINVAL);
458 }
459 LOCK(mutex->lock);
460 if (mutex->sig != _PTHREAD_MUTEX_SIG)
461 {
462 if (mutex->sig != _PTHREAD_MUTEX_SIG_init)
463 {
464 if (mutex->sig == _PTHREAD_KERN_MUTEX_SIG) {
465 int mutexid = mutex->_pthread_mutex_kernid;
466 UNLOCK(mutex->lock);
467 if( __pthread_mutex_unlock(mutexid) == -1) {
468 PLOCKSTAT_MUTEX_ERROR(mutex, errno);
469 return(errno);
470 }
471 PLOCKSTAT_MUTEX_RELEASE(mutex, 0);
472 return(0);
473 } else {
474 PLOCKSTAT_MUTEX_ERROR(mutex, EINVAL);
475 UNLOCK(mutex->lock);
476 return (EINVAL);
477 }
478 }
479 _pthread_mutex_init(mutex, NULL);
480 } else
481
482 #if !defined(DEBUG)
483 if (mutex->type != PTHREAD_MUTEX_NORMAL)
484 #endif
485 {
486 pthread_t self = pthread_self();
487 if (mutex->owner != self)
488 {
489 #if defined(DEBUG)
490 abort();
491 #endif
492 PLOCKSTAT_MUTEX_ERROR(mutex, EPERM);
493 UNLOCK(mutex->lock);
494 return EPERM;
495 } else if (mutex->type == PTHREAD_MUTEX_RECURSIVE &&
496 --mutex->lock_count)
497 {
498 PLOCKSTAT_MUTEX_RELEASE(mutex, 1);
499 UNLOCK(mutex->lock);
500 return(0);
501 }
502 }
503
504 mutex->lock_count = 0;
505 #if defined(DEBUG)
506 _pthread_mutex_remove(mutex, mutex->owner);
507 #endif /* DEBUG */
508
509 waiters = mutex->waiters;
510 if (waiters)
511 {
512 mutex->owner = _PTHREAD_MUTEX_OWNER_SWITCHING;
513 PLOCKSTAT_MUTEX_RELEASE(mutex, 0);
514 UNLOCK(mutex->lock);
515 PTHREAD_MACH_CALL(semaphore_signal(mutex->sem), kern_res);
516 }
517 else
518 {
519 mutex->owner = (pthread_t)NULL;
520 PLOCKSTAT_MUTEX_RELEASE(mutex, 0);
521 UNLOCK(mutex->lock);
522 }
523 return (0);
524 }
525
526 /*
527 * Fetch the priority ceiling value from a mutex variable.
528 * Note: written as a 'helper' function to hide implementation details.
529 */
530 int
531 pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,
532 int *prioceiling)
533 {
534 int res;
535
536 LOCK(mutex->lock);
537 if (mutex->sig == _PTHREAD_MUTEX_SIG)
538 {
539 *prioceiling = mutex->prioceiling;
540 res = 0;
541 } else
542 res = EINVAL; /* Not an initialized 'attribute' structure */
543 UNLOCK(mutex->lock);
544 return (res);
545 }
546
547 /*
548 * Set the priority ceiling for a mutex.
549 * Note: written as a 'helper' function to hide implementation details.
550 */
551 int
552 pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
553 int prioceiling,
554 int *old_prioceiling)
555 {
556 int res;
557
558 LOCK(mutex->lock);
559 if (mutex->sig == _PTHREAD_MUTEX_SIG)
560 {
561 if ((prioceiling >= -999) ||
562 (prioceiling <= 999))
563 {
564 *old_prioceiling = mutex->prioceiling;
565 mutex->prioceiling = prioceiling;
566 res = 0;
567 } else
568 res = EINVAL; /* Invalid parameter */
569 } else
570 res = EINVAL; /* Not an initialized 'attribute' structure */
571 UNLOCK(mutex->lock);
572 return (res);
573 }
574
575 /*
576 * Get the priority ceiling value from a mutex attribute structure.
577 * Note: written as a 'helper' function to hide implementation details.
578 */
579 int
580 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr,
581 int *prioceiling)
582 {
583 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
584 {
585 *prioceiling = attr->prioceiling;
586 return (0);
587 } else
588 {
589 return (EINVAL); /* Not an initialized 'attribute' structure */
590 }
591 }
592
593 /*
594 * Get the mutex 'protocol' value from a mutex attribute structure.
595 * Note: written as a 'helper' function to hide implementation details.
596 */
597 int
598 pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,
599 int *protocol)
600 {
601 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
602 {
603 *protocol = attr->protocol;
604 return (0);
605 } else
606 {
607 return (EINVAL); /* Not an initialized 'attribute' structure */
608 }
609 }
610 /*
611 * Get the mutex 'type' value from a mutex attribute structure.
612 * Note: written as a 'helper' function to hide implementation details.
613 */
614 int
615 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr,
616 int *type)
617 {
618 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
619 {
620 *type = attr->type;
621 return (0);
622 } else
623 {
624 return (EINVAL); /* Not an initialized 'attribute' structure */
625 }
626 }
627
628 /*
629 *
630 */
631 int
632 pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared)
633 {
634 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
635 {
636 *pshared = (int)attr->pshared;
637 return (0);
638 } else
639 {
640 return (EINVAL); /* Not an initialized 'attribute' structure */
641 }
642 }
643
644 /*
645 * Initialize a mutex attribute structure to system defaults.
646 */
647 int
648 pthread_mutexattr_init(pthread_mutexattr_t *attr)
649 {
650 attr->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
651 attr->protocol = _PTHREAD_DEFAULT_PROTOCOL;
652 attr->type = PTHREAD_MUTEX_DEFAULT;
653 attr->sig = _PTHREAD_MUTEX_ATTR_SIG;
654 attr->pshared = _PTHREAD_DEFAULT_PSHARED;
655 return (0);
656 }
657
658 /*
659 * Set the priority ceiling value in a mutex attribute structure.
660 * Note: written as a 'helper' function to hide implementation details.
661 */
662 int
663 pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr,
664 int prioceiling)
665 {
666 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
667 {
668 if ((prioceiling >= -999) ||
669 (prioceiling <= 999))
670 {
671 attr->prioceiling = prioceiling;
672 return (0);
673 } else
674 {
675 return (EINVAL); /* Invalid parameter */
676 }
677 } else
678 {
679 return (EINVAL); /* Not an initialized 'attribute' structure */
680 }
681 }
682
683 /*
684 * Set the mutex 'protocol' value in a mutex attribute structure.
685 * Note: written as a 'helper' function to hide implementation details.
686 */
687 int
688 pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
689 int protocol)
690 {
691 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
692 {
693 if ((protocol == PTHREAD_PRIO_NONE) ||
694 (protocol == PTHREAD_PRIO_INHERIT) ||
695 (protocol == PTHREAD_PRIO_PROTECT))
696 {
697 attr->protocol = protocol;
698 return (0);
699 } else
700 {
701 return (EINVAL); /* Invalid parameter */
702 }
703 } else
704 {
705 return (EINVAL); /* Not an initialized 'attribute' structure */
706 }
707 }
708 /*
709 * Set the mutex 'type' value in a mutex attribute structure.
710 * Note: written as a 'helper' function to hide implementation details.
711 */
712 int
713 pthread_mutexattr_settype(pthread_mutexattr_t *attr,
714 int type)
715 {
716 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
717 {
718 if ((type == PTHREAD_MUTEX_NORMAL) ||
719 (type == PTHREAD_MUTEX_ERRORCHECK) ||
720 (type == PTHREAD_MUTEX_RECURSIVE) ||
721 (type == PTHREAD_MUTEX_DEFAULT))
722 {
723 attr->type = type;
724 return (0);
725 } else
726 {
727 return (EINVAL); /* Invalid parameter */
728 }
729 } else
730 {
731 return (EINVAL); /* Not an initialized 'attribute' structure */
732 }
733 }
734
735
736 int mutex_try_lock(int *x) {
737 return _spin_lock_try((pthread_lock_t *)x);
738 }
739
740 void mutex_wait_lock(int *x) {
741 for (;;) {
742 if( _spin_lock_try((pthread_lock_t *)x)) {
743 return;
744 }
745 swtch_pri(0);
746 }
747 }
748
749 void
750 cthread_yield(void)
751 {
752 sched_yield();
753 }
754
755 void
756 pthread_yield_np (void)
757 {
758 sched_yield();
759 }
760
761
762 /*
763 * Temp: till pshared is fixed correctly
764 */
765 int
766 pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
767 {
768 #if __DARWIN_UNIX03
769 if (__unix_conforming == 0)
770 __unix_conforming = 1;
771 #endif /* __DARWIN_UNIX03 */
772
773 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
774 {
775 #if __DARWIN_UNIX03
776 #ifdef PR_5243343
777 if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED && PR_5243343_flag))
778 #else /* !PR_5243343 */
779 if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED))
780 #endif /* PR_5243343 */
781 #else /* __DARWIN_UNIX03 */
782 if ( pshared == PTHREAD_PROCESS_PRIVATE)
783 #endif /* __DARWIN_UNIX03 */
784 {
785 attr->pshared = pshared;
786 return (0);
787 } else
788 {
789 return (EINVAL); /* Invalid parameter */
790 }
791 } else
792 {
793 return (EINVAL); /* Not an initialized 'attribute' structure */
794 }
795 }
796
797
798 #endif /* !BUILDING_VARIANT ] */
799
800 /*
801 * Destroy a mutex attribute structure.
802 */
803 int
804 pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
805 {
806 #if __DARWIN_UNIX03
807 if (__unix_conforming == 0)
808 __unix_conforming = 1;
809 if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG)
810 return (EINVAL);
811 #endif /* __DARWIN_UNIX03 */
812
813 attr->sig = _PTHREAD_NO_SIG; /* Uninitialized */
814 return (0);
815 }
816
817