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