Loading...
--- Libc/Libc-583/pthreads/pthread_rwlock.c
+++ Libc/Libc-498/pthreads/pthread_rwlock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2003, 2007 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@@ -56,20 +56,9 @@
*/
#include "pthread_internals.h"
-#include <stdio.h> /* For printf(). */
-
extern int __unix_conforming;
-#ifdef PLOCKSTAT
#include "plockstat.h"
-#else /* !PLOCKSTAT */
-#define PLOCKSTAT_RW_ERROR(x, y, z)
-#define PLOCKSTAT_RW_BLOCK(x, y)
-#define PLOCKSTAT_RW_BLOCKED(x, y, z)
-#define PLOCKSTAT_RW_ACQUIRE(x, y)
-#define PLOCKSTAT_RW_RELEASE(x, y)
-#endif /* PLOCKSTAT */
-
#define READ_LOCK_PLOCKSTAT 0
#define WRITE_LOCK_PLOCKSTAT 1
@@ -79,86 +68,8 @@
/* maximum number of times a read lock may be obtained */
#define MAX_READ_LOCKS (INT_MAX - 1)
-#if defined(__i386__) || defined(__x86_64__)
#ifndef BUILDING_VARIANT /* [ */
-int usenew_impl = 0;
-#else /* BUILDING_VARIANT */
-extern int usenew_impl;
-#endif /* BUILDING_VARIANT */
-
-
-#if defined(__LP64__)
-#define RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr) \
-{ \
- if (rwlock->misalign != 0) { \
- lseqaddr = &rwlock->rw_seq[1]; \
- wcaddr = &rwlock->rw_seq[2]; \
- useqaddr = &rwlock->rw_seq[3]; \
- } else { \
- lseqaddr = &rwlock->rw_seq[0]; \
- wcaddr = &rwlock->rw_seq[1]; \
- useqaddr = &rwlock->rw_seq[2]; \
- } \
-}
-#else /* __LP64__ */
-#define RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr) \
-{ \
- if (rwlock->misalign != 0) { \
- lseqaddr = &rwlock->rw_seq[0]; \
- wcaddr = &rwlock->rw_seq[1]; \
- useqaddr = &rwlock->rw_seq[2]; \
- }else { \
- lseqaddr = &rwlock->rw_seq[1]; \
- wcaddr = &rwlock->rw_seq[2]; \
- useqaddr = &rwlock->rw_seq[3]; \
- } \
-}
-#endif /* __LP64__ */
-
-int _new_pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
-int _new_pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_longrdlock_np(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_yieldwrlock_np(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_downgrade_np(pthread_rwlock_t *rwlock);
-int _new_pthread_rwlock_upgrade_np(pthread_rwlock_t *rwlock);
-
-#define _KSYN_TRACE_ 0
-
-#if _KSYN_TRACE_
-/* The Function qualifiers */
-#define DBG_FUNC_START 1
-#define DBG_FUNC_END 2
-#define DBG_FUNC_NONE 0
-
-int __kdebug_trace(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
-
-#define _KSYN_TRACE_RW_RDLOCK 0x9000080
-#define _KSYN_TRACE_RW_WRLOCK 0x9000084
-#define _KSYN_TRACE_RW_UNLOCK 0x9000088
-#define _KSYN_TRACE_RW_UNACT1 0x900808c
-#define _KSYN_TRACE_RW_UNACT2 0x9008090
-#define _KSYN_TRACE_RW_UNACTK 0x9008094
-#define _KSYN_TRACE_RW_UNACTE 0x9008098
-#endif /* _KSYN_TRACE_ */
-#endif /* __i386__ || __x86_64__ */
-
-#ifndef BUILDING_VARIANT /* [ */
-
-#if defined(__i386__) || defined(__x86_64__)
-static int rwlock_unlock_action_onread(pthread_rwlock_t * rwlock, uint32_t updateval);
-static int rwlock_unlock_action1(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t updateval);
-static int rwlock_unlock_action2(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t updateval);
-static uint32_t modbits(uint32_t lgenval, uint32_t updateval);
-static int rwlock_unlock_action_k(pthread_rwlock_t * rwlock, uint32_t lgenval, uint32_t updateval);
-static int rwlock_exclusive_lockreturn(pthread_rwlock_t * rwlock, uint32_t updateval);
-static int rw_diffgenseq(uint32_t x, uint32_t y);
-#endif /* __i386__ || __x86_64__ */
int
@@ -191,6 +102,11 @@
}
}
+/* Temp: untill pshared is fixed right */
+#ifdef PR_5243343
+/* 5243343 - temporary hack to detect if we are running the conformance test */
+extern int PR_5243343_flag;
+#endif /* PR_5243343 */
int
pthread_rwlockattr_setpshared(pthread_rwlockattr_t * attr, int pshared)
@@ -198,7 +114,11 @@
if (attr->sig == _PTHREAD_RWLOCK_ATTR_SIG)
{
#if __DARWIN_UNIX03
+#ifdef PR_5243343
+ if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED && PR_5243343_flag))
+#else /* !PR_5243343 */
if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED))
+#endif /* PR_5243343 */
#else /* __DARWIN_UNIX03 */
if ( pshared == PTHREAD_PROCESS_PRIVATE)
#endif /* __DARWIN_UNIX03 */
@@ -216,1968 +136,16 @@
}
-#if defined(__i386__) || defined(__x86_64__) /* [ */
-int
-_new_pthread_rwlock_destroy(pthread_rwlock_t *orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-#if __DARWIN_UNIX03
- uint32_t rw_lseqcnt, rw_useqcnt;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-#endif /* __DARWIN_UNIX03 */
-
+#endif /* !BUILDING_VARIANT ] */
+
+int
+pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
+{
+ int ret;
+
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
return(EINVAL);
} else {
-#if __DARWIN_UNIX03
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- rw_lseqcnt = *lseqaddr;
- rw_useqcnt = *useqaddr;
-
- if((rw_lseqcnt & PTHRW_COUNT_MASK) != rw_useqcnt)
- return(EBUSY);
-
-#endif /* __DARWIN_UNIX03 */
- //bzero(rwlock, sizeof(npthread_rwlock_t));
- rwlock->sig = _PTHREAD_NO_SIG;
- return(0);
- }
-}
-
-
-int
-_new_pthread_rwlock_init(pthread_rwlock_t * orwlock, const pthread_rwlockattr_t *attr)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-#if __DARWIN_UNIX03
- uint32_t rw_lseqcnt, rw_useqcnt;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-#endif /* __DARWIN_UNIX03 */
-
-#if __DARWIN_UNIX03
- if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) {
- return(EINVAL);
- }
-
- /* if already inited check whether it is in use, then return EBUSY */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG) {
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
- rw_lseqcnt = *lseqaddr;
- rw_useqcnt = *useqaddr;
-
- if ((rw_lseqcnt & PTHRW_COUNT_MASK) != rw_useqcnt)
- return(EBUSY);
-
- }
-#endif /* __DARWIN_UNIX03 */
-
- /* initialize the lock */
- bzero(rwlock, sizeof(pthread_rwlock_t));
-
- if ((attr != NULL) && (attr->pshared == PTHREAD_PROCESS_SHARED)) {
- rwlock->pshared = PTHREAD_PROCESS_SHARED;
- rwlock->rw_flags = PTHRW_KERN_PROCESS_SHARED;
-
- } else {
- rwlock->pshared = _PTHREAD_DEFAULT_PSHARED;
- rwlock->rw_flags = PTHRW_KERN_PROCESS_PRIVATE;
- }
-
- if (((uintptr_t)rwlock & 0x07) != 0) {
- rwlock->misalign = 1;
-#if defined(__LP64__)
- rwlock->rw_lseqaddr = &rwlock->rw_seq[1];
- rwlock->rw_wcaddr = &rwlock->rw_seq[2];
- rwlock->rw_useqaddr = &rwlock->rw_seq[3];
- rwlock->rw_seq[1]= PTHRW_RW_INIT;
-#else /* __LP64__ */
- rwlock->rw_lseqaddr = &rwlock->rw_seq[0];
- rwlock->rw_wcaddr = &rwlock->rw_seq[1];
- rwlock->rw_useqaddr = &rwlock->rw_seq[2];
- rwlock->rw_seq[0]= PTHRW_RW_INIT;
-#endif /* __LP64__ */
-
- } else {
- rwlock->misalign = 0;
-#if defined(__LP64__)
- rwlock->rw_lseqaddr = &rwlock->rw_seq[0];
- rwlock->rw_wcaddr = &rwlock->rw_seq[1];
- rwlock->rw_useqaddr = &rwlock->rw_seq[2];
- rwlock->rw_seq[0]= PTHRW_RW_INIT;
-#else /* __LP64__ */
- rwlock->rw_lseqaddr = &rwlock->rw_seq[1];
- rwlock->rw_wcaddr = &rwlock->rw_seq[2];
- rwlock->rw_useqaddr = &rwlock->rw_seq[3];
- rwlock->rw_seq[1]= PTHRW_RW_INIT;
-#endif /* __LP64__ */
-
- }
- rwlock->sig = _PTHREAD_RWLOCK_SIG;
-
- return(0);
-}
-
-int
-_new_pthread_rwlock_rdlock(pthread_rwlock_t * orwlock)
-{
-#if __DARWIN_UNIX03
- pthread_t self;
-#endif /* __DARWIN_UNIX03 */
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval, ugenval, rw_wc, newval, updateval;
- int error = 0, ret;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_START, (uint32_t)rwlock, lgenval, newval, rw_wc, 0);
-#endif
-
- if (is_rw_lbit_set(lgenval))
- goto gotlock;
- if(is_rw_ewubit_clear(lgenval))
- goto gotlock;
-
-#if __DARWIN_UNIX03
- if (is_rw_ebit_set(lgenval)) {
- self = pthread_self();
- if(rwlock->rw_owner == self) {
- error = EDEADLK;
- goto out;
- }
- }
-#endif /* __DARWIN_UNIX03 */
-
- /* mean Lbit is set and R bit not set; block in kernel */
- newval = (lgenval + PTHRW_INC);
-
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- goto loop;
-
- /* give writers priority over readers */
- PLOCKSTAT_RW_BLOCK(orwlock, READ_LOCK_PLOCKSTAT);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lgenval, newval, rw_wc+1, 0);
-#endif
-
-retry:
- updateval = __psynch_rw_rdlock(orwlock, (newval & ~PTHRW_RW_INIT), ugenval, rw_wc, rwlock->rw_flags);
-
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR)
- goto retry;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
-
-
-
- if (error == 0) {
- if ((updateval & PTHRW_RW_HUNLOCK) != 0) {
- ret = rwlock_unlock_action_onread(orwlock, (updateval & ~PTHRW_RW_HUNLOCK));
- if (ret != 0) {
- LIBC_ABORT("rdlock_unlock handling failed");
- }
- }
- PLOCKSTAT_RW_BLOCKED(orwlock, READ_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
- return(0);
- } else {
- PLOCKSTAT_RW_BLOCKED(orwlock, READ_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
- goto out;
- }
- /* Not reached */
-
-gotlock:
- /* check for max readers */
- ugenval = *useqaddr;
- if (rw_diffgenseq(lgenval, ugenval) >= PTHRW_MAX_READERS) {
- error = EAGAIN;
- goto out;
- }
-
- newval = (lgenval + PTHRW_INC);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lgenval, newval, 0);
-#endif
-
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, 0, 0, 0);
-#endif
- return(0);
- } else
- goto loop;
-out:
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(error);
-}
-
-
-int
-_new_pthread_rwlock_tryrdlock(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, newval, ugenval;
- int error = 0;
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-loop:
- lgenval = *lseqaddr;
- if (is_rw_lbit_set(lgenval))
- goto gotlock;
- if (is_rw_ewubit_clear(lgenval))
- goto gotlock;
-
-
- error = EBUSY;
- goto out;
-
-gotlock:
- ugenval = *useqaddr;
- if (rw_diffgenseq(lgenval, ugenval) >= PTHRW_MAX_READERS) {
- error = EAGAIN;
- goto out;
- }
-
- newval = (lgenval + PTHRW_INC);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
- return(0);
- } else
- goto loop;
-out:
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
-}
-
-#ifdef NOTYET
-/*****************************************************************************/
-/* TBD need to add towards MAX_READERS */
-int
-_new_pthread_rwlock_longrdlock_np(pthread_rwlock_t * orwlock)
-{
- pthread_t self;
- uint32_t lgenval, ugenval, rw_wc, newval, updateval;
- int error = 0, ret;
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-loop:
-
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
- if (is_rw_ewuybit_clear(lgenval))
- goto gotlock;
-
- /* if w bit is set ensure there is no deadlock */
- if (is_rw_ebit_set(lgenval)) {
- self = pthread_self();
- if(rwlock->rw_owner == self) {
- error = EDEADLK;
- goto out;
- }
- }
-
- newval = (lgenval + PTHRW_INC);
- /* update lock seq and block in kernel */
-
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- goto loop;
-kblock:
- updateval = __psynch_rw_longrdlock(orwlock, newval, ugenval, (rw_wc+1), rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR)
- goto kblock;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- if (error == 0) {
-
- if ((updateval & PTHRW_RW_HUNLOCK) != 0) {
- ret = rwlock_unlock_action_onread(orwlock, (updateval & ~PTHRW_RW_HUNLOCK));
- if (ret != 0) {
- LIBC_ABORT("rdlock_unlock handling failed");
- }
- }
-
- error = FALSE;
- while (error == FALSE) {
- lgenval = *lseqaddr;
- newval = lgenval | PTHRW_LBIT;
- error = OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr);
- }
-
- goto successout;
- } else
- goto out;
- goto successout;
-
-gotlock:
- newval = ((lgenval + PTHRW_INC)| PTHRW_LBIT);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- goto loop;
-
-successout:
- PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
- return(0);
-out:
- PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
- return(error);
-}
-/**************************************************************/
-#endif /* NOTYET */
-
-int
-_new_pthread_rwlock_trywrlock(pthread_rwlock_t * orwlock)
-{
- int error = 0;
- uint32_t lgenval, newval;
-#if __DARWIN_UNIX03
- pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = PTHRW_RW_INIT;
- newval = PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
-#if __DARWIN_UNIX03
- rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- }
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EBUSY);
- return(EBUSY);
-}
-
-int
-_new_pthread_rwlock_wrlock(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, newval, ugenval, updateval, rw_wc;
- int error = 0;
-#if __DARWIN_UNIX03
- pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lgenval, ugenval, rw_wc, 0);
-#endif
-#if __DARWIN_UNIX03
- if (is_rw_ebit_set(lgenval)) {
- if(rwlock->rw_owner == self) {
- error = EDEADLK;
- goto out;
- }
- }
-#endif /* __DARWIN_UNIX03 */
-
- if (lgenval == PTHRW_RW_INIT) {
- newval = ( PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- goto gotit;
- }
- }
-
- newval = (lgenval + PTHRW_INC) | PTHRW_WBIT | PTHRW_SHADOW_W;
-
- /* update lock seq and block in kernel */
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lgenval, newval, 0);
-#endif
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- goto loop;
-
-retry:
- PLOCKSTAT_RW_BLOCK(orwlock, WRITE_LOCK_PLOCKSTAT);
-retry1:
- updateval = __psynch_rw_wrlock(orwlock, newval, ugenval, (rw_wc+1), rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR) {
- goto retry1;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x33333333, newval, updateval, 0);
-#endif
- PLOCKSTAT_RW_BLOCKED(orwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
- if (error != 0) {
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- goto out;
- }
-
- if (is_rw_ebit_clear(updateval)) {
- /* kernel cannot wakeup without granting E bit */
- abort();
- }
-
- error = rwlock_exclusive_lockreturn(orwlock, updateval);
- if (error == EAGAIN)
- goto retry;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- if (error == 0) {
-gotit:
-#if __DARWIN_UNIX03
- rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(0);
- }
-out:
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(error);
-}
-
-
-#ifdef NOTYET
-/*****************************************************************************/
-int
-_new_pthread_rwlock_yieldwrlock_np(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, newval, ugenval, updateval, rw_wc;
- int error = 0;
-#if __DARWIN_UNIX03
- pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
- return(EINVAL);
- }
- }
-
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
-#if __DARWIN_UNIX03
- if (is_rw_ebit_set(lgenval)) {
- if (rwlock->rw_owner == self) {
- error = EDEADLK;
- goto out;
- }
- }
-#endif /* __DARWIN_UNIX03 */
-
- if (lgenval == PTHRW_RW_INIT) {
- newval = PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- goto gotit;
- }
- }
-
- newval = (lgenval + PTHRW_INC);
- if ((lgenval & PTHRW_WBIT) == 0)
- newval |= PTHRW_YBIT;
-
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- PLOCKSTAT_RW_BLOCK(orwlock, WRITE_LOCK_PLOCKSTAT);
-retry:
- updateval = __psynch_rw_yieldwrlock(orwlock, newval, ugenval, (rw_wc+1), rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR)
- goto retry;
-
-
- PLOCKSTAT_RW_BLOCKED(orwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
- if (error != 0) {
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- goto out;
- }
-
- if (is_rw_ebit_clear(updateval)) {
- /* kernel cannot wakeup without granting E bit */
- abort();
- }
-
- error = rwlock_exclusive_lockreturn(orwlock, updateval);
- if (error == EAGAIN)
- goto retry;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- if (error == 0) {
- gotit:
-#if __DARWIN_UNIX03
- rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- }
- return(error);
-out:
- PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
- return(error);
-}
-/**************************************************************/
-#endif /* NOTYET */
-
-int
-_new_pthread_rwlock_unlock(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, ugenval, rw_wc, newval, nlval, ulval;
- int error = 0;
- int wrlock = 0, kern_trans;
- uint32_t updateval, bits, newbits;
- uint32_t isupgrade = 0;
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- int retry_count = 0, retry_count1 = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
- pthread_t self = NULL;
- uint64_t threadid = 0;
- int ubitchanged = 0, initbitset = 0, num;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- PLOCKSTAT_RW_ERROR(orwlock, wrlock, error);
- return(error);
- }
- } else {
- PLOCKSTAT_RW_ERROR(orwlock, wrlock, EINVAL);
- return(EINVAL);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
-
-loop1:
- if ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK)) {
- retry_count++;
- sched_yield();
- if (retry_count < 1024)
- goto loop;
- error = EINVAL;
- goto out;
- }
- retry_count = 0;
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lgenval, ugenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, rw_wc, 0, 0);
-#endif
- if (is_rw_ebit_set(lgenval)) {
- wrlock = 1;
-#if __DARWIN_UNIX03
- rwlock->rw_owner = (pthread_t)0;
-#endif /* __DARWIN_UNIX03 */
- }
-
- /* last unlock ? */
- if((lgenval & PTHRW_COUNT_MASK) == (ugenval + PTHRW_INC)) {
- if (OSAtomicCompareAndSwap32(ugenval, 0, (volatile int32_t *)useqaddr) != TRUE) {
- goto loop;
- }
- if (OSAtomicCompareAndSwap32(lgenval, PTHRW_RW_INIT, (volatile int32_t *)lseqaddr) != TRUE) {
- if (OSAtomicCompareAndSwap32(0, ugenval, (volatile int32_t *)useqaddr) != TRUE) {
-lp1:
- ulval = *useqaddr;
- nlval = ugenval+ulval;
- if (OSAtomicCompareAndSwap32(ulval, nlval, (volatile int32_t *)useqaddr) != TRUE)
- goto lp1;
- }
-
- goto loop;
- }
-
- goto succout;
- }
-
- /* do we need kernel trans? */
-
-lp11:
- nlval = lgenval & PTHRW_COUNT_MASK;
- if (ubitchanged == 0)
- ulval = (ugenval + PTHRW_INC) & PTHRW_COUNT_MASK;
- else
- ulval = ugenval & PTHRW_COUNT_MASK;
-
- num = rw_diffgenseq(nlval, ulval);
- kern_trans = ( num == (rw_wc << PTHRW_COUNT_SHIFT));
- /* if three more waiters than needed for kernel tras*/
- if ((ubitchanged ==0) && (kern_trans == 0) && (num < (rw_wc << PTHRW_COUNT_SHIFT))) {
- retry_count1++;
- sched_yield();
- if (retry_count1 < 1024)
- goto loop;
- }
- retry_count1 = 0;
-
- if (ubitchanged == 0) {
- if (OSAtomicCompareAndSwap32(ugenval, ugenval+PTHRW_INC, (volatile int32_t *)useqaddr) != TRUE)
- goto loop;
- ubitchanged = 1;
- }
-
-
- if (kern_trans == 0) {
- goto succout;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 1, ugenval+PTHRW_INC, 0);
-#endif
- initbitset = 0;
- bits = lgenval & PTHRW_BIT_MASK;
- newbits = bits;
- /* if this is first unlock to kernel, notify kernel of init status */
- if ((bits & PTHRW_RW_INIT) != 0) {
- /* reset the initbit if present */
- newbits &= ~PTHRW_RW_INIT;
- initbitset = PTHRW_RW_INIT;
- }
- if (((bits & PTHRW_EBIT) != 0) && ((bits & PTHRW_WBIT) == 0)) {
- /* reset E bit is no U bit is set */
- newbits &= ~PTHRW_EBIT;
- }
- /* clear shadow bit, as W is going to be sent to kernel */
- if ((bits & PTHRW_WBIT) != 0) {
- newbits &= ~PTHRW_SHADOW_W;
- }
-
- /* reset L bit */
- if (bits & PTHRW_LBIT)
- newbits &= ~PTHRW_LBIT;
- if (bits & PTHRW_UBIT) {
- /* reset U and set E bit */
- newbits &= ~PTHRW_LBIT;
- newbits |= PTHRW_EBIT;
- isupgrade = PTHRW_UBIT;
- }
-
- /* updates bits on the L */
- newval = (lgenval & PTHRW_COUNT_MASK) | newbits;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE) {
- /* reread the value */
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
- /* since lgen changed check for trans again */
- goto lp11;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 2, newval, 0);
-#endif
-
- /* send upgrade bit to kernel */
- newval |= (isupgrade | initbitset);
- updateval = __psynch_rw_unlock(orwlock, newval, ugenval+PTHRW_INC, rw_wc, rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if(error != 0) {
- /* not sure what is the scenario */
- if(error != EINTR)
- goto out;
- }
-
- /*
- * If the unlock is spurious return. Also if the
- * exclusive lock is being granted, let that thread
- * manage the status bits, otherwise stale bits exclusive
- * bit can be set, if that thread had already unlocked.
- */
- if ((updateval & (PTHRW_RW_SPURIOUS | PTHRW_EBIT)) != 0) {
- goto succout;
- }
-
-lp2:
- lgenval = *lseqaddr;
-
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 3, lgenval, 0);
-#endif
- /* if the kernel antcipated seq and one on the lock are same, set the one from kernel */
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE)
- goto lp2;
- goto succout;
- }
-
- /* state bits are same? */
- if ((lgenval & PTHRW_BIT_MASK) == (updateval & PTHRW_BIT_MASK)) {
- /* nothing to do */
- goto succout;
- }
-
- newval = ((lgenval & PTHRW_UN_BIT_MASK) << PTHRW_COUNT_SHIFT) | (updateval & PTHRW_BIT_MASK);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 4, newval, 0);
-#endif
- /* high bits are state on the lock; lowbits are one kernel need to set */
- switch (newval) {
- /* W States */
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
-
- /* L states */
- case ((PTHRW_LBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* Y states */
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* YU states */
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* E states */
- case ((PTHRW_EBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WE states */
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WL states */
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- default:
- /* illegal states */
- self = pthread_self();
- threadid = self->thread_id;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 6, lgenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 7, updateval, 0);
-#endif
- LIBC_ABORT("incorect state on return 0x%x: lgenval 0x%x, updateval 0x%x; threadid (0x%x)\n", newval, lgenval, updateval, (uint32_t)threadid);
-
- };
-
- if (error != 0)
- goto lp2;
-succout:
- PLOCKSTAT_RW_RELEASE(orwlock, wrlock);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(0);
-out:
- PLOCKSTAT_RW_ERROR(orwlock, wrlock, error);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
- return(error);
-}
-
-#ifdef NOTYET
-/*****************************************************************************/
-int
-_new_pthread_rwlock_downgrade_np(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, newval, ugenval, rw_wc;
- int error = 0;
- pthread_t self = pthread_self();
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(error);
- }
- } else {
- return(EINVAL);
- }
- }
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
- if ((is_rw_ebit_set(lgenval )) && (rwlock->rw_owner != self)) {
- return(EINVAL);
- }
-
- if ((lgenval & PTHRW_COUNT_MASK) != ugenval) {
-
- newval = lgenval & ~PTHRW_EBIT;
-
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
-#if __DARWIN_UNIX03
- rwlock->rw_owner = 0;
-#endif /* __DARWIN_UNIX03 */
- if (rw_wc != 0) {
- error = __psynch_rw_downgrade(orwlock, newval, ugenval, rw_wc, rwlock->rw_flags);
-
- }
- return(0);
- } else {
- goto loop;
- }
- }
- return(EINVAL);
-}
-
-
-int
-_new_pthread_rwlock_upgrade_np(pthread_rwlock_t * orwlock)
-{
- uint32_t lgenval, newval, ugenval, ulval, updateval, rw_wc;
- int error = 0, kern_trans;
- pthread_t self = pthread_self();
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint64_t oldval64, newval64;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- /* check for static initialization */
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(error);
- }
- } else {
- return(EINVAL);
- }
- }
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
- if (is_rw_uebit_set(lgenval)) {
- return(EINVAL);
-
- }
-
- if ((lgenval & PTHRW_COUNT_MASK) == ugenval)
- return(EINVAL);
-
- if (lgenval > ugenval)
- ulval = (lgenval & PTHRW_COUNT_MASK) - (ugenval & PTHRW_COUNT_MASK);
- else
- ulval = (ugenval & PTHRW_COUNT_MASK) - (lgenval & PTHRW_COUNT_MASK);
-
-
- newval = lgenval | PTHRW_UBIT;
-
- kern_trans = 1;
- if (rw_wc != 0) {
- if (ulval == ((rw_wc - 1) << PTHRW_COUNT_SHIFT))
- kern_trans = 0;
- } else if (ulval == 1)
- kern_trans = 0;
-
- if (kern_trans == 0) {
- newval = ((lgenval | PTHRW_EBIT) & ~PTHRW_LBIT);
- } else {
- newval = lgenval | PTHRW_UBIT;
- }
- if (kern_trans == 0) {
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- goto loop;
-
- } else {
- newval = (lgenval + PTHRW_INC);
-
- oldval64 = (((uint64_t)rw_wc) << 32);
- oldval64 |= lgenval;
-
- newval64 = (((uint64_t)(rw_wc + 1)) << 32);
- newval64 |= newval;
-
- if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
- goto loop;
- /* kern_trans == 1 */
- retry:
- updateval = __psynch_rw_upgrade(orwlock, newval, ugenval, rw_wc+1, rwlock->rw_flags);
- if (updateval == (uint32_t)-1) {
- error = errno;
- } else
- error = 0;
-
- if (error == EINTR)
- goto retry;
-
- if (error != 0) {
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
- goto out;
- }
-
- if (is_rw_ebit_set(updateval)) {
- /* kernel cannot wakeup without granting E bit */
- abort();
- }
-
- error = rwlock_exclusive_lockreturn(orwlock, updateval);
- if (error == EAGAIN)
- goto retry;
-
- OSAtomicDecrement32((volatile int32_t *)wcaddr);
-
- }
- if (error == 0) {
- rwlock->rw_owner = self;
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- }
-
-out:
- return(error);
-}
-
-int
-pthread_rwlock_tryupgrade_np(pthread_rwlock_t *orwlock)
-{
- pthread_t self = pthread_self();
- uint32_t lgenval, newval, ugenval, ulval, rw_wc;
- int error = 0, kern_trans;
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(error);
- }
- } else {
- return(EINVAL);
- }
- }
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-loop:
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
- rw_wc = *wcaddr;
-
- if (is_rw_uebit_set(lgenval)) {
- return(EBUSY);
- }
-
- if ((lgenval & PTHRW_COUNT_MASK) == ugenval)
- return(EINVAL);
-
- if (lgenval > ugenval)
- ulval = (lgenval & PTHRW_COUNT_MASK) - (ugenval & PTHRW_COUNT_MASK);
- else
- ulval = (ugenval & PTHRW_COUNT_MASK) - (lgenval & PTHRW_COUNT_MASK);
-
-
- newval = lgenval | PTHRW_UBIT;
-
- kern_trans = 1;
- if (rw_wc != 0) {
- /* there is only one reader thread */
- if (ulval == (rw_wc - 1))
- kern_trans = 0;
- } else if (ulval == 1)
- kern_trans = 0;
-
- if (kern_trans == 0) {
- newval = (lgenval | PTHRW_EBIT) & ~PTHRW_LBIT;
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- goto loop;
-
- rwlock->rw_owner = self;
- PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
- return(0);
- }
- return(EBUSY);
-}
-
-/* Returns true if the rwlock is held for reading by any thread or held for writing by the current thread */
-int
-pthread_rwlock_held_np(pthread_rwlock_t * orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval, ugenval;
- int error = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(0);
- }
- } else {
- return(-1);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
- ugenval = *useqaddr;
-
- if ((lgenval & PTHRW_COUNT_MASK) == (ugenval & PTHRW_COUNT_MASK))
- return(0);
-
- return(1);
-}
-
-/* Returns true if the rwlock is held for reading by any thread */
-int
-pthread_rwlock_rdheld_np(pthread_rwlock_t * orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval;
- int error = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(0);
- }
- } else {
- return(-1);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
-
- if (is_rw_ebit_set(lgenval)) {
- return(0);
- }
- return(0);
-}
-
-/* Returns true if the rwlock is held for writing by the current thread */
-int
-pthread_rwlock_wrheld_np(pthread_rwlock_t * orwlock)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- pthread_t self;
- uint32_t lgenval;
- int error = 0;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
- if ((error = pthread_rwlock_init(orwlock, NULL)) != 0) {
- return(0);
- }
- } else {
- return(-1);
- }
- }
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- self = pthread_self();
-
- lgenval = *lseqaddr;
- if ((is_rw_ebit_set(lgenval)) && (rwlock->rw_owner == self)) {
- return(1);
- }
- return(0);
-}
-/**************************************************************/
-#endif /* NOTYET */
-
-static int
-rwlock_unlock_action_onread(pthread_rwlock_t * orwlock, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- int error = 0;
- uint32_t lgenval, newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
- pthread_t self;
- uint64_t threadid;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- lgenval = *lseqaddr;
-
-lp2:
- lgenval = *lseqaddr;
-
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 3, lgenval, 0);
-#endif
- /* if the kernel antcipated seq and one on the lock are same, set the one from kernel */
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE)
- goto lp2;
- goto succout;
- }
-
- /* state bits are same? */
- if ((lgenval & PTHRW_BIT_MASK) == (updateval & PTHRW_BIT_MASK)) {
- /* nothing to do */
- goto succout;
- }
-
- newval = ((lgenval & PTHRW_UN_BIT_MASK) << PTHRW_COUNT_SHIFT) | (updateval & PTHRW_BIT_MASK);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 4, newval, 0);
-#endif
- /* high bits are state on the lock; lowbits are one kernel need to set */
- switch (newval) {
- /* W States */
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
-
- /* L states */
- case ((PTHRW_LBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* Y states */
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* YU states */
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action_k(orwlock, lgenval, updateval);
- //goto ktrans;
- }
- break;
-
- /* E states */
- case ((PTHRW_EBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WE states */
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action2(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WL states */
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_LBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_LBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- default:
- /* illegal states */
- self = pthread_self();
- threadid = self->thread_id;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 6, lgenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 7, updateval, 0);
-#endif
- LIBC_ABORT("incorect state on return 0x%x: lgenval 0x%x, updateval 0x%x; threadid (0x%x)\n", newval, lgenval, updateval, (uint32_t)threadid);
- };
-
- if (error != 0)
- goto lp2;
-
-succout:
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, lgenval, newval, 0, 0, 0);
-#endif
- return(0);
-}
-
-
-static uint32_t
-modbits(uint32_t lgenval, uint32_t updateval)
-{
- uint32_t lval = lgenval & PTHRW_BIT_MASK;
- uint32_t uval = updateval & PTHRW_BIT_MASK;
- uint32_t rval, nlval;
-
- nlval = (lval | uval);
- if ((uval & PTHRW_EBIT) == 0)
- nlval &= ~PTHRW_EBIT;
- if ((nlval & (PTHRW_WBIT | PTHRW_YBIT)) == (PTHRW_WBIT | PTHRW_YBIT))
- nlval &= ~PTHRW_YBIT;
- /* no new writers and kernel resets w bit, reset W bit on the lock */
- if (((nlval & (PTHRW_WBIT | PTHRW_SHADOW_W)) == PTHRW_WBIT) && ((updateval & PTHRW_WBIT) == 0))
- nlval &= ~PTHRW_WBIT;
-
- rval = (lgenval & PTHRW_COUNT_MASK) | nlval;
- return(rval);
-}
-
-static int
-rwlock_unlock_action1(pthread_rwlock_t * orwlock, uint32_t lgenval, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- int error = 0;
- uint32_t newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- newval = modbits(lgenval, updateval);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) != TRUE)
- error = EINVAL;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, lgenval, newval, 0, 0, 0);
-#endif
- return(error);
-}
-
-static int
-rwlock_unlock_action2(pthread_rwlock_t * orwlock, uint32_t lgenval, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- newval = modbits(lgenval, updateval);
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
- /* roundtrip kernel */
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT2 | DBG_FUNC_NONE, lgenval, newval, 0, 0, 0);
-#endif
- (void) __psynch_rw_unlock2(orwlock, lgenval, *useqaddr, *wcaddr, rwlock->rw_flags);
- return(0);
- }
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACT2 | DBG_FUNC_NONE, 0xffffffff, 0, 0, 0, 0);
-#endif
-
- return(EINVAL);
-}
-
-/* This is used when an exclusive write lock of any kind is being granted. For unlock thread, it needs to try to set the bit, if not move on */
-static int
-rwlock_unlock_action_k(pthread_rwlock_t * orwlock, uint32_t lgenval, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
- newval = modbits(lgenval, updateval);
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTK | DBG_FUNC_NONE, lgenval, updateval, newval, 0, 0);
-#endif
- /* try to set, if not not a prolem as the thread taking exclusive will take care of the discrepency */
-
- if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTK | DBG_FUNC_NONE, 0x55555555, lgenval, newval, 0, 0);
-#endif
-
- } else {
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTK | DBG_FUNC_NONE, 0xAAAAAAAA, lgenval, newval, 0, 0);
-#endif
-
- }
-
- return(0);
-}
-
-static int
-rwlock_exclusive_lockreturn(pthread_rwlock_t * orwlock, uint32_t updateval)
-{
- npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
- uint32_t lgenval, newval;
- volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
- pthread_t self;
- uint64_t threadid;
-
- int error = 0;
-
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
- } else {
- lseqaddr = rwlock->rw_lseqaddr;
- useqaddr = rwlock->rw_useqaddr;
- wcaddr = rwlock->rw_wcaddr;
- }
-
-lp2:
- lgenval = *lseqaddr;
-
- /* if the kernel antcipated seq and one on the lock are same, set the one from kernel */
- if ((lgenval & PTHRW_COUNT_MASK) == (updateval & PTHRW_COUNT_MASK)) {
- if (OSAtomicCompareAndSwap32(lgenval, updateval, (volatile int32_t *)lseqaddr) != TRUE)
- goto lp2;
- goto out;
- }
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, lgenval, updateval, 1, 0, 0);
-#endif
- /* state bits are same? */
- if ((lgenval & PTHRW_BIT_MASK) == (updateval & PTHRW_BIT_MASK)) {
- /* nothing to do */
- goto out;
- }
-
-
- newval = ((lgenval & PTHRW_UN_BIT_MASK) << PTHRW_COUNT_SHIFT) | (updateval & PTHRW_BIT_MASK);
-
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, newval, 0, 2, 0, 0);
-#endif
- /* high bits are state on the lock; lowbits are one kernel need to set */
- switch (newval) {
- /* W States */
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case ((PTHRW_WBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
-
- /* All L states illegal here */
-
- /* Y states */
- case (PTHRW_YBIT << PTHRW_COUNT_SHIFT) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
- case ((PTHRW_YBIT << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
- /* YU states */
- case ((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
- case (((PTHRW_YBIT | PTHRW_UBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = EAGAIN;
- }
- break;
-
- /* E states */
- case ((PTHRW_EBIT << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* WE states */
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_WBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
- case (((PTHRW_WBIT | PTHRW_EBIT) << PTHRW_COUNT_SHIFT) | (PTHRW_YBIT | PTHRW_EBIT)) : {
- error = rwlock_unlock_action1(orwlock, lgenval, updateval);
- }
- break;
-
- /* All WL states are illegal*/
-
- default:
- /* illegal states */
- self = pthread_self();
- threadid = self->thread_id;
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 6, lgenval, 0);
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, 7, updateval, 0);
-#endif
- LIBC_ABORT("rwlock_exclusive_lockreturn: incorect state on return 0x%x: lgenval 0x%x, updateval 0x%x; threadid (0x%x)\n", newval, lgenval, updateval, (uint32_t)threadid);
- };
-
- if (error == EINVAL)
- goto lp2;
-out:
-#if _KSYN_TRACE_
- (void)__kdebug_trace(_KSYN_TRACE_RW_UNACTE | DBG_FUNC_NONE, error, 0, 0xffffffff, 0, 0);
-#endif
- return(error);
-}
-
-/* returns are not bit shifted */
-static int
-rw_diffgenseq(uint32_t x, uint32_t y)
-{
- uint32_t lx = (x & PTHRW_COUNT_MASK);
- uint32_t ly = (y &PTHRW_COUNT_MASK);
-
- if (lx > ly) {
- return(lx-ly);
- } else {
- return((PTHRW_MAX_READERS - y) + lx + PTHRW_INC);
- }
-
-}
-
-#endif /* i386 || x86_64 ] */
-
-
-#endif /* !BUILDING_VARIANT ] */
-
-int
-pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
-{
-#if defined(__i386__) || defined(__x86_64__) || defined(__DARWIN_UNIX03)
- int ret;
-#endif /* __i386__ || __x86_64__ */
-
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_destroy(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
- if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
- return(EINVAL);
- }
-#if defined(__i386__) || defined(__x86_64__)
- else if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_destroy(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
- else {
#if __DARWIN_UNIX03
/* grab the monitor lock */
if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0)
@@ -2202,27 +170,10 @@
pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
{
int ret;
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_init(rwlock, attr));
- }
-#endif /* __i386__ || __x86_64__ */
-
#if __DARWIN_UNIX03
if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) {
return(EINVAL);
}
-#endif /* __DARWIN_UNIX03 */
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((attr != NULL) && (attr->pshared == PTHREAD_PROCESS_SHARED)) {
- ret = _new_pthread_rwlock_init(rwlock, attr);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
-
-#if __DARWIN_UNIX03
/* if already inited check whether it is in use, then return EBUSY */
if ((rwlock->sig == _PTHREAD_RWLOCK_SIG) && (rwlock->state !=0 )) {
return(EBUSY);
@@ -2272,12 +223,6 @@
pthread_t self = pthread_self();
#endif
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_rdlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
@@ -2289,12 +234,6 @@
PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_rdlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
/* grab the monitor lock */
if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
@@ -2356,12 +295,9 @@
pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
{
int ret;
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_tryrdlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
+#if __DARWIN_UNIX03
+ pthread_t self = pthread_self();
+#endif
/* check for static initialization */
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
@@ -2375,13 +311,6 @@
PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_tryrdlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
-
/* grab the monitor lock */
if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);
@@ -2416,12 +345,6 @@
pthread_t self = pthread_self();
#endif /* __DARWIN_UNIX03 */
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_trywrlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
/* check for static initialization */
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
@@ -2434,14 +357,6 @@
PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
-
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_trywrlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
-
/* grab the monitor lock */
if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
@@ -2473,26 +388,14 @@
{
int ret;
int writer = (rwlock < 0) ? 1:0;
-
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_unlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
+#if __DARWIN_UNIX03
+ pthread_t self = pthread_self();
+#endif /* __DARWIN_UNIX03 */
if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
PLOCKSTAT_RW_ERROR(rwlock, writer, EINVAL);
return(EINVAL);
}
-
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_unlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
-
-
/* grab the monitor lock */
if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
PLOCKSTAT_RW_ERROR(rwlock, writer, ret);
@@ -2535,12 +438,6 @@
pthread_t self = pthread_self();
#endif /* __DARWIN_UNIX03 */
-#if defined(__i386__) || defined(__x86_64__)
- if ((usenew_impl != 0)) {
- return(_new_pthread_rwlock_wrlock(rwlock));
- }
-#endif /* __i386__ || __x86_64__ */
-
/* check for static initialization */
if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) {
@@ -2553,20 +450,11 @@
PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
return(EINVAL);
}
-
-#if defined(__i386__) || defined(__x86_64__)
- if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
- ret = _new_pthread_rwlock_wrlock(rwlock);
- return(ret);
- }
-#endif /* __i386__ || __x86_64__ */
-
-
/* grab the monitor lock */
if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) {
PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
return(ret);
- }
+ }
#if __DARWIN_UNIX03
if ((rwlock->state < 0) && (rwlock->owner == self)) {
@@ -2607,3 +495,4 @@
return(ret);
}
+