Loading...
pthreads/pthread_rwlock.c Libc-763.12 Libc-583
--- Libc/Libc-763.12/pthreads/pthread_rwlock.c
+++ Libc/Libc-583/pthreads/pthread_rwlock.c
@@ -79,54 +79,58 @@
 /* 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 /* [ */
-__private_extern__ int usenew_impl = 1;
+int usenew_impl = 0;
 #else /* BUILDING_VARIANT */
 extern int usenew_impl;
 #endif /* BUILDING_VARIANT */
 
-extern int PR_5243343_flag;
 
 #if defined(__LP64__)
-#define RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr) \
+#define RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr) \
 { \
                 if (rwlock->misalign != 0) { \
-                        lcntaddr = &rwlock->rw_seq[1]; \
-			seqaddr = &rwlock->rw_seq[2]; \
-                        ucntaddr = &rwlock->rw_seq[3]; \
+                        lseqaddr = &rwlock->rw_seq[1]; \
+			wcaddr = &rwlock->rw_seq[2]; \
+                        useqaddr = &rwlock->rw_seq[3]; \
                  } else { \
-                        lcntaddr = &rwlock->rw_seq[0]; \
-			seqaddr = &rwlock->rw_seq[1]; \
-                        ucntaddr = &rwlock->rw_seq[2]; \
+                        lseqaddr = &rwlock->rw_seq[0]; \
+			wcaddr = &rwlock->rw_seq[1]; \
+                        useqaddr = &rwlock->rw_seq[2]; \
                 } \
 }
 #else /* __LP64__ */
-#define RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr) \
+#define RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr) \
 { \
                 if (rwlock->misalign != 0) { \
-                        lcntaddr = &rwlock->rw_seq[1]; \
-			seqaddr = &rwlock->rw_seq[2]; \
-                        ucntaddr = &rwlock->rw_seq[3]; \
-                 } else { \
-                        lcntaddr = &rwlock->rw_seq[0]; \
-			seqaddr = &rwlock->rw_seq[1]; \
-                        ucntaddr = &rwlock->rw_seq[2]; \
+                        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__ */
 
-__private_extern__ int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
-
+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_
-#include <sys/sysctl.h>
-#ifndef BUILDING_VARIANT /* [ */
-static void set_enable(int);
-#endif /* !BUILDING_VARIANT ] */
-
 /* The Function qualifiers  */
 #define DBG_FUNC_START          1
 #define DBG_FUNC_END            2
@@ -141,17 +145,21 @@
 #define _KSYN_TRACE_RW_UNACT2    0x9008090
 #define _KSYN_TRACE_RW_UNACTK    0x9008094
 #define _KSYN_TRACE_RW_UNACTE    0x9008098
-#define _KSYN_TRACE_RW_UNACTR    0x900809c
-#define _KSYN_TRACE_RW_TOOMANY    0x90080a0
-#define _KSYN_TRACE_RW_TRYWRLOCK    0x90080a4
-#define _KSYN_TRACE_RW_TRYRDLOCK    0x90080a8
 #endif /* _KSYN_TRACE_ */
-
-__private_extern__ void rwlock_action_onreturn(pthread_rwlock_t * rwlock, uint32_t updateval);
-__private_extern__ int rw_diffgenseq(uint32_t x, uint32_t y);
+#endif /* __i386__ || __x86_64__ */
 
 #ifndef BUILDING_VARIANT /* [ */
-static uint32_t modbits(uint32_t lgenval, uint32_t updateval, uint32_t savebits);
+
+#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
 pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
@@ -208,14 +216,81 @@
 
 }
 
-__private_extern__ int
-__pthread_rwlock_init(pthread_rwlock_t * orwlock, const pthread_rwlockattr_t *attr)
+#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 */
+	
+	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;
@@ -224,262 +299,83 @@
 	if (((uintptr_t)rwlock & 0x07) != 0) {
 		rwlock->misalign = 1;
 #if defined(__LP64__)
-		rwlock->rw_lcntaddr = &rwlock->rw_seq[1];
-		rwlock->rw_seqaddr = &rwlock->rw_seq[2];
-		rwlock->rw_ucntaddr = &rwlock->rw_seq[3];
-		rwlock->rw_seq[1]= PTHRW_RWLOCK_INIT;
-		rwlock->rw_seq[2]= PTHRW_RWS_INIT;
-		rwlock->rw_seq[3]= 0;
+		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_lcntaddr = &rwlock->rw_seq[1];
-		rwlock->rw_seqaddr = &rwlock->rw_seq[2];
-		rwlock->rw_ucntaddr = &rwlock->rw_seq[3];
-		rwlock->rw_seq[1]= PTHRW_RWLOCK_INIT;
-		rwlock->rw_seq[2]= PTHRW_RWS_INIT;
-		rwlock->rw_seq[3]= 0;
+		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_lcntaddr = &rwlock->rw_seq[0];
-		rwlock->rw_seqaddr = &rwlock->rw_seq[1];
-		rwlock->rw_ucntaddr = &rwlock->rw_seq[2];
-		rwlock->rw_seq[0]= PTHRW_RWLOCK_INIT;
-		rwlock->rw_seq[1]= PTHRW_RWS_INIT;
-		rwlock->rw_seq[2]= 0;
+		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_lcntaddr = &rwlock->rw_seq[0];
-		rwlock->rw_seqaddr = &rwlock->rw_seq[1];
-		rwlock->rw_ucntaddr = &rwlock->rw_seq[2];
-		rwlock->rw_seq[0]= PTHRW_RWLOCK_INIT;
-		rwlock->rw_seq[1]= PTHRW_RWS_INIT;
-		rwlock->rw_seq[2]= 0;
+		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->reserv = 0;
-	rwlock->rw_owner = NULL;
-#if defined(__LP64__)
-	memset(rwlock->rfu, 0, PTHRW_RFU_64BIT);
-#else
-	memset(rwlock->rfu, 0, PTHRW_RFU_32BIT);
-#endif 
-
 	rwlock->sig = _PTHREAD_RWLOCK_SIG;
 	
 	return(0);
 }
 
-#if _KSYN_TRACE_
-static void
-set_enable(int val)
-{
-	int mib[6];
-	size_t needed = 0;
-
-    mib[0] = CTL_KERN;
-	mib[1] = KERN_KDEBUG;
-	mib[2] = KERN_KDENABLE;
-	mib[3] = val;
-	mib[4] = 0;
-	mib[5] = 0;
-	/* best effort to stop the trace */
-	(void)sysctl(mib, 4, NULL, &needed, NULL, 0);
-}
-#endif
-
-static uint32_t
-modbits(uint32_t lgenval, uint32_t updateval, uint32_t savebits)
-{
-	uint32_t lval = lgenval & PTHRW_BIT_MASK;
-	uint32_t uval = updateval & PTHRW_BIT_MASK;
-	uint32_t rval, nlval;
-
-	nlval = (lval | uval) & ~(PTH_RWL_MBIT);
-	
-	/* reconcile bits on the lock with what kernel needs to set */
-	if ((uval & PTH_RWL_LBIT) != 0)
-		nlval &= ~PTH_RWL_KBIT;
-	else if (((uval & PTH_RWL_KBIT) == 0) && ((lval & PTH_RWL_WBIT) == 0))
-		nlval &= ~PTH_RWL_KBIT;
-
-	if (savebits !=0 ) {
-		if (((savebits & PTH_RWS_WSVBIT) != 0) && ((nlval & PTH_RWL_WBIT) == 0) && 
-				((nlval & PTH_RWL_EBIT) == 0)) {
-			if ((nlval & PTH_RWL_LBIT) == 0)
-				nlval |= (PTH_RWL_WBIT | PTH_RWL_KBIT);
-			else
-				nlval |= PTH_RWL_WBIT;
-		}
-		if (((savebits & PTH_RWS_YSVBIT) != 0) && ((nlval & PTH_RWL_YBIT) == 0) && 
-				((nlval & PTH_RWL_EBIT) == 0)) {
-				nlval |= PTH_RWL_YBIT;
-		}
-		if (((savebits & PTH_RWS_USVBIT) != 0) && ((nlval & PTH_RWL_EBIT) == 0)) {
-			if ((nlval & PTH_RWL_LBIT) == 0)
-				nlval |= (PTH_RWL_UBIT | PTH_RWL_KBIT);
-			else
-				nlval |= PTH_RWL_UBIT;
-		}
-	}
-	rval = (lgenval & PTHRW_COUNT_MASK) | nlval;
-	return(rval);
-}
-
-
-__private_extern__ void
-rwlock_action_onreturn(pthread_rwlock_t * orwlock, uint32_t updateval)
-{
-
+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 lcntval, rw_seq, newval = 0, newsval, lval, uval;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+	uint32_t lgenval, ugenval, rw_wc, newval, updateval;
+	int error = 0, ret;
 	uint64_t oldval64, newval64;
-	int setbits = 0;
-	int overlap = 0;
-	uint32_t savebits = 0;
-	int isoverlap = 0;
-	
-	/* TBD: restore U bit */
-	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_START, updateval, 0, 0, 0, 0);
-#endif
-
-	isoverlap = updateval & PTH_RWL_MBIT;
-
-loop:
-	setbits = 0;
-	lcntval = *lcntaddr;
-	rw_seq = *seqaddr;
-	savebits = 0;
-	
-	if (isoverlap != 0) {
-		/* overlap return, just increment and inspect bits */
-		setbits = 1;
-		overlap = 1;
-		/* set s word, increment by specified value  */
-		newsval = rw_seq + (updateval & PTHRW_COUNT_MASK);
-		if ((newsval &  PTHRW_RWS_SAVEMASK) != 0) {
-			savebits = newsval & PTHRW_RWS_SAVEMASK;
-			newsval &= ~PTHRW_RWS_SAVEMASK;
-		}
-	} else {
-		/* normal return */
-		if (is_rws_setunlockinit(rw_seq) != 0) {
-			setbits = 1;
-			/* set s word to passed in value */
-			newsval = (rw_seq & PTHRW_COUNT_MASK) + (updateval & PTHRW_COUNT_MASK);
-			if ((rw_seq &  PTHRW_RWS_SAVEMASK) != 0) {
-				savebits = rw_seq & PTHRW_RWS_SAVEMASK;
-				newsval &= ~PTHRW_RWS_SAVEMASK;
-			}
-		} else {
-			newval = lcntval;
-			newsval = rw_seq;
-		}
-	}
-	if (setbits != 0) {
-		newval = modbits(lcntval, updateval, savebits);
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, rw_seq, newsval, 0xeeeeeeee, updateval, 0);
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_NONE, lcntval, newval, 0xeeeeeeee, updateval, 0);
-#endif
-		oldval64 = (((uint64_t)rw_seq) << 32);
-		oldval64 |= lcntval;
-		newval64 = (((uint64_t)newsval) << 32);
-		newval64 |= newval;
-	
-		if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-			goto loop;
-		/* Check for consistency */
-		lval = lcntval & PTHRW_BIT_MASK;
-		uval = updateval & PTHRW_BIT_MASK;
-	}
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNACT1 | DBG_FUNC_END, rw_seq, newsval, 0xffffffff, 0, 0);
-#endif
-	return;
-}
-
-/* returns are not bit shifted */
-__private_extern__ 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);
-	}
-
-}
-
-#ifdef NOTYET
-/********************************************************** */
-static int pthread_rwlock_upgrade_internal(pthread_rwlock_t * orwlock, int trylock);
-
-int
-pthread_rwlock_longrdlock_np(pthread_rwlock_t * orwlock)
-{
-	pthread_t self;
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
-	int error = 0, retry_count = 0;
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
 	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
 				return(error);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
+		} else {
 			PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
 			return(EINVAL);
 		}
-		UNLOCK(rwlock->lock);
 	}
 	
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
+		lseqaddr = rwlock->rw_lseqaddr;
+		useqaddr = rwlock->rw_useqaddr;
+		wcaddr = rwlock->rw_wcaddr;
+	}
 loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-	
-	if (can_rwl_longreadinuser(lcntval))
+	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 __DARWIN_UNIX03
-	if (is_rwl_ebit_set(lcntval)) {
+	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;
@@ -488,85 +384,244 @@
 	}
 #endif /* __DARWIN_UNIX03 */
 	
-	/* need to block in kernel */
-	newval  = (lcntval + PTHRW_INC);
-
-	newsval = rw_seq;
-	if (is_rws_setseq(rw_seq)) {
-		newsval &= PTHRW_SW_Reset_BIT_MASK;
-		newsval |= (newval & PTHRW_COUNT_MASK);
-	}
-
-	/* update lock seq and  block in kernel */
-	
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	newval64 = (((uint64_t)(newsval)) << 32);
+	/* 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 *)lcntaddr) != TRUE)
+	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
 		goto loop;
-kblock:
-	updateval = __psynch_rw_longrdlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
+
+	/* 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) {
-		rwlock_action_onreturn(orwlock, updateval);
-		if ( is_rwl_lbit_clear(updateval)) {
-#if _KSYN_TRACE_
-			set_enable(2);
-#endif /* _KSYN_TRACE_ */
-			(void)pthread_threadid_np(pthread_self(), &myid);
-			LIBC_ABORT("yieldwrlock from kernel without EBit  %x: tid %x\n", updateval, (uint32_t)myid);
-			/* kernel cannot wakeup without granting E bit */
-		}
+	
+		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 {
-#if _KSYN_TRACE_
-		set_enable(2);
-#endif /* _KSYN_TRACE_ */
-		(void)pthread_threadid_np(pthread_self(), &myid);
-		LIBC_ABORT("yieldwrlock from kernel with unknown error %x: tid %x\n", updateval, (uint32_t)myid);
+	} else
 		goto out;
-	}
+	goto successout;
 	
 gotlock:
-	if (rw_diffgenseq(lcntval, ucntval) >= PTHRW_MAX_READERS) {
-		/* since ucntval may be newer, just redo */
-		retry_count++;
-		if (retry_count > 1024) {
-		
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TOOMANY | DBG_FUNC_NONE, (uint32_t)rwlock, 0XEEEEEEEE, lcntval, ucntval, 0);
-#endif
-			error = EAGAIN;
-			goto out;
-		} else {
-			sched_yield();
-			goto loop;
-		}
-	}
-	
-	/* Need to update L and S word */
-	newval  = (lcntval + PTHRW_INC) | PTH_RWL_LBIT;
-	newsval = (rw_seq + PTHRW_INC);
-
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	newval64 = (((uint64_t)newsval) << 32);
-	newval64 |= newval;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+	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);
@@ -574,126 +629,279 @@
 	PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);    
 	return(error);
 }
+/**************************************************************/
+#endif /* NOTYET */
 
 int
-pthread_rwlock_yieldwrlock_np(pthread_rwlock_t * orwlock)
-{
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
+_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;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
 	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
+		/* check for static initialization */
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
 				return(error);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
+		} else {
 			PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
 			return(EINVAL);
 		}
-		UNLOCK(rwlock->lock);
-	}
-
+	}
+	
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
+		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:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-
-#if __DARWIN_UNIX03
-	if (is_rwl_ebit_set(lcntval)) {
-		if (rwlock->rw_owner == self) {
+	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 (lcntval == PTHRW_RWL_INIT) {
-		/* if we can acquire set L and S word */
-		lcntval = PTHRW_RWL_INIT;
-		newval  = PTHRW_RWL_INIT | PTHRW_INC | PTH_RWL_KBIT| PTH_RWL_EBIT;
-		newsval = rw_seq + PTHRW_INC;
-
-		oldval64 = (((uint64_t)rw_seq) << 32);
-		oldval64 |= lcntval;
-	
-		newval64 = (((uint64_t)newsval) << 32);
-		newval64 |= newval;
-	
-		if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) == TRUE) {
+	if (lgenval  == PTHRW_RW_INIT) {
+		newval  = ( PTHRW_RW_INIT | PTHRW_INC | PTHRW_EBIT);
+		if (OSAtomicCompareAndSwap32(lgenval, newval, (volatile int32_t *)lseqaddr) == TRUE) {
 			goto gotit;
-		} else
-			goto loop;
-	}
-	
-	newval = (lcntval + PTHRW_INC)| PTH_RWL_YBIT;	
-
-	newsval = rw_seq;
-	if (is_rws_setseq(rw_seq)) {
-		newsval &= PTHRW_SW_Reset_BIT_MASK;
-		newsval |= (newval & PTHRW_COUNT_MASK);
-	}
-	
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	newval64 = (((uint64_t)(newsval)) << 32);
+		}
+	}
+	
+	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 (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
+#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);
-retry:
-	updateval = __psynch_rw_yieldwrlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
+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) {
-#if _KSYN_TRACE_
-		set_enable(2);
-#endif /* _KSYN_TRACE_ */
-		(void)pthread_threadid_np(pthread_self(), &myid);
-		LIBC_ABORT("yieldwrlock from kernel with unknown error %x: tid %x\n", updateval, (uint32_t)myid);
-	}
-	
-	
-out:	
+		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:
-		rwlock_action_onreturn(orwlock, updateval);
-		if ( is_rwl_ebit_clear(updateval)) {
-#if _KSYN_TRACE_
-			set_enable(2);
-#endif /* _KSYN_TRACE_ */
-			(void)pthread_threadid_np(pthread_self(), &myid);
-			LIBC_ABORT("yieldwrlock from kernel without EBit  %x: tid %x\n", updateval, (uint32_t)myid);
-		}
+	gotit:
 #if __DARWIN_UNIX03
 		rwlock->rw_owner = self;
 #endif /* __DARWIN_UNIX03 */
@@ -701,291 +909,680 @@
 		return(0);
 	} else {
 		PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);    
-		return(error);
-	}
-}
+	}
+	return(error);
+out:
+	PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);    
+	return(error);
+}
+/**************************************************************/
+#endif /* NOTYET */
+
 int
-pthread_rwlock_downgrade_np(pthread_rwlock_t * orwlock)
-{
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
-	int error = 0, haswbit = 0, hasubit = 0, hasybit = 0;
-#if __DARWIN_UNIX03
+_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();
-#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)  {
+				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 * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
 	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
+		/* check for static initialization */
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
-				PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				return(error);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
-			PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
+		} else {
 			return(EINVAL);
 		}
-		UNLOCK(rwlock->lock);
 	}
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
+		lseqaddr = rwlock->rw_lseqaddr;
+		useqaddr = rwlock->rw_useqaddr;
+		wcaddr = rwlock->rw_wcaddr;
+	}
 loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-
-	
-	/* if not holding exclusive lock, return */
-	if ((is_rwl_ebit_set(lcntval )== 0) || (rwlock->rw_owner != self)) {
+	lgenval = *lseqaddr;
+	ugenval = *useqaddr;
+	rw_wc = *wcaddr;
+	
+	if (is_rw_uebit_set(lgenval)) {
 		return(EINVAL);
-	}
-	
-	/* no other waiters and be granted in user space? ? */
-	if ((lcntval & PTHRW_COUNT_MASK) == (ucntval + PTHRW_INC)) {
-#if 0
-		/* should have no write waiters pending */
-		if (is_rwl_wbit_set(lcntval) != 0) {
-#if _KSYN_TRACE_
-			set_enable(2);
-#endif /* _KSYN_TRACE_ */
-			(void)pthread_threadid_np(pthread_self(), &myid);
-			LIBC_ABORT("downgrade in user mode but W bit set  %x: tid %x\n", lcntval, (uint32_t)myid);
-		}
-#endif
-		/* preserve count and remove ke bits */
-		newval = lcntval & ~(PTH_RWL_EBIT | PTH_RWL_KBIT);
-		/* if we can acquire set L and S word */
-		newsval = rw_seq;
-
-		oldval64 = (((uint64_t)rw_seq) << 32);
-		oldval64 |= lcntval;
-	
-		newval64 = (((uint64_t)newsval) << 32);
+		
+	}
+	
+	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 *)lcntaddr) == TRUE) {
-#if __DARWIN_UNIX03
-			rwlock->rw_owner = (pthread_t)0;
-#endif /* __DARWIN_UNIX03 */
-			return(0);
-		} else
+		
+		if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lseqaddr) != TRUE)
 			goto loop;
-	} else {
-		
-		haswbit = lcntval & PTH_RWL_WBIT;
-		hasubit = lcntval & PTH_RWL_UBIT;
-		hasybit = lcntval & PTH_RWL_YBIT;
-
-		/* reset all bits and set k */
-		newval = (lcntval & PTHRW_COUNT_MASK) | PTH_RWL_KBIT;
-		/* set I bit on S word */	
-		newsval = rw_seq | PTH_RWS_IBIT;
-		if (haswbit != 0)
-			newsval |= PTH_RWS_WSVBIT;
-		if (hasubit != 0)
-			newsval |= PTH_RWS_USVBIT;
-		if (hasybit != 0)
-			newsval |= PTH_RWS_YSVBIT;
-
-		oldval64 = (((uint64_t)rw_seq) << 32);
-		oldval64 |= lcntval;
-	
-		newval64 = (((uint64_t)newsval) << 32);
-		newval64 |= newval;
-	
-		if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-			goto loop;
-
-#if __DARWIN_UNIX03
-		rwlock->rw_owner = 0;
-#endif /* __DARWIN_UNIX03 */
-
-retry:
-		updateval = __psynch_rw_downgrade(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
+		/* 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;
-	
-		/* TBD: what to do with the error, EINTR ?? */
+		
 		if (error == EINTR)
 			goto retry;
-
-		if (error == 0)  {
-			rwlock_action_onreturn(orwlock, updateval);
-			return(0);
-		} else {
-#if _KSYN_TRACE_
-			set_enable(1);
-#endif /* _KSYN_TRACE_ */
-			(void)pthread_threadid_np(pthread_self(), &myid);
-			LIBC_ABORT("downgrade from kernel with unknown error %x with tid %x\n", updateval, (uint32_t)myid);
-		}
-		/* Not reached */	
-	}
-	return(EINVAL);	
-}
-
-int
-pthread_rwlock_upgrade_np(pthread_rwlock_t * orwlock)
-{
-	return(pthread_rwlock_upgrade_internal(orwlock, 0));
+		
+		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)
 {
-	return(pthread_rwlock_upgrade_internal(orwlock, 1));
-}
-
-static int
-pthread_rwlock_upgrade_internal(pthread_rwlock_t * orwlock, int trylock)
-{
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
-	int error = 0, flags ;
-#if __DARWIN_UNIX03
 	pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
+	uint32_t lgenval, newval, ugenval, ulval, rw_wc;
+	int error = 0, kern_trans;
 	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
 	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		/* check for static initialization */
-		LOCK(rwlock->lock);
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				return(error);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
+		} else {
 			return(EINVAL);
 		}
-		UNLOCK(rwlock->lock);
 	}
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
+		lseqaddr = rwlock->rw_lseqaddr;
+		useqaddr = rwlock->rw_useqaddr;
+		wcaddr = rwlock->rw_wcaddr;
 	}
 
 loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-	
-	if (is_rwl_eubit_set(lcntval) !=0) {
+	lgenval = *lseqaddr;
+	ugenval = *useqaddr;
+	rw_wc = *wcaddr;
+	
+	if (is_rw_uebit_set(lgenval)) {
 		return(EBUSY);
 	}
 	
-	/* set U and K bit and go to kernel */
-	newval  = (lcntval  | (PTH_RWL_UBIT | PTH_RWL_KBIT));
-	newsval = rw_seq;
-#if 0
-	if (is_rws_setseq(rw_seq)) {
-		newsval &= PTHRW_SW_Reset_BIT_MASK;
-		newsval |= (newval & PTHRW_COUNT_MASK);
-	}
-#endif
-
-	/* update lock seq and  block in kernel */
-	
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	newval64 = (((uint64_t)(newsval)) << 32);
-	newval64 |= newval;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-		goto loop;
-	flags = rwlock->rw_flags;
-	if (trylock != 0) {
-		flags |= _PTHREAD_RWLOCK_UPGRADE_TRY;
-	}
-retry:
-	updateval = __psynch_rw_upgrade(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
-	if (updateval == (uint32_t)-1) {
-		error = errno;
-	} else
-		error = 0;
+	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;
 		
-	if (error == EINTR)
-		goto retry;
-		
-		
-	if (error == 0) {
-		rwlock_action_onreturn(orwlock, updateval);
-		if ( is_rwl_ebit_clear(updateval)) {
-#if _KSYN_TRACE_
-			set_enable(2);
-#endif /* _KSYN_TRACE_ */
-			(void)pthread_threadid_np(pthread_self(), &myid);
-			LIBC_ABORT("upgrade from kernel without EBit  %x: tid %x\n", updateval, (uint32_t)myid);
-		}
-#if __DARWIN_UNIX03
 		rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
+		PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
 		return(0);
-	} else {
-		if (trylock != 0) {
-			return (EBUSY);
-		}
-	}
-
-	return(error);	
+	}
+	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)
 {
-	uint32_t lcntval, ucntval, rw_seq;
+	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+	uint32_t lgenval, ugenval;
 	int error = 0;
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
+	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				return(0);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
+		} else {
 			return(-1);
 		}
-		UNLOCK(rwlock->lock);
 	}
 	
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-	
-	if ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK))
+		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);
@@ -995,886 +1592,1018 @@
 int 
 pthread_rwlock_rdheld_np(pthread_rwlock_t * orwlock)
 {
-	uint32_t lcntval, ucntval, rw_seq;
+	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
+	uint32_t lgenval;
 	int error = 0;
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
 	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				return(0);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
+		} else {
 			return(-1);
 		}
-		UNLOCK(rwlock->lock);
-	}
-	
-
+	}
+	
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-
-	if ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK))
+		lseqaddr = rwlock->rw_lseqaddr;
+		useqaddr = rwlock->rw_useqaddr;
+		wcaddr = rwlock->rw_wcaddr;
+	}
+
+	lgenval = *lseqaddr;
+	
+	if (is_rw_ebit_set(lgenval)) {
 		return(0);
-
-	if (is_rwl_ebit_set(lcntval) !=0) {
-		return(0);
-	}
-	return(1);
+	}
+	return(0);
 }
 
 /* Returns true if the rwlock is held for writing by the current thread */
 int 
 pthread_rwlock_wrheld_np(pthread_rwlock_t * orwlock)
 {
-	uint32_t lcntval, ucntval, rw_seq;
-	pthread_t self = pthread_self();
 	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
+	pthread_t self;
+	uint32_t lgenval;
 	int error = 0;
+	volatile uint32_t * lseqaddr, *useqaddr, *wcaddr;
 	
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
 		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
+		 	if ((error = pthread_rwlock_init(orwlock, NULL)) != 0)  {
 				return(0);
 			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
+		} else {
 			return(-1);
 		}
-		UNLOCK(rwlock->lock);
 	}
 	
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		RWLOCK_GETSEQ_ADDR(rwlock, lseqaddr, useqaddr, wcaddr);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-
-	if ((is_rwl_ebit_set(lcntval)) && (rwlock->rw_owner == self)) {
+		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 *orwlock)
-{
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-#if __DARWIN_UNIX03
-	uint32_t rw_lcnt, rw_ucnt;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-#endif /* __DARWIN_UNIX03 */
-	
-	if (rwlock->sig != _PTHREAD_RWLOCK_SIG && rwlock->sig != _PTHREAD_RWLOCK_SIG_init)
+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 (rwlock->sig == _PTHREAD_RWLOCK_SIG) {
-#if __DARWIN_UNIX03
-		if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-			RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-		} else {
-			lcntaddr = rwlock->rw_lcntaddr;
-			ucntaddr = rwlock->rw_ucntaddr;
-			seqaddr = rwlock->rw_seqaddr;
-		}
-
-		rw_lcnt = *lcntaddr;
-		rw_ucnt = *ucntaddr;
-		
-		if((rw_lcnt & PTHRW_COUNT_MASK) != rw_ucnt)
-			return(EBUSY);
-		
-#endif /* __DARWIN_UNIX03 */
-		//bzero(rwlock, sizeof(npthread_rwlock_t));
+	} 
+#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)
+        return(ret);
+
+    	if (rwlock->state != 0) {
+        	pthread_mutex_unlock(&rwlock->lock);
+        	return(EBUSY);
+    	}
+		pthread_mutex_unlock(&rwlock->lock);
+#endif /* __DARWIN_UNIX03 */
+
+		pthread_mutex_destroy(&rwlock->lock);
+		pthread_cond_destroy(&rwlock->read_signal);
+		pthread_cond_destroy(&rwlock->write_signal);
 		rwlock->sig = _PTHREAD_NO_SIG;
 		return(0);
-	} else if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		rwlock->sig = _PTHREAD_NO_SIG;
-                return(0);
-	} else 
+	}
+}
+
+int
+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);
+		}
+#endif /* __DARWIN_UNIX03 */
+
+	/* initialize the lock */
+	if ((ret = pthread_mutex_init(&rwlock->lock, NULL)) != 0)
+		return(ret);
+	else {
+		/* initialize the read condition signal */
+		ret = pthread_cond_init(&rwlock->read_signal, NULL);
+
+		if (ret != 0) {
+			pthread_mutex_destroy(&rwlock->lock);
+			return(ret);
+		} else {
+			/* initialize the write condition signal */
+			ret = pthread_cond_init(&rwlock->write_signal, NULL);
+
+			if (ret != 0) {
+				pthread_cond_destroy(&rwlock->read_signal);
+				pthread_mutex_destroy(&rwlock->lock);
+				return(ret);
+			} else {
+				/* success */
+				rwlock->state = 0;
+				rwlock->owner = (pthread_t)0;
+				rwlock->blocked_writers = 0;
+				if (attr)
+					rwlock->pshared = attr->pshared;
+				else
+					rwlock->pshared = _PTHREAD_DEFAULT_PSHARED;
+					
+				rwlock->sig = _PTHREAD_RWLOCK_SIG;
+				return(0);
+			}
+		}
+	}
+}
+
+int
+pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
+{
+	int			ret;
+#if __DARWIN_UNIX03
+	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);
+			return(ret);
+		}
+	}
+
+	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+		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);    
+		return(ret);
+	}
+
+#if __DARWIN_UNIX03
+	if ((rwlock->state < 0) && (rwlock->owner == self)) {
+		pthread_mutex_unlock(&rwlock->lock);
+		PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EDEADLK);    
+		return(EDEADLK);
+	}
+#endif /* __DARWIN_UNIX03 */
+
+#if __DARWIN_UNIX03
+	while (rwlock->blocked_writers || ((rwlock->state < 0) && (rwlock->owner != self))) 
+#else /* __DARWIN_UNIX03 */
+	while (rwlock->blocked_writers || rwlock->state < 0) 
+
+#endif /* __DARWIN_UNIX03 */
+	{
+	/* give writers priority over readers */
+		PLOCKSTAT_RW_BLOCK(rwlock, READ_LOCK_PLOCKSTAT);
+		ret = pthread_cond_wait(&rwlock->read_signal, &rwlock->lock);
+
+		if (ret != 0) {
+			/* can't do a whole lot if this fails */
+			pthread_mutex_unlock(&rwlock->lock);
+			PLOCKSTAT_RW_BLOCKED(rwlock, READ_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
+			PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);    
+			return(ret);
+		}
+
+		PLOCKSTAT_RW_BLOCKED(rwlock, READ_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
+	}
+
+	/* check lock count */
+	if (rwlock->state == MAX_READ_LOCKS) {
+		ret = EAGAIN;
+		PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);    
+	}
+	else {
+		++rwlock->state; /* indicate we are locked for reading */
+		PLOCKSTAT_RW_ACQUIRE(rwlock, READ_LOCK_PLOCKSTAT);    
+	}
+
+	/*
+	 * Something is really wrong if this call fails.  Returning
+	 * error won't do because we've already obtained the read
+	 * lock.  Decrementing 'state' is no good because we probably
+	 * don't have the monitor lock.
+	 */
+	pthread_mutex_unlock(&rwlock->lock);
+
+	return(ret);
+}
 
 int
-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_lcnt, rw_ucnt;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-#endif /* __DARWIN_UNIX03 */
-	
-#if __DARWIN_UNIX03
-	if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) {
+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__ */
+
+	/* check for static initialization */
+	if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
+		if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0)  {
+			PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);    
+			return(ret);
+		}
+	}
+
+	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
+		PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL);    
 		return(EINVAL);
 	}
-	
-	if (rwlock->sig == _PTHREAD_RWLOCK_SIG) {
-		if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-			RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-		} else {
-			lcntaddr = rwlock->rw_lcntaddr;
-			ucntaddr = rwlock->rw_ucntaddr;
-			seqaddr = rwlock->rw_seqaddr;
-		}
-		
-		rw_lcnt = *lcntaddr;
-		rw_ucnt = *ucntaddr;
-		
-		if ((rw_lcnt & PTHRW_COUNT_MASK) != rw_ucnt)
-			return(EBUSY);
-		
-	}
-#endif
-	LOCK_INIT(rwlock->lock);
-	return(__pthread_rwlock_init(orwlock, attr));
-	
+#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);    
+		return(ret);
+	}
+
+	/* give writers priority over readers */
+	if (rwlock->blocked_writers || rwlock->state < 0) {
+		ret = EBUSY;
+		PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);    
+	}
+	else if (rwlock->state == MAX_READ_LOCKS) {
+		ret = EAGAIN; /* too many read locks acquired */
+		PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret);    
+	}
+	else {
+		++rwlock->state; /* indicate we are locked for reading */
+		PLOCKSTAT_RW_ACQUIRE(rwlock, READ_LOCK_PLOCKSTAT);    
+	}
+
+	/* see the comment on this in pthread_rwlock_rdlock */
+	pthread_mutex_unlock(&rwlock->lock);
+
+	return(ret);
 }
 
 int
-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 lcntval, ucntval, rw_seq, newval, newsval, updateval;
-	int error = 0, retry_count = 0;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
-	
+pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
+{
+	int			ret;
+#if __DARWIN_UNIX03
+	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)  {
+			PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);    
+			return(ret);
+		}
+	}
+
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
-		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
-				PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
-				return(error);
-			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
-			PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
-			return(EINVAL);
-		}
-		UNLOCK(rwlock->lock);
-	}
-	
+		PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);    
+		return(EINVAL);
+	}
+
+#if  defined(__i386__) || defined(__x86_64__)
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
+		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);    
+		return(ret);
+	}
+
+
+	if (rwlock->state != 0) {
+		ret = EBUSY;
+		PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);    
+	}
+	else {
+		/* indicate we are locked for writing */
+		rwlock->state = -1;
+#if __DARWIN_UNIX03
+		rwlock->owner = self;
+#endif /* __DARWIN_UNIX03 */
+		PLOCKSTAT_RW_ACQUIRE(rwlock, WRITE_LOCK_PLOCKSTAT);    
+	}
+
+	/* see the comment on this in pthread_rwlock_rdlock */
+	pthread_mutex_unlock(&rwlock->lock);
+
+	return(ret);
+}
+
+int
+pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+{
+	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 (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);    
+		return(ret);
+	}
+
+	if (rwlock->state > 0) {
+		if (--rwlock->state == 0 && rwlock->blocked_writers)
+			ret = pthread_cond_signal(&rwlock->write_signal);
+	} else if (rwlock->state < 0) {
+		rwlock->state = 0;
+#if __DARWIN_UNIX03
+		rwlock->owner = (pthread_t)0;
+#endif /* __DARWIN_UNIX03 */
+
+		if (rwlock->blocked_writers)
+			ret = pthread_cond_signal(&rwlock->write_signal);
+		else
+			ret = pthread_cond_broadcast(&rwlock->read_signal);
+	} else
+		ret = EINVAL;
+
+	if (ret == 0) {
+		PLOCKSTAT_RW_RELEASE(rwlock, writer);
 	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lcntval, (ucntval | 0xee), rw_seq, 0);
-#endif
-	
-	/* if l bit is on or u and k bit is clear, acquire lock in userland */
-	if (can_rwl_readinuser(lcntval))
-		goto gotlock;
-	
-#if __DARWIN_UNIX03
-	if (is_rwl_ebit_set(lcntval)) {
-		self = pthread_self();
-		if(rwlock->rw_owner == self) {
-			error = EDEADLK;
-			goto out;
-		}
-	}
-#endif /* __DARWIN_UNIX03 */
-	
-
-	/* Need to block in kernel , remove Rbit */
-	newval  = (lcntval + PTHRW_INC) & PTH_RWLOCK_RESET_RBIT;
-	
-	newsval = rw_seq;
-	if (is_rws_setseq(rw_seq)) {
-		newsval &= PTHRW_SW_Reset_BIT_MASK;
-		newsval |= (newval & PTHRW_COUNT_MASK);
-	}
-
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	newval64 = (((uint64_t)newsval) << 32);
-	newval64 |= newval;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-		goto loop;
-
-	/* give writers priority over readers */
-	PLOCKSTAT_RW_BLOCK(orwlock, READ_LOCK_PLOCKSTAT);
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lcntval, newval, newsval, 0);
-#endif
-
-retry:
-	updateval = __psynch_rw_rdlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
-	
-	if (updateval == (uint32_t)-1) {
-		error = errno;
-	} else
-		error = 0;
-	
-	if (error == EINTR)
-		goto retry;
-
-	if (error == 0)  {
-		rwlock_action_onreturn(orwlock, updateval);
-		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);
-#if _KSYN_TRACE_
-		set_enable(1);
-#endif /* _KSYN_TRACE_ */
-		(void)pthread_threadid_np(pthread_self(), &myid);
-		LIBC_ABORT("rdlock from kernel with unknown error %x with tid %x\n", updateval, (uint32_t)myid);
-		goto out;
-	}
-	/* Not reached */	
-	
-gotlock:
-	if (rw_diffgenseq(lcntval, ucntval) >= PTHRW_MAX_READERS) {
-		/* since ucntval may be newer, just redo */
-		retry_count++;
-		if (retry_count > 1024) {
-		
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TOOMANY | DBG_FUNC_NONE, (uint32_t)rwlock, 0XEEEEEEEE, lcntval, ucntval, 0);
-#endif
-			error = EAGAIN;
-			goto out;
-		} else {
-			sched_yield();
-			goto loop;
-		}
-	}
-	
-	/* Need to update L (remove R bit) and S word */
-	newval  = (lcntval + PTHRW_INC)  & PTH_RWLOCK_RESET_RBIT;
-	newsval = (rw_seq + PTHRW_INC);
-
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	newval64 = (((uint64_t)newsval) << 32);
-	newval64 |= newval;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-		goto loop;
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lcntval, newval, 0);
-#endif
-	
-	PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, 0, 0, 0);
-#endif
-	return(0);
-out:
-	PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);    
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_RDLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
-	return(error);
+		PLOCKSTAT_RW_ERROR(rwlock, writer, ret);
+	}
+
+	/* see the comment on this in pthread_rwlock_rdlock */
+	pthread_mutex_unlock(&rwlock->lock);
+
+	return(ret);
 }
 
 int
-pthread_rwlock_tryrdlock(pthread_rwlock_t * orwlock)
-{
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval;
-	int error = 0, retry_count = 0;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	
+pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
+{
+	int			ret;
+#if __DARWIN_UNIX03
+	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)  {
+			PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
+			return(ret);
+		}
+	}
+
 	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
-		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
-				PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);
-				return(error);
-			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
-			PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, EINVAL);
-			return(EINVAL);
-		}
-		UNLOCK(rwlock->lock);
-	}
-	
+		PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
+		return(EINVAL);
+	}
+
+#if  defined(__i386__) || defined(__x86_64__)
 	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TRYRDLOCK | DBG_FUNC_START, (uint32_t)rwlock, lcntval, ucntval, rw_seq, 0);
-#endif
-
-	/* if l bit is on or u and k bit is clear, acquire lock in userland */
-	if (can_rwl_readinuser(lcntval))
-		goto gotlock;
-	
-	error = EBUSY;
-	goto out;
-	
-gotlock:
-	if (rw_diffgenseq(lcntval, ucntval) >= PTHRW_MAX_READERS) {
-		/* since ucntval may be newer, just redo */
-		retry_count++;
-		if (retry_count > 1024) {
-		
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TOOMANY | DBG_FUNC_NONE, (uint32_t)rwlock, 0XEEEEEEEE, lcntval, ucntval, 0);
-#endif
-			error = EAGAIN;
-			goto out;
-		} else {
-			sched_yield();
-			goto loop;
-		}
-	}
-	
-	/* Need to update L(remove Rbit ) and S word */
-	newval  = (lcntval + PTHRW_INC) & PTH_RWLOCK_RESET_RBIT;
-	newsval = (rw_seq + PTHRW_INC);
-
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	newval64 = (((uint64_t)newsval) << 32);
-	newval64 |= newval;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-		goto loop;
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TRYRDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lcntval, newval, 0);
-#endif
-	
-	PLOCKSTAT_RW_ACQUIRE(orwlock, READ_LOCK_PLOCKSTAT);
-	return(0);
-
-out:
-	PLOCKSTAT_RW_ERROR(orwlock, READ_LOCK_PLOCKSTAT, error);    
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TRYRDLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, error, 0, 0);
-#endif
-	return(error);
-}
-
-int
-pthread_rwlock_trywrlock(pthread_rwlock_t * orwlock)
-{
-#if __DARWIN_UNIX03
-	pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	uint32_t lcntval, rw_seq, newval, newsval;
-	int error = 0, gotlock = 0;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	
-	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
-		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
-				PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
-				return(error);
-			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
-			PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
-			return(EINVAL);
-		}
-		UNLOCK(rwlock->lock);
-	}
-	
-	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TRYWRLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
-	lcntval = *lcntaddr;
-	rw_seq = *seqaddr;
-
-	/* can we acquire in userland? */
-	if ((lcntval & PTH_RWL_RBIT) != 0) {
-		newval  = ((lcntval + PTHRW_INC) & PTHRW_COUNT_MASK) | PTH_RWL_IBIT | PTH_RWL_KBIT| PTH_RWL_EBIT;
-		newsval = rw_seq + PTHRW_INC;
-		gotlock = 1;
-	} else
-		gotlock = 0;
-
-
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	if (gotlock != 0) {
-		newval64 = (((uint64_t)newsval) << 32);
-		newval64 |= newval;
-	} else 
-		newval64 = oldval64;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE) {
-		goto loop;
-	}
-	if (gotlock == 1) {
-#if __DARWIN_UNIX03
-		rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
-		PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TRYWRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-		return(0);
-	} else {
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_TRYWRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, EBUSY, 0, 0);
-#endif
-
-		PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EBUSY);    
-		return(EBUSY);
-	}
-}
-
-int
-pthread_rwlock_wrlock(pthread_rwlock_t * orwlock)
-{
-#if __DARWIN_UNIX03
-	pthread_t self = pthread_self();
-#endif /* __DARWIN_UNIX03 */
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval;
-	int error = 0, gotlock = 0;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
-	
-	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
-		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
-				PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);
-				return(error);
-			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
-			PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, EINVAL);
-			return(EINVAL);
-		}
-		UNLOCK(rwlock->lock);
-	}
-	
-	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, lcntval, ucntval, rw_seq, 0);
-#endif
-
-#if __DARWIN_UNIX03
-	if (is_rwl_ebit_set(lcntval)) {
-		if(rwlock->rw_owner == self) {
-			error = EDEADLK;
-			goto out;
-		}
-	}
-#endif /* __DARWIN_UNIX03 */
-
-	
-	if ((lcntval & PTH_RWL_RBIT) != 0) {
-		/* lock is restart state, writer can acquire the lock */
-		newval  = ((lcntval + PTHRW_INC) & PTHRW_COUNT_MASK) | PTH_RWL_IBIT | PTH_RWL_KBIT| PTH_RWL_EBIT;
-
-		newsval = rw_seq + PTHRW_INC;
-		gotlock = 1;
-
-	} else {
-		if (is_rwl_lbit_set(lcntval))
-			newval = (lcntval + PTHRW_INC)| PTH_RWL_WBIT;	
-		else
-			newval = (lcntval + PTHRW_INC) | PTH_RWL_KBIT| PTH_RWL_WBIT;	
-
-		newsval = rw_seq;
-		if (is_rws_setseq(rw_seq)) {
-			newsval &= PTHRW_SW_Reset_BIT_MASK;
-			newsval |= (newval & PTHRW_COUNT_MASK);
-		}
-		gotlock = 0;
-	}
-
-	/* update lock seq */
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	newval64 = (((uint64_t)newsval) << 32);
-	newval64 |= newval;
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555555, lcntval, newval, 0);
-#endif
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-		goto loop;
-		
-	/* lock acquired in userland itself? */
-	if (gotlock != 0)
-		goto gotit;
-
-	/* unable to acquire in userland, transition to kernel */
-
-	PLOCKSTAT_RW_BLOCK(orwlock, WRITE_LOCK_PLOCKSTAT);
-retry:
-	updateval = __psynch_rw_wrlock(orwlock, newval, ucntval, newsval, rwlock->rw_flags);
-	if (updateval == (uint32_t)-1) {
-		error = errno;
-	} else
-		error = 0;
-	
-	if (error == EINTR) {
-		goto retry;
-	} 
-
-	if (error != 0) {
-#if _KSYN_TRACE_
-		set_enable(2);
-#endif /* _KSYN_TRACE_ */
-		(void)pthread_threadid_np(pthread_self(), &myid);
-		LIBC_ABORT("wrlock from kernel with unknown error %x: tid %x\n", updateval, (uint32_t)myid);
-	}
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(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) {
-		rwlock_action_onreturn(orwlock, updateval);
-gotit:
-#if __DARWIN_UNIX03
-		rwlock->rw_owner = self;
-#endif /* __DARWIN_UNIX03 */
-		PLOCKSTAT_RW_ACQUIRE(orwlock, WRITE_LOCK_PLOCKSTAT);
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
-		return(0);
-	} 
-#if __DARWIN_UNIX03
-out:
-#endif /* __DARWIN_UNIX03 */
-	PLOCKSTAT_RW_ERROR(orwlock, WRITE_LOCK_PLOCKSTAT, error);    
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_WRLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
-	return(error);
-}
-
-
-int
-pthread_rwlock_unlock(pthread_rwlock_t * orwlock)
-{
-	npthread_rwlock_t * rwlock = (npthread_rwlock_t *)orwlock;
-	uint32_t lcntval, ucntval, rw_seq, newval, newsval, updateval, ulval;
-	int error = 0, wrlock = 0, haswbit = 0, hasubit = 0, hasybit = 0;
-	uint64_t oldval64, newval64;
-	volatile uint32_t * lcntaddr, *ucntaddr, *seqaddr;
-	uint64_t myid = 0;
-	
-	if (rwlock->sig != _PTHREAD_RWLOCK_SIG) {
-		LOCK(rwlock->lock);
-		if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) {
-		 	if ((error = __pthread_rwlock_init(orwlock, NULL)) != 0)  {
-				UNLOCK(rwlock->lock);
-				PLOCKSTAT_RW_ERROR(orwlock, wrlock, error);
-				return(error);
-			}
-		} else if (rwlock->sig != _PTHREAD_RWLOCK_SIG){
-			UNLOCK(rwlock->lock);
-			PLOCKSTAT_RW_ERROR(orwlock, wrlock, EINVAL);
-			return(EINVAL);
-		}
-		UNLOCK(rwlock->lock);
-	}
-	
-	if (rwlock->pshared == PTHREAD_PROCESS_SHARED) {
-		RWLOCK_GETSEQ_ADDR(rwlock, lcntaddr, ucntaddr, seqaddr);
-	} else {
-		lcntaddr = rwlock->rw_lcntaddr;
-		ucntaddr = rwlock->rw_ucntaddr;
-		seqaddr = rwlock->rw_seqaddr;
-	}
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_START, (uint32_t)rwlock, 0, 0, 0, 0);
-#endif
-loop:
-	lcntval = *lcntaddr;
-	ucntval = *ucntaddr;
-	rw_seq = *seqaddr;
-	
-
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x51515151, lcntval, ucntval, 0);
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x51515151, rw_seq, 0, 0);
-#endif
-	/* check for spurious unlocks */
-	if ((lcntval & PTH_RWL_RBIT) != 0) {
-		newval  = lcntval ;
-		newsval = rw_seq;
-
-		oldval64 = (((uint64_t)rw_seq) << 32);
-		oldval64 |= lcntval;
-	
-		newval64 = (((uint64_t)newsval) << 32);
-		newval64 |= newval;
-	
-		if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) == TRUE) {
-			/* spurious unlock, return */
-			error = EINVAL;
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x1a1b1c1d, lcntval, ucntval, 0);
-#endif
-			goto succout;
-		} else
-			goto loop;
-	}
-
-	if (is_rwl_ebit_set(lcntval)) {
-		wrlock = 1;
-#if __DARWIN_UNIX03
-		rwlock->rw_owner = (pthread_t)0;
-#endif /* __DARWIN_UNIX03 */
-	}
-	
-	/* update U */
-	
-	ulval = (ucntval + PTHRW_INC);
-
-	if (OSAtomicCompareAndSwap32(ucntval, ulval, (volatile int32_t *)ucntaddr) != TRUE)
-		goto loop;
-	
-lp11:
-	/* just validate the l and S values */
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-
-	newval64 = oldval64;
-
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)  {
-		lcntval = *lcntaddr;
-		rw_seq = *seqaddr;
-		goto lp11;
-	}
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xd1d2d3d4, lcntval, rw_seq, 0);
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xd1d2d3d4, ulval, 0, 0);
-#endif
-
-	/* last unlock, note U is already updated ? */
-	if((lcntval & PTHRW_COUNT_MASK) == (ulval & PTHRW_COUNT_MASK)) {
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xbbbbbbbb, lcntval, ucntval, 0);
-#endif
-		/* Set L with R and init bits and set S to L */
-		newval  = (lcntval & PTHRW_COUNT_MASK)| PTHRW_RWLOCK_INIT;
-		newsval = (lcntval & PTHRW_COUNT_MASK)| PTHRW_RWS_INIT;
-
-		oldval64 = (((uint64_t)rw_seq) << 32);
-		oldval64 |= lcntval;
-
-		newval64 = (((uint64_t)newsval) << 32);
-		newval64 |= newval;
-
-		if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)  {
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xcccccccc, 0, 0, 0);
-#endif
-			lcntval = *lcntaddr;
-			rw_seq = *seqaddr;
-			goto lp11;
-		}
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0xdddddddd, lcntval, ucntval, 0);
-#endif
-		goto succout;
-	}
-
-	/* if it is not exclusive or no Writer/yield pending, skip */
-	if ((lcntval & (PTH_RWL_EBIT | PTH_RWL_WBIT | PTH_RWL_YBIT | PTH_RWL_KBIT)) == 0) {
-		goto succout;
-	}
-
-	/* kernel transition needed? */
-	/* U+1 == S? */
-	if ((ulval + PTHRW_INC) != (rw_seq & PTHRW_COUNT_MASK)) {
-		if ((lcntval & PTH_RWL_UBIT) != 0) {
-			/* if U bit is set U + 2 == S ? */
-			if ((ulval + PTHRW_INC + PTHRW_INC) != (rw_seq & PTHRW_COUNT_MASK))
-				goto succout;
-		} else 
-			goto succout;
-	}
-
-	haswbit = lcntval & PTH_RWL_WBIT;
-	hasubit = lcntval & PTH_RWL_UBIT;
-	hasybit = lcntval & PTH_RWL_YBIT;
-
-	/* reset all bits and set k */
-	newval = (lcntval & PTHRW_COUNT_MASK) | PTH_RWL_KBIT;
-	/* set I bit on S word */	
-	newsval = rw_seq | PTH_RWS_IBIT;
-	if (haswbit != 0)
-		newsval |= PTH_RWS_WSVBIT;
-	if (hasubit != 0)
-		newsval |= PTH_RWS_USVBIT;
-	if (hasybit != 0)
-		newsval |= PTH_RWS_YSVBIT;
-
-	oldval64 = (((uint64_t)rw_seq) << 32);
-	oldval64 |= lcntval;
-	
-	newval64 = (((uint64_t)newsval) << 32);
-	newval64 |= newval;
-	
-	if (OSAtomicCompareAndSwap64(oldval64, newval64, (volatile int64_t *)lcntaddr) != TRUE)
-		goto lp11;
-
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555511, 1, ulval, 0);
-#endif
-	updateval = __psynch_rw_unlock(orwlock, lcntval, ulval, newsval, 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) {
-#if _KSYN_TRACE_
-		set_enable(4);
-#endif /* _KSYN_TRACE_ */
-			(void)pthread_threadid_np(pthread_self(), &myid);
-			LIBC_ABORT("rwunlock from kernel with unknown error %x: tid %x\n", error, (uint32_t)myid);
-			goto succout;
-		}
-		error = 0;
-	}
-	
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_NONE, (uint32_t)rwlock, 0x55555522, 3, lcntval, 0);
-#endif
-
-succout:
-	PLOCKSTAT_RW_RELEASE(orwlock, wrlock);
-#if _KSYN_TRACE_
-	if (__pthread_lock_debug != 0)
-	(void)__kdebug_trace(_KSYN_TRACE_RW_UNLOCK | DBG_FUNC_END, (uint32_t)rwlock, 0xAAAAAAAA, error, 0, 0);
-#endif
-	return(0);
-}
-
+		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)) {
+		pthread_mutex_unlock(&rwlock->lock);
+		PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EDEADLK);
+		return(EDEADLK);
+	}
+#endif /* __DARWIN_UNIX03 */
+	while (rwlock->state != 0) {
+		++rwlock->blocked_writers;
+
+		PLOCKSTAT_RW_BLOCK(rwlock, WRITE_LOCK_PLOCKSTAT);
+		ret = pthread_cond_wait(&rwlock->write_signal, &rwlock->lock);
+
+		if (ret != 0) {
+			--rwlock->blocked_writers;
+			pthread_mutex_unlock(&rwlock->lock);
+			PLOCKSTAT_RW_BLOCKED(rwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT);
+			PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret);
+			return(ret);
+		}
+
+		PLOCKSTAT_RW_BLOCKED(rwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT);
+
+		--rwlock->blocked_writers;
+	}
+
+	/* indicate we are locked for writing */
+	rwlock->state = -1;
+#if __DARWIN_UNIX03
+	rwlock->owner = self;
+#endif /* __DARWIN_UNIX03 */
+	PLOCKSTAT_RW_ACQUIRE(rwlock, WRITE_LOCK_PLOCKSTAT);
+
+	/* see the comment on this in pthread_rwlock_rdlock */
+	pthread_mutex_unlock(&rwlock->lock);
+
+	return(ret);
+}
+