]> git.saurik.com Git - apple/libc.git/blob - pthreads/pthread_mutex.c
53465b5752c11a7582b52c4c419904cbc09bed2b
[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 extern int __unix_conforming;
69
70 #ifndef BUILDING_VARIANT
71 __private_extern__ int usenew_mtximpl = 1;
72 static void __pthread_mutex_set_signature(npthread_mutex_t * mutex);
73 int __mtx_markprepost(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit);
74 static int _pthread_mutex_destroy_locked(pthread_mutex_t *omutex);
75 #else /* BUILDING_VARIANT */
76 extern int usenew_mtximpl;
77 #endif /* BUILDING_VARIANT */
78
79
80 #ifdef NOTNEEDED
81 #define USE_COMPAGE 1
82 extern int _commpage_pthread_mutex_lock(uint32_t * lvalp, int flags, uint64_t mtid, uint32_t mask, uint64_t * tidp, int *sysret);
83 #endif
84
85 #include <machine/cpu_capabilities.h>
86
87 int _pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr, uint32_t static_type);
88
89
90 #if defined(__LP64__)
91 #define MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr) \
92 { \
93 if (mutex->mtxopts.options.misalign != 0) { \
94 lseqaddr = &mutex->m_seq[0]; \
95 useqaddr = &mutex->m_seq[1]; \
96 } else { \
97 lseqaddr = &mutex->m_seq[1]; \
98 useqaddr = &mutex->m_seq[2]; \
99 } \
100 }
101 #else /* __LP64__ */
102 #define MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr) \
103 { \
104 if (mutex->mtxopts.options.misalign != 0) { \
105 lseqaddr = &mutex->m_seq[1]; \
106 useqaddr = &mutex->m_seq[2]; \
107 }else { \
108 lseqaddr = &mutex->m_seq[0]; \
109 useqaddr = &mutex->m_seq[1]; \
110 } \
111 }
112 #endif /* __LP64__ */
113
114 #define _KSYN_TRACE_ 0
115
116 #if _KSYN_TRACE_
117 /* The Function qualifiers */
118 #define DBG_FUNC_START 1
119 #define DBG_FUNC_END 2
120 #define DBG_FUNC_NONE 0
121
122 int __kdebug_trace(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
123
124 #define _KSYN_TRACE_UM_LOCK 0x9000060
125 #define _KSYN_TRACE_UM_UNLOCK 0x9000064
126 #define _KSYN_TRACE_UM_MHOLD 0x9000068
127 #define _KSYN_TRACE_UM_MDROP 0x900006c
128 #define _KSYN_TRACE_UM_MUBITS 0x900007c
129 #define _KSYN_TRACE_UM_MARKPP 0x90000a8
130
131 #endif /* _KSYN_TRACE_ */
132
133 #ifndef BUILDING_VARIANT /* [ */
134
135 #define BLOCK_FAIL_PLOCKSTAT 0
136 #define BLOCK_SUCCESS_PLOCKSTAT 1
137
138 #ifdef PR_5243343
139 /* 5243343 - temporary hack to detect if we are running the conformance test */
140 extern int PR_5243343_flag;
141 #endif /* PR_5243343 */
142
143 /* This function is never called and exists to provide never-fired dtrace
144 * probes so that user d scripts don't get errors.
145 */
146 __private_extern__ void _plockstat_never_fired(void)
147 {
148 PLOCKSTAT_MUTEX_SPIN(NULL);
149 PLOCKSTAT_MUTEX_SPUN(NULL, 0, 0);
150 }
151
152
153 /*
154 * Initialize a mutex variable, possibly with additional attributes.
155 * Public interface - so don't trust the lock - initialize it first.
156 */
157 int
158 pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
159 {
160 #if 0
161 /* conformance tests depend on not having this behavior */
162 /* The test for this behavior is optional */
163 if (mutex->sig == _PTHREAD_MUTEX_SIG)
164 return EBUSY;
165 #endif
166 LOCK_INIT(mutex->lock);
167 return (_pthread_mutex_init(mutex, attr, 0x7));
168 }
169
170 /*
171 * Fetch the priority ceiling value from a mutex variable.
172 * Note: written as a 'helper' function to hide implementation details.
173 */
174 int
175 pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,
176 int *prioceiling)
177 {
178 int res;
179
180 LOCK(mutex->lock);
181 if (mutex->sig == _PTHREAD_MUTEX_SIG)
182 {
183 *prioceiling = mutex->prioceiling;
184 res = 0;
185 } else
186 res = EINVAL; /* Not an initialized 'attribute' structure */
187 UNLOCK(mutex->lock);
188 return (res);
189 }
190
191 /*
192 * Set the priority ceiling for a mutex.
193 * Note: written as a 'helper' function to hide implementation details.
194 */
195 int
196 pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
197 int prioceiling,
198 int *old_prioceiling)
199 {
200 int res;
201
202 LOCK(mutex->lock);
203 if (mutex->sig == _PTHREAD_MUTEX_SIG)
204 {
205 if ((prioceiling >= -999) ||
206 (prioceiling <= 999))
207 {
208 *old_prioceiling = mutex->prioceiling;
209 mutex->prioceiling = prioceiling;
210 res = 0;
211 } else
212 res = EINVAL; /* Invalid parameter */
213 } else
214 res = EINVAL; /* Not an initialized 'attribute' structure */
215 UNLOCK(mutex->lock);
216 return (res);
217 }
218
219 /*
220 * Get the priority ceiling value from a mutex attribute structure.
221 * Note: written as a 'helper' function to hide implementation details.
222 */
223 int
224 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr,
225 int *prioceiling)
226 {
227 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
228 {
229 *prioceiling = attr->prioceiling;
230 return (0);
231 } else
232 {
233 return (EINVAL); /* Not an initialized 'attribute' structure */
234 }
235 }
236
237 /*
238 * Get the mutex 'protocol' value from a mutex attribute structure.
239 * Note: written as a 'helper' function to hide implementation details.
240 */
241 int
242 pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,
243 int *protocol)
244 {
245 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
246 {
247 *protocol = attr->protocol;
248 return (0);
249 } else
250 {
251 return (EINVAL); /* Not an initialized 'attribute' structure */
252 }
253 }
254 /*
255 * Get the mutex 'type' value from a mutex attribute structure.
256 * Note: written as a 'helper' function to hide implementation details.
257 */
258 int
259 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr,
260 int *type)
261 {
262 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
263 {
264 *type = attr->type;
265 return (0);
266 } else
267 {
268 return (EINVAL); /* Not an initialized 'attribute' structure */
269 }
270 }
271
272 /*
273 *
274 */
275 int
276 pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared)
277 {
278 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
279 {
280 *pshared = (int)attr->pshared;
281 return (0);
282 } else
283 {
284 return (EINVAL); /* Not an initialized 'attribute' structure */
285 }
286 }
287
288 /*
289 * Initialize a mutex attribute structure to system defaults.
290 */
291 int
292 pthread_mutexattr_init(pthread_mutexattr_t *attr)
293 {
294 attr->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
295 attr->protocol = _PTHREAD_DEFAULT_PROTOCOL;
296 attr->policy = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
297 attr->type = PTHREAD_MUTEX_DEFAULT;
298 attr->sig = _PTHREAD_MUTEX_ATTR_SIG;
299 attr->pshared = _PTHREAD_DEFAULT_PSHARED;
300 return (0);
301 }
302
303 /*
304 * Set the priority ceiling value in a mutex attribute structure.
305 * Note: written as a 'helper' function to hide implementation details.
306 */
307 int
308 pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr,
309 int prioceiling)
310 {
311 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
312 {
313 if ((prioceiling >= -999) ||
314 (prioceiling <= 999))
315 {
316 attr->prioceiling = prioceiling;
317 return (0);
318 } else
319 {
320 return (EINVAL); /* Invalid parameter */
321 }
322 } else
323 {
324 return (EINVAL); /* Not an initialized 'attribute' structure */
325 }
326 }
327
328 /*
329 * Set the mutex 'protocol' value in a mutex attribute structure.
330 * Note: written as a 'helper' function to hide implementation details.
331 */
332 int
333 pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
334 int protocol)
335 {
336 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
337 {
338 if ((protocol == PTHREAD_PRIO_NONE) ||
339 (protocol == PTHREAD_PRIO_INHERIT) ||
340 (protocol == PTHREAD_PRIO_PROTECT))
341 {
342 attr->protocol = protocol;
343 return (0);
344 } else
345 {
346 return (EINVAL); /* Invalid parameter */
347 }
348 } else
349 {
350 return (EINVAL); /* Not an initialized 'attribute' structure */
351 }
352 }
353
354 int
355 pthread_mutexattr_setpolicy_np(pthread_mutexattr_t *attr,
356 int policy)
357 {
358 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
359 {
360 if (
361 (policy == _PTHREAD_MUTEX_POLICY_FAIRSHARE) ||
362 (policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT)
363 #if NOTYET
364 ||
365 (policy == _PTHREAD_MUTEX_POLICY_REALTIME) ||
366 (policy == _PTHREAD_MUTEX_POLICY_ADAPTIVE) ||
367 (policy == _PTHREAD_MUTEX_POLICY_PRIPROTECT) ||
368 (policy == _PTHREAD_MUTEX_POLICY_PRIINHERIT)
369 #endif /* NOTYET */
370 )
371 {
372 attr->policy = policy;
373 return (0);
374 } else
375 {
376 return (EINVAL); /* Invalid parameter */
377 }
378 } else
379 {
380 return (EINVAL); /* Not an initialized 'attribute' structure */
381 }
382 }
383
384 /*
385 * Set the mutex 'type' value in a mutex attribute structure.
386 * Note: written as a 'helper' function to hide implementation details.
387 */
388 int
389 pthread_mutexattr_settype(pthread_mutexattr_t *attr,
390 int type)
391 {
392 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
393 {
394 if ((type == PTHREAD_MUTEX_NORMAL) ||
395 (type == PTHREAD_MUTEX_ERRORCHECK) ||
396 (type == PTHREAD_MUTEX_RECURSIVE) ||
397 (type == PTHREAD_MUTEX_DEFAULT))
398 {
399 attr->type = type;
400 return (0);
401 } else
402 {
403 return (EINVAL); /* Invalid parameter */
404 }
405 } else
406 {
407 return (EINVAL); /* Not an initialized 'attribute' structure */
408 }
409 }
410
411
412 int mutex_try_lock(int *x) {
413 return _spin_lock_try((pthread_lock_t *)x);
414 }
415
416 void mutex_wait_lock(int *x) {
417 for (;;) {
418 if( _spin_lock_try((pthread_lock_t *)x)) {
419 return;
420 }
421 swtch_pri(0);
422 }
423 }
424
425 void
426 cthread_yield(void)
427 {
428 sched_yield();
429 }
430
431 void
432 pthread_yield_np (void)
433 {
434 sched_yield();
435 }
436
437
438 /*
439 * Temp: till pshared is fixed correctly
440 */
441 int
442 pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
443 {
444 #if __DARWIN_UNIX03
445 if (__unix_conforming == 0)
446 __unix_conforming = 1;
447 #endif /* __DARWIN_UNIX03 */
448
449 if (attr->sig == _PTHREAD_MUTEX_ATTR_SIG)
450 {
451 #if __DARWIN_UNIX03
452 if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED))
453 #else /* __DARWIN_UNIX03 */
454 if ( pshared == PTHREAD_PROCESS_PRIVATE)
455 #endif /* __DARWIN_UNIX03 */
456 {
457 attr->pshared = pshared;
458 return (0);
459 } else {
460 return (EINVAL); /* Invalid parameter */
461 }
462 } else
463 {
464 return (EINVAL); /* Not an initialized 'attribute' structure */
465 }
466 }
467
468 /*
469 * Drop the mutex unlock references(from cond wait or mutex_unlock().
470 *
471 */
472 __private_extern__ int
473 __mtx_droplock(npthread_mutex_t * mutex, uint32_t diffgen, uint32_t * flagsp, uint32_t ** pmtxp, uint32_t * mgenp, uint32_t * ugenp)
474 {
475 pthread_t self;
476 uint64_t selfid, resettid;
477 int firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
478 uint32_t lgenval, ugenval, nlval, ulval, morewaiters=0, flags;
479 volatile uint32_t * lseqaddr, *useqaddr;
480 uint64_t oldval64, newval64;
481 int numwaiters=0, clearprepost = 0;
482
483 #if _KSYN_TRACE_
484 (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_START, (uint32_t)mutex, diffgen, 0, 0, 0);
485 #endif
486 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
487
488
489 flags = mutex->mtxopts.value;
490 flags &= ~_PTHREAD_MTX_OPT_NOTIFY; /* no notification by default */
491
492
493 if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL)
494 {
495 self = pthread_self();
496 (void) pthread_threadid_np(self, &selfid);
497
498 if (mutex->m_tid != selfid)
499 {
500 //LIBC_ABORT("dropping recur or error mutex not owned by the thread\n");
501 PLOCKSTAT_MUTEX_ERROR((pthread_mutex_t *)mutex, EPERM);
502 return(EPERM);
503 } else if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE &&
504 --mutex->mtxopts.options.lock_count)
505 {
506 PLOCKSTAT_MUTEX_RELEASE((pthread_mutex_t *)mutex, 1);
507 goto out;
508 }
509 }
510
511
512 retry:
513 lgenval = *lseqaddr;
514 ugenval = *useqaddr;
515
516 numwaiters = diff_genseq((lgenval & PTHRW_COUNT_MASK),(ugenval & PTHRW_COUNT_MASK)); /* pendig waiters */
517
518 if (numwaiters == 0) {
519 /* spurious unlocks, do not touch tid */
520 oldval64 = (((uint64_t)ugenval) << 32);
521 oldval64 |= lgenval;
522 if ((firstfit != 0) && ((lgenval & PTH_RWL_PBIT) != 0)) {
523 clearprepost = 1;
524 lgenval &= ~PTH_RWL_PBIT;
525 newval64 = (((uint64_t)ugenval) << 32);
526 newval64 |= lgenval;
527 } else
528 newval64 = oldval64;
529 if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
530 goto retry;
531 /* validated L & U to be same, this is spurious unlock */
532 flags &= ~_PTHREAD_MTX_OPT_NOTIFY;
533 if (clearprepost == 1)
534 __psynch_cvclrprepost(mutex, lgenval, ugenval, 0, 0, lgenval, (flags | _PTHREAD_MTX_OPT_MUTEX));
535
536 goto out;
537 }
538
539 if (numwaiters < diffgen) {
540 #if _KSYN_TRACE_
541 (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, numwaiters, lgenval, ugenval, 0);
542 #endif
543 /* cannot drop more than existing number of waiters */
544 diffgen = numwaiters;
545 }
546
547 oldval64 = (((uint64_t)ugenval) << 32);
548 oldval64 |= lgenval;
549 ulval = ugenval + diffgen;
550 nlval = lgenval;
551
552 if ((lgenval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK)) {
553 /* do not reset Ibit, just K&E */
554 nlval &= ~(PTH_RWL_KBIT | PTH_RWL_EBIT);
555 flags &= ~_PTHREAD_MTX_OPT_NOTIFY;
556 if ((firstfit != 0) && ((lgenval & PTH_RWL_PBIT) != 0)) {
557 clearprepost = 1;
558 nlval &= ~PTH_RWL_PBIT;
559 }
560 } else {
561 /* need to signal others waiting for mutex */
562 morewaiters = 1;
563 flags |= _PTHREAD_MTX_OPT_NOTIFY;
564 }
565
566 if (((nlval & PTH_RWL_EBIT) != 0) && (firstfit != 0)) {
567 nlval &= ~PTH_RWL_EBIT; /* reset Ebit so another can acquire meanwhile */
568 }
569
570 newval64 = (((uint64_t)ulval) << 32);
571 newval64 |= nlval;
572
573 resettid = mutex->m_tid;
574
575 if ((lgenval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK))
576 mutex->m_tid = 0;
577 else if (firstfit == 0)
578 mutex->m_tid = PTHREAD_MTX_TID_SWITCHING;
579
580 if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE) {
581 mutex->m_tid = resettid;
582 goto retry;
583 }
584
585
586 #if _KSYN_TRACE_
587 (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
588 (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_NONE, (uint32_t)mutex, 2, nlval, ulval, 0);
589 #endif
590
591 if (clearprepost != 0) {
592 __psynch_cvclrprepost(mutex, nlval, ulval, 0, 0, nlval, (flags | _PTHREAD_MTX_OPT_MUTEX));
593 }
594
595 if (mgenp != NULL)
596 *mgenp = nlval;
597 if (ugenp != NULL)
598 *ugenp = ulval;
599 #if USE_COMPAGE
600 if (pmtxp != NULL)
601 *pmtxp = lseqaddr;
602 #else
603 if (pmtxp != NULL)
604 *pmtxp = (uint32_t *)mutex;
605 #endif
606
607 out:
608 if (flagsp != NULL)
609 *flagsp = flags;
610
611 #if _KSYN_TRACE_
612 (void)__kdebug_trace(_KSYN_TRACE_UM_MDROP | DBG_FUNC_END, (uint32_t)mutex, flags, 0, 0, 0);
613 #endif
614 return(0);
615 }
616
617 int
618 __mtx_updatebits(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit, int fromcond, uint64_t selfid)
619 {
620 uint32_t updateval = oupdateval;
621 #if !USE_COMPAGE
622 pthread_mutex_t * omutex = (pthread_mutex_t *)mutex;
623 #endif
624 int isebit = 0;
625 uint32_t lgenval, ugenval, nval, uval, bits;
626 volatile uint32_t * lseqaddr, *useqaddr;
627 uint64_t oldval64, newval64;
628
629 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
630
631 #if _KSYN_TRACE_
632 (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_START, (uint32_t)mutex, oupdateval, firstfit, fromcond, 0);
633 #endif
634
635 retry:
636 lgenval = *lseqaddr;
637 ugenval = *useqaddr;
638 bits = updateval & PTHRW_BIT_MASK;
639
640 #if _KSYN_TRACE_
641 (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 1, lgenval, ugenval, 0);
642 #endif
643
644
645 if ((updateval & PTH_RWL_MTX_WAIT) != 0) {
646 lgenval = (updateval & PTHRW_COUNT_MASK) | (lgenval & PTHRW_BIT_MASK);
647 if (fromcond == 0) {
648 /* if from mutex_lock(), it will handle the rewind */
649 return(1);
650 }
651 /* go block in the kernel with same lgenval as returned */
652 goto ml1;
653 } else {
654 /* firsfit might not have EBIT */
655 if (firstfit != 0) {
656 if ((lgenval & PTH_RWL_EBIT) != 0)
657 isebit = 1;
658 else
659 isebit = 0;
660 } else if ((lgenval & (PTH_RWL_KBIT|PTH_RWL_EBIT)) == (PTH_RWL_KBIT|PTH_RWL_EBIT)) {
661 /* fairshare mutex and the bits are already set, just update tid */
662 goto out;
663 }
664 }
665
666 /* either firstfist or no E bit set */
667 /* update the bits */
668 oldval64 = (((uint64_t)ugenval) << 32);
669 oldval64 |= lgenval;
670 uval = ugenval;
671 nval = lgenval | (PTH_RWL_KBIT|PTH_RWL_EBIT);
672 newval64 = (((uint64_t)uval) << 32);
673 newval64 |= nval;
674
675 /* set s and b bit */
676 if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
677 #if _KSYN_TRACE_
678 (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 2, nval, uval, 0);
679 #endif
680 if ((firstfit != 0) && (isebit != 0))
681 goto handleffit;
682
683 goto out;
684 } else {
685 if (firstfit == 0)
686 goto retry;
687 else
688 goto handleffit;
689 }
690
691 #if _KSYN_TRACE_
692 (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_NONE, (uint32_t)mutex, 4, nval, uval, 0);
693 #endif
694
695 out:
696 /* succesful bits updation */
697 mutex->m_tid = selfid;
698 #if _KSYN_TRACE_
699 (void)__kdebug_trace(_KSYN_TRACE_UM_MUBITS | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
700 #endif
701 return(0);
702
703 handleffit:
704 /* firstfit failure */
705 lgenval = *lseqaddr;
706 ugenval = *useqaddr;
707 if ((lgenval & PTH_RWL_EBIT) == 0)
708 goto retry;
709
710 if (fromcond == 0)
711 return(1);
712 else {
713 /* called from condition variable code block again */
714 ml1:
715 #if USE_COMPAGE /* [ */
716 updateval = __psynch_mutexwait((pthread_mutex_t *)lseqaddr, lgenval | PTH_RWL_RETRYBIT, ugenval, mutex->m_tid,
717 mutex->mtxopts.value);
718 #else /* USECOMPAGE ][ */
719 updateval = __psynch_mutexwait(omutex, lgenval | PTH_RWL_RETRYBIT, ugenval, mutex->m_tid,
720 mutex->mtxopts.value);
721 #endif /* USE_COMPAGE ] */
722 if (updateval == (uint32_t)-1) {
723 goto ml1;
724 }
725
726 /* now update the bits */
727 goto retry;
728 }
729 /* cannot reach */
730 goto retry;
731 }
732
733
734 int
735 __mtx_markprepost(npthread_mutex_t *mutex, uint32_t oupdateval, int firstfit)
736 {
737 uint32_t updateval = oupdateval;
738 int clearprepost = 0;
739 uint32_t lgenval, ugenval,flags;
740 volatile uint32_t * lseqaddr, *useqaddr;
741 uint64_t oldval64, newval64;
742
743 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
744
745 #if _KSYN_TRACE_
746 (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_START, (uint32_t)mutex, oupdateval, firstfit, 0, 0);
747 #endif
748
749 retry:
750
751
752
753 if ((firstfit != 0) && ((updateval & PTH_RWL_PBIT) != 0)) {
754 flags = mutex->mtxopts.value;
755
756 lgenval = *lseqaddr;
757 ugenval = *useqaddr;
758
759 #if _KSYN_TRACE_
760 (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_NONE, (uint32_t)mutex, 1, lgenval, ugenval, 0);
761 #endif
762 /* update the bits */
763 oldval64 = (((uint64_t)ugenval) << 32);
764 oldval64 |= lgenval;
765
766 if ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK)) {
767 clearprepost = 1;
768 lgenval &= ~PTH_RWL_PBIT;
769
770 } else {
771 lgenval |= PTH_RWL_PBIT;
772 }
773 newval64 = (((uint64_t)ugenval) << 32);
774 newval64 |= lgenval;
775
776 if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
777 #if _KSYN_TRACE_
778 (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
779 #endif
780
781 if (clearprepost != 0)
782 __psynch_cvclrprepost(mutex, lgenval, ugenval, 0, 0, lgenval, (flags | _PTHREAD_MTX_OPT_MUTEX));
783
784 } else {
785 goto retry;
786 }
787
788 #if _KSYN_TRACE_
789 (void)__kdebug_trace(_KSYN_TRACE_UM_MARKPP | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
790 #endif
791 }
792 return(0);
793 }
794
795 /*
796 * For the new style mutex, interlocks are not held all the time.
797 * We needed the signature to be set in the end. And we need
798 * to protect against the code getting reorganized by compiler.
799 */
800 static void
801 __pthread_mutex_set_signature(npthread_mutex_t * mutex)
802 {
803 mutex->sig = _PTHREAD_MUTEX_SIG;
804 }
805
806 int
807 pthread_mutex_lock(pthread_mutex_t *omutex)
808 {
809 pthread_t self;
810 uint64_t selfid;
811 npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
812 int sig = mutex->sig;
813 #if NEVERINCOMPAGE || !USE_COMPAGE
814 //uint32_t oldval, newval;
815 #endif
816 int retval;
817 int gotlock = 0, firstfit = 0;
818 uint32_t updateval, lgenval, ugenval, nval, uval;
819 volatile uint32_t * lseqaddr, *useqaddr;
820 uint64_t oldval64, newval64;
821 #if USE_COMPAGE
822 int sysret = 0;
823 uint32_t mask;
824 #else
825 int retrybit = 0;
826 #endif
827
828 /* To provide backwards compat for apps using mutex incorrectly */
829 if ((sig != _PTHREAD_MUTEX_SIG) && ((sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP)) {
830 PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
831 return(EINVAL);
832 }
833 if (mutex->sig != _PTHREAD_MUTEX_SIG) {
834 LOCK(mutex->lock);
835 if ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) == _PTHREAD_MUTEX_SIG_CMP) {
836 /* static initializer, init the mutex */
837 if(retval = _pthread_mutex_init(omutex, NULL, (mutex->sig & 0xf)) != 0){
838 UNLOCK(mutex->lock);
839 PLOCKSTAT_MUTEX_ERROR(omutex, retval);
840 return(retval);
841 }
842 } else if (mutex->sig != _PTHREAD_MUTEX_SIG) {
843 UNLOCK(mutex->lock);
844 PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
845 return(EINVAL);
846 }
847 UNLOCK(mutex->lock);
848 }
849
850 #if _KSYN_TRACE_
851 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_START, (uint32_t)mutex, 0, 0, 0, 0);
852 #endif
853 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
854
855 self = pthread_self();
856 (void) pthread_threadid_np(self, &selfid);
857
858 if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL) {
859 if (mutex->m_tid == selfid) {
860 if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
861 {
862 if (mutex->mtxopts.options.lock_count < USHRT_MAX)
863 {
864 mutex->mtxopts.options.lock_count++;
865 PLOCKSTAT_MUTEX_ACQUIRE(omutex, 1, 0);
866 retval = 0;
867 } else {
868 retval = EAGAIN;
869 PLOCKSTAT_MUTEX_ERROR(omutex, retval);
870 }
871 } else { /* PTHREAD_MUTEX_ERRORCHECK */
872 retval = EDEADLK;
873 PLOCKSTAT_MUTEX_ERROR(omutex, retval);
874 }
875 return (retval);
876 }
877 }
878
879 #if _KSYN_TRACE_
880 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 1, 0, 0, 0);
881 #endif
882
883 #if USE_COMPAGE /* [ */
884
885 ml0:
886 mask = PTH_RWL_EBIT;
887 retval = _commpage_pthread_mutex_lock(lseqaddr, mutex->mtxopts.value, selfid, mask, &mutex->m_tid, &sysret);
888 if (retval == 0) {
889 gotlock = 1;
890 } else if (retval == 1) {
891 gotlock = 1;
892 updateval = sysret;
893 /* returns 0 on succesful update */
894 if (__mtx_updatebits( mutex, updateval, firstfit, 0, selfid) == 1) {
895 /* could not acquire, may be locked in ffit case */
896 #if USE_COMPAGE
897 LIBC_ABORT("comapge implementatin looping in libc \n");
898 #endif
899 goto ml0;
900 }
901 }
902 #if NEVERINCOMPAGE
903 else if (retval == 3) {
904 cthread_set_errno_self(sysret);
905 oldval = *lseqaddr;
906 uval = *useqaddr;
907 newval = oldval + PTHRW_INC;
908 gotlock = 0;
909 /* to block in the kerenl again */
910 }
911 #endif
912 else {
913 LIBC_ABORT("comapge implementation bombed \n");
914 }
915
916
917 #else /* USECOMPAGE ][ */
918 retry:
919 lgenval = *lseqaddr;
920 ugenval = *useqaddr;
921
922 #if _KSYN_TRACE_
923 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
924 #endif /* _KSYN_TRACE_ */
925
926 if((lgenval & PTH_RWL_EBIT) == 0) {
927 gotlock = 1;
928 } else {
929 gotlock = 0;
930 }
931
932 oldval64 = (((uint64_t)ugenval) << 32);
933 oldval64 |= lgenval;
934 uval = ugenval;
935 nval = (lgenval + PTHRW_INC) | (PTH_RWL_EBIT|PTH_RWL_KBIT);
936 newval64 = (((uint64_t)uval) << 32);
937 newval64 |= nval;
938
939 if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
940 #if _KSYN_TRACE_
941 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, nval, uval, 0);
942 #endif
943 if (gotlock != 0) {
944 mutex->m_tid = selfid;
945 goto out;
946 }
947 } else
948 goto retry;
949
950
951 retrybit = 0;
952 if (gotlock == 0) {
953 #if _KSYN_TRACE_
954 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 3, nval, uval, 0);
955 #endif
956 firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
957 ml1:
958 updateval = __psynch_mutexwait(omutex, nval | retrybit, uval, mutex->m_tid,
959 mutex->mtxopts.value);
960
961 #if _KSYN_TRACE_
962 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 4, updateval, 0, 0);
963 #endif
964 if (updateval == (uint32_t)-1) {
965 goto ml1;
966 }
967
968 /* returns 0 on succesful update; in firstfit it may fail with 1 */
969 if (__mtx_updatebits( mutex, PTHRW_INC | (PTH_RWL_KBIT | PTH_RWL_EBIT), firstfit, 0, selfid) == 1) {
970 /* could not acquire, may be locked in ffit case */
971 retrybit = PTH_RWL_RETRYBIT;
972 #if USE_COMPAGE
973 LIBC_ABORT("comapge implementatin looping in libc \n");
974
975 #endif
976 goto ml1;
977 }
978 }
979 #endif /* USE_COMPAGE ] */
980
981 out:
982 if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
983 mutex->mtxopts.options.lock_count = 1;
984
985 #if _KSYN_TRACE_
986 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
987 #endif
988 return (0);
989 }
990
991 /*
992 * Attempt to lock a mutex, but don't block if this isn't possible.
993 */
994 int
995 pthread_mutex_trylock(pthread_mutex_t *omutex)
996 {
997 npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
998 int sig = mutex->sig;
999 int error = 0;
1000 pthread_t self;
1001 uint64_t selfid;
1002 int gotlock = 0;
1003 uint32_t lgenval, ugenval, nval, uval;
1004 volatile uint32_t * lseqaddr, *useqaddr;
1005 uint64_t oldval64, newval64;
1006
1007 /* To provide backwards compat for apps using mutex incorrectly */
1008 if ((sig != _PTHREAD_MUTEX_SIG) && ((sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP)) {
1009 PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
1010 return(EINVAL);
1011 }
1012
1013 if ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) == _PTHREAD_MUTEX_SIG_CMP) {
1014 LOCK(mutex->lock);
1015 if (mutex->sig == _PTHREAD_MUTEX_SIG_init) {
1016 /* static initializer, init the mutex */
1017 if((error = _pthread_mutex_init(omutex, NULL, (mutex->sig & 0xf))) != 0){
1018 UNLOCK(mutex->lock);
1019 PLOCKSTAT_MUTEX_ERROR(omutex, error);
1020 return(error);
1021 }
1022 } else if (mutex->sig != _PTHREAD_MUTEX_SIG) {
1023 UNLOCK(mutex->lock);
1024 PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
1025 return(EINVAL);
1026 }
1027 UNLOCK(mutex->lock);
1028 }
1029
1030 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
1031
1032 self = pthread_self();
1033 (void) pthread_threadid_np(self, &selfid);
1034
1035 if (mutex->mtxopts.options.type != PTHREAD_MUTEX_NORMAL) {
1036 if (mutex->m_tid == selfid) {
1037 if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
1038 {
1039 if (mutex->mtxopts.options.lock_count < USHRT_MAX)
1040 {
1041 mutex->mtxopts.options.lock_count++;
1042 PLOCKSTAT_MUTEX_ACQUIRE(omutex, 1, 0);
1043 error = 0;
1044 } else {
1045 error = EAGAIN;
1046 PLOCKSTAT_MUTEX_ERROR(omutex, error);
1047 }
1048 } else { /* PTHREAD_MUTEX_ERRORCHECK */
1049 error = EDEADLK;
1050 PLOCKSTAT_MUTEX_ERROR(omutex, error);
1051 }
1052 return (error);
1053 }
1054 }
1055 retry:
1056 lgenval = *lseqaddr;
1057 ugenval = *useqaddr;
1058
1059 #if _KSYN_TRACE_
1060 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, lgenval, ugenval, 0);
1061 #endif /* _KSYN_TRACE_ */
1062
1063
1064 oldval64 = (((uint64_t)ugenval) << 32);
1065 oldval64 |= lgenval;
1066 uval = ugenval;
1067
1068 /* if we can acquire go ahead otherwise ensure it is still busy */
1069 if((lgenval & PTH_RWL_EBIT) == 0) {
1070 gotlock = 1;
1071 nval = (lgenval + PTHRW_INC) | (PTH_RWL_EBIT|PTH_RWL_KBIT);
1072 } else {
1073 nval = (lgenval | PTH_RWL_TRYLKBIT);
1074 gotlock = 0;
1075 }
1076
1077 newval64 = (((uint64_t)uval) << 32);
1078 newval64 |= nval;
1079
1080 /* set s and b bit */
1081 if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) == TRUE) {
1082 #if _KSYN_TRACE_
1083 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_NONE, (uint32_t)mutex, 2, nval, uval, 0);
1084 #endif
1085 if (gotlock != 0) {
1086 mutex->m_tid = selfid;
1087 if (mutex->mtxopts.options.type == PTHREAD_MUTEX_RECURSIVE)
1088 mutex->mtxopts.options.lock_count = 1;
1089 PLOCKSTAT_MUTEX_ACQUIRE(omutex, 1, 0);
1090 } else {
1091 error = EBUSY;
1092 PLOCKSTAT_MUTEX_ERROR(omutex, error);
1093 }
1094 } else
1095 goto retry;
1096
1097
1098 #if _KSYN_TRACE_
1099 (void)__kdebug_trace(_KSYN_TRACE_UM_LOCK | DBG_FUNC_END, (uint32_t)mutex, 0xfafafafa, 0, error, 0);
1100 #endif
1101 return (error);
1102 }
1103
1104 /*
1105 * Unlock a mutex.
1106 * TODO: Priority inheritance stuff
1107 */
1108 int
1109 pthread_mutex_unlock(pthread_mutex_t *omutex)
1110 {
1111 npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
1112 int retval;
1113 uint32_t mtxgen, mtxugen, flags, notify, updateval;
1114 int sig = mutex->sig;
1115 pthread_t self;
1116 uint64_t selfid;
1117 volatile uint32_t * lseqaddr, *useqaddr;
1118 int firstfit = 0;
1119
1120 /* To provide backwards compat for apps using mutex incorrectly */
1121
1122 #if _KSYN_TRACE_
1123 (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_START, (uint32_t)mutex, 0, 0, 0, 0);
1124 #endif
1125 if ((sig != _PTHREAD_MUTEX_SIG) && ((sig & _PTHREAD_MUTEX_SIG_init_MASK) != _PTHREAD_MUTEX_SIG_CMP)) {
1126 PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
1127 return(EINVAL);
1128 }
1129
1130 if (mutex->sig != _PTHREAD_MUTEX_SIG) {
1131 LOCK(mutex->lock);
1132 if ((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK) == _PTHREAD_MUTEX_SIG_CMP) {
1133 /* static initializer, init the mutex */
1134 if((retval = _pthread_mutex_init(omutex, NULL, (mutex->sig & 0xf))) != 0){
1135 UNLOCK(mutex->lock);
1136 PLOCKSTAT_MUTEX_ERROR(omutex, retval);
1137 return(retval);
1138 }
1139 } else if (mutex->sig != _PTHREAD_MUTEX_SIG) {
1140 UNLOCK(mutex->lock);
1141 PLOCKSTAT_MUTEX_ERROR(omutex, EINVAL);
1142 return(EINVAL);
1143 }
1144 UNLOCK(mutex->lock);
1145 }
1146
1147 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
1148
1149 notify = 0;
1150 retval = __mtx_droplock(mutex, PTHRW_INC, &flags, NULL, &mtxgen, &mtxugen);
1151 if (retval != 0)
1152 return(retval);
1153
1154 if ((flags & _PTHREAD_MTX_OPT_NOTIFY) != 0) {
1155 firstfit = (mutex->mtxopts.options.policy == _PTHREAD_MUTEX_POLICY_FIRSTFIT);
1156
1157 self = pthread_self();
1158 (void) pthread_threadid_np(self, &selfid);
1159
1160 #if _KSYN_TRACE_
1161 (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_NONE, (uint32_t)mutex, 1, mtxgen, mtxugen, 0);
1162 #endif
1163 #if USE_COMPAGE /* [ */
1164 if ((updateval = __psynch_mutexdrop((pthread_mutex_t *)lseqaddr, mtxgen, mtxugen, mutex->m_tid, flags)) == (uint32_t)-1)
1165 #else /* USECOMPAGE ][ */
1166 if ((updateval = __psynch_mutexdrop(omutex, mtxgen, mtxugen, mutex->m_tid, flags))== (uint32_t)-1)
1167 #endif /* USE_COMPAGE ] */
1168 {
1169 retval = errno;
1170 #if _KSYN_TRACE_
1171 (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_END, (uint32_t)mutex, retval, 0, 0, 0);
1172 #endif
1173 if (retval == 0)
1174 return(0);
1175 else if (errno == EINTR)
1176 return(0);
1177 else {
1178 LIBC_ABORT("__p_mutexdrop failed with error %d\n", retval);
1179 return(retval);
1180 }
1181 } else if (firstfit == 1) {
1182 if ((updateval & PTH_RWL_PBIT) != 0) {
1183 __mtx_markprepost(mutex, updateval, firstfit);
1184 }
1185 }
1186 }
1187 #if _KSYN_TRACE_
1188 (void)__kdebug_trace(_KSYN_TRACE_UM_UNLOCK | DBG_FUNC_END, (uint32_t)mutex, 0, 0, 0, 0);
1189 #endif
1190 return(0);
1191 }
1192
1193
1194 /*
1195 * Initialize a mutex variable, possibly with additional attributes.
1196 */
1197 int
1198 _pthread_mutex_init(pthread_mutex_t *omutex, const pthread_mutexattr_t *attr, uint32_t static_type)
1199 {
1200 npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
1201
1202 if (attr)
1203 {
1204 if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG)
1205 return (EINVAL);
1206 mutex->prioceiling = attr->prioceiling;
1207 mutex->mtxopts.options.protocol = attr->protocol;
1208 mutex->mtxopts.options.policy = attr->policy;
1209 mutex->mtxopts.options.type = attr->type;
1210 mutex->mtxopts.options.pshared = attr->pshared;
1211 } else {
1212 switch(static_type) {
1213 case 1:
1214 mutex->mtxopts.options.type = PTHREAD_MUTEX_ERRORCHECK;
1215 break;
1216 case 2:
1217 mutex->mtxopts.options.type = PTHREAD_MUTEX_RECURSIVE;
1218 break;
1219 case 3:
1220 /* firstfit fall thru */
1221 case 7:
1222 mutex->mtxopts.options.type = PTHREAD_MUTEX_DEFAULT;
1223 break;
1224 default:
1225 return(EINVAL);
1226 }
1227
1228 mutex->prioceiling = _PTHREAD_DEFAULT_PRIOCEILING;
1229 mutex->mtxopts.options.protocol = _PTHREAD_DEFAULT_PROTOCOL;
1230 if (static_type != 3)
1231 mutex->mtxopts.options.policy = _PTHREAD_MUTEX_POLICY_FAIRSHARE;
1232 else
1233 mutex->mtxopts.options.policy = _PTHREAD_MUTEX_POLICY_FIRSTFIT;
1234 mutex->mtxopts.options.pshared = _PTHREAD_DEFAULT_PSHARED;
1235 }
1236
1237 mutex->mtxopts.options.notify = 0;
1238 mutex->mtxopts.options.rfu = 0;
1239 mutex->mtxopts.options.hold = 0;
1240 mutex->mtxopts.options.mutex = 1;
1241 mutex->mtxopts.options.lock_count = 0;
1242 /* address 8byte aligned? */
1243 if (((uintptr_t)mutex & 0x07) != 0) {
1244 /* 4byte alinged */
1245 mutex->mtxopts.options.misalign = 1;
1246 #if defined(__LP64__)
1247 mutex->m_lseqaddr = &mutex->m_seq[0];
1248 mutex->m_useqaddr = &mutex->m_seq[1];
1249 #else /* __LP64__ */
1250 mutex->m_lseqaddr = &mutex->m_seq[1];
1251 mutex->m_useqaddr = &mutex->m_seq[2];
1252 #endif /* __LP64__ */
1253 } else {
1254 /* 8byte alinged */
1255 mutex->mtxopts.options.misalign = 0;
1256 #if defined(__LP64__)
1257 mutex->m_lseqaddr = &mutex->m_seq[1];
1258 mutex->m_useqaddr = &mutex->m_seq[2];
1259 #else /* __LP64__ */
1260 mutex->m_lseqaddr = &mutex->m_seq[0];
1261 mutex->m_useqaddr = &mutex->m_seq[1];
1262 #endif /* __LP64__ */
1263 }
1264 mutex->m_tid = 0;
1265 mutex->m_seq[0] = 0;
1266 mutex->m_seq[1] = 0;
1267 mutex->m_seq[2] = 0;
1268 mutex->prioceiling = 0;
1269 mutex->priority = 0;
1270 /*
1271 * For the new style mutex, interlocks are not held all the time.
1272 * We needed the signature to be set in the end. And we need
1273 * to protect against the code getting reorganized by compiler.
1274 * mutex->sig = _PTHREAD_MUTEX_SIG;
1275 */
1276 __pthread_mutex_set_signature(mutex);
1277 return (0);
1278 }
1279
1280
1281 /*
1282 * Destroy a mutex variable.
1283 */
1284 int
1285 pthread_mutex_destroy(pthread_mutex_t *omutex)
1286 {
1287 int res;
1288 npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
1289
1290 LOCK(mutex->lock);
1291 res = _pthread_mutex_destroy_locked(omutex);
1292 UNLOCK(mutex->lock);
1293
1294 return(res);
1295 }
1296
1297
1298 static int
1299 _pthread_mutex_destroy_locked(pthread_mutex_t *omutex)
1300 {
1301 int res;
1302 npthread_mutex_t * mutex = (npthread_mutex_t *)omutex;
1303 uint32_t lgenval, ugenval;
1304 volatile uint32_t * lseqaddr, *useqaddr;
1305
1306
1307 if (mutex->sig == _PTHREAD_MUTEX_SIG)
1308 {
1309 MUTEX_GETSEQ_ADDR(mutex, lseqaddr, useqaddr);
1310
1311 lgenval = *(lseqaddr);
1312 ugenval = *(useqaddr);
1313 if ((mutex->m_tid == (uint64_t)0) &&
1314 ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK)))
1315 {
1316 mutex->sig = _PTHREAD_NO_SIG;
1317 res = 0;
1318 }
1319 else
1320 res = EBUSY;
1321 } else if((mutex->sig & _PTHREAD_MUTEX_SIG_init_MASK )== _PTHREAD_MUTEX_SIG_CMP) {
1322 mutex->sig = _PTHREAD_NO_SIG;
1323 res = 0;
1324 } else
1325 res = EINVAL;
1326
1327 return (res);
1328 }
1329
1330
1331 #endif /* !BUILDING_VARIANT ] */
1332
1333 /*
1334 * Destroy a mutex attribute structure.
1335 */
1336 int
1337 pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
1338 {
1339 #if __DARWIN_UNIX03
1340 if (__unix_conforming == 0)
1341 __unix_conforming = 1;
1342 if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG)
1343 return (EINVAL);
1344 #endif /* __DARWIN_UNIX03 */
1345
1346 attr->sig = _PTHREAD_NO_SIG; /* Uninitialized */
1347 return (0);
1348 }
1349
1350