FreeBSD/sys/kern/kern_rwlock.c
/*
 * Attempt to do a non-blocking upgrade from a read lock to a write
 * lock.  This will only succeed if this thread holds a single read
 * lock.  Returns true if the upgrade succeeded and false otherwise.
 */
Attempt to do a non-blocking upgrade from a read lock to a write
lock.  This will only succeed if this thread holds a single read
lock.  Returns true if the upgrade succeeded and false otherwise.
Attempt to do a non - blocking upgrade from a read lock to a write lock . This will only succeed if this thread holds a single read lock . Returns true if the upgrade succeeded and false otherwise .
int
__rw_try_upgrade(volatile uintptr_t *c, const char *file, int line)
{
	struct rwlock *rw;
	uintptr_t v, x, tid;
	struct turnstile *ts;
	int success;
	if (SCHEDULER_STOPPED())
		return (1);
	rw = rwlock2rw(c);
	KASSERT(rw->rw_lock != RW_DESTROYED,
	    ("rw_try_upgrade() of destroyed rwlock @ %s:%d", file, line));
	__rw_assert(c, RA_RLOCKED, file, line);
	tid = (uintptr_t)curthread;
	success = 0;
	for (;;) {
		v = rw->rw_lock;
		if (RW_READERS(v) > 1)
			break;
		if (!(v & RW_LOCK_WAITERS)) {
			success = atomic_cmpset_ptr(&rw->rw_lock, v, tid);
			if (!success)
				continue;
			break;
		}
		ts = turnstile_trywait(&rw->lock_object);
		v = rw->rw_lock;
		if (RW_READERS(v) > 1) {
			turnstile_cancel(ts);
			break;
		}
		x = rw->rw_lock & RW_LOCK_WAITERS;
		success = atomic_cmpset_ptr(&rw->rw_lock, v, tid | x);
		if (success) {
			if (x)
				turnstile_claim(ts);
			else
				turnstile_cancel(ts);
			break;
		}
		turnstile_cancel(ts);
	}
	LOCK_LOG_TRY("WUPGRADE", &rw->lock_object, 0, success, file, line);
	if (success) {
		curthread->td_rw_rlocks--;
		WITNESS_UPGRADE(&rw->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
		    file, line);
		LOCKSTAT_RECORD0(rw__upgrade, rw);
	}
	return (success);
}
int __rw_try_upgrade ( volatile uintptr_t * c , const char * file , int line ) { struct rwlock * rw ; uintptr_t v , x , tid ; struct turnstile * ts ; int success ; if ( SCHEDULER_STOPPED ( ) ) return ( 1 ) ; rw = rwlock2rw ( c ) ; KASSERT ( rw -> rw_lock != RW_DESTROYED , ( " " , file , line ) ) ; __rw_assert ( c , RA_RLOCKED , file , line ) ; tid = ( uintptr_t ) curthread ; success = 0 ; for ( ; ; ) { v = rw -> rw_lock ; if ( RW_READERS ( v ) > 1 ) break ; if ( ! ( v & RW_LOCK_WAITERS ) ) { success = atomic_cmpset_ptr ( & rw -> rw_lock , v , tid ) ; if ( ! success ) continue ; break ; } ts = turnstile_trywait ( & rw -> lock_object ) ; v = rw -> rw_lock ; if ( RW_READERS ( v ) > 1 ) { turnstile_cancel ( ts ) ; break ; } x = rw -> rw_lock & RW_LOCK_WAITERS ; success = atomic_cmpset_ptr ( & rw -> rw_lock , v , tid | x ) ; if ( success ) { if ( x ) turnstile_claim ( ts ) ; else turnstile_cancel ( ts ) ; break ; } turnstile_cancel ( ts ) ; } LOCK_LOG_TRY ( " " , & rw -> lock_object , 0 , success , file , line ) ; if ( success ) { curthread -> td_rw_rlocks -- ; WITNESS_UPGRADE ( & rw -> lock_object , LOP_EXCLUSIVE | LOP_TRYLOCK , file , line ) ; LOCKSTAT_RECORD0 ( rw__upgrade , rw ) ; } return ( success ) ; }
Attempt to do a non-blocking upgrade from a read lock to a write
 lock.
Attempt to do a non - blocking upgrade from a read lock to a write lock .
/*
	 * Attempt to switch from one reader to a writer.  If there
	 * are any write waiters, then we will have to lock the
	 * turnstile first to prevent races with another writer
	 * calling turnstile_wait() before we have claimed this
	 * turnstile.  So, do the simple case of no waiters first.
	 */ /*
		 * Ok, we think we have waiters, so lock the turnstile.
		 */ /*
		 * Try to switch from one reader to a writer again.  This time
		 * we honor the current state of the waiters flags.
		 * If we obtain the lock with the flags set, then claim
		 * ownership of the turnstile.
		 */