FreeBSD/sys/kern/kern_sx.c
/*
 * This function represents the so-called 'hard case' for sx_sunlock
 * operation.  All 'easy case' failures are redirected to this.  Note
 * that ideally this would be a static function, but it needs to be
 * accessible from at least sx.h.
 */
This function represents the so-called 'hard case' for sx_sunlock
operation.  All 'easy case' failures are redirected to this.  Note
that ideally this would be a static function, but it needs to be
accessible from at least sx.h.
This function represents the so - called ' hard case ' for sx_sunlock operation . All ' easy case ' failures are redirected to this . Note that ideally this would be a static function but it needs to be accessible from at least sx . h .
void
_sx_sunlock_hard(struct sx *sx, const char *file, int line)
{
	uintptr_t x;
	int wakeup_swapper;
	if (SCHEDULER_STOPPED())
		return;
	for (;;) {
		x = sx->sx_lock;
		KASSERT(!(x & SX_LOCK_SHARED_WAITERS),
		    ("%s: waiting sharers", __func__));
		if (SX_SHARERS(x) > 1) {
			if (atomic_cmpset_rel_ptr(&sx->sx_lock, x,
			    x - SX_ONE_SHARER)) {
				if (LOCK_LOG_TEST(&sx->lock_object, 0))
					CTR4(KTR_LOCK,
					    "%s: %p succeeded %p -> %p",
					    __func__, sx, (void *)x,
					    (void *)(x - SX_ONE_SHARER));
				break;
			}
			continue;
		}
		if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) {
			MPASS(x == SX_SHARERS_LOCK(1));
			if (atomic_cmpset_rel_ptr(&sx->sx_lock,
			    SX_SHARERS_LOCK(1), SX_LOCK_UNLOCKED)) {
				if (LOCK_LOG_TEST(&sx->lock_object, 0))
					CTR2(KTR_LOCK, "%s: %p last succeeded",
					    __func__, sx);
				break;
			}
			continue;
		}
		MPASS(x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS));
		sleepq_lock(&sx->lock_object);
		if (!atomic_cmpset_rel_ptr(&sx->sx_lock,
		    SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS,
		    SX_LOCK_UNLOCKED)) {
			sleepq_release(&sx->lock_object);
			continue;
		}
		if (LOCK_LOG_TEST(&sx->lock_object, 0))
			CTR2(KTR_LOCK, "%s: %p waking up all thread on"
			    "exclusive queue", __func__, sx);
		wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX,
		    0, SQ_EXCLUSIVE_QUEUE);
		sleepq_release(&sx->lock_object);
		if (wakeup_swapper)
			kick_proc0();
		break;
	}
}
void _sx_sunlock_hard ( struct sx * sx , const char * file , int line ) { uintptr_t x ; int wakeup_swapper ; if ( SCHEDULER_STOPPED ( ) ) return ; for ( ; ; ) { x = sx -> sx_lock ; KASSERT ( ! ( x & SX_LOCK_SHARED_WAITERS ) , ( " " , __func__ ) ) ; if ( SX_SHARERS ( x ) > 1 ) { if ( atomic_cmpset_rel_ptr ( & sx -> sx_lock , x , x - SX_ONE_SHARER ) ) { if ( LOCK_LOG_TEST ( & sx -> lock_object , 0 ) ) CTR4 ( KTR_LOCK , " " , __func__ , sx , ( void * ) x , ( void * ) ( x - SX_ONE_SHARER ) ) ; break ; } continue ; } if ( ! ( x & SX_LOCK_EXCLUSIVE_WAITERS ) ) { MPASS ( x == SX_SHARERS_LOCK ( 1 ) ) ; if ( atomic_cmpset_rel_ptr ( & sx -> sx_lock , SX_SHARERS_LOCK ( 1 ) , SX_LOCK_UNLOCKED ) ) { if ( LOCK_LOG_TEST ( & sx -> lock_object , 0 ) ) CTR2 ( KTR_LOCK , " " , __func__ , sx ) ; break ; } continue ; } MPASS ( x == ( SX_SHARERS_LOCK ( 1 ) | SX_LOCK_EXCLUSIVE_WAITERS ) ) ; sleepq_lock ( & sx -> lock_object ) ; if ( ! atomic_cmpset_rel_ptr ( & sx -> sx_lock , SX_SHARERS_LOCK ( 1 ) | SX_LOCK_EXCLUSIVE_WAITERS , SX_LOCK_UNLOCKED ) ) { sleepq_release ( & sx -> lock_object ) ; continue ; } if ( LOCK_LOG_TEST ( & sx -> lock_object , 0 ) ) CTR2 ( KTR_LOCK , " " " " , __func__ , sx ) ; wakeup_swapper = sleepq_broadcast ( & sx -> lock_object , SLEEPQ_SX , 0 , SQ_EXCLUSIVE_QUEUE ) ; sleepq_release ( & sx -> lock_object ) ; if ( wakeup_swapper ) kick_proc0 ( ) ; break ; } }
This function represents the so-called 'hard case' for sx_sunlock
 operation.
This function represents the so - called ' hard case ' for sx_sunlock operation .
/*
		 * We should never have sharers while at least one thread
		 * holds a shared lock.
		 */ /*
		 * See if there is more than one shared lock held.  If
		 * so, just drop one and return.
		 */ /*
		 * If there aren't any waiters for an exclusive lock,
		 * then try to drop it quickly.
		 */ /*
		 * At this point, there should just be one sharer with
		 * exclusive waiters.
		 */ /*
		 * Wake up semantic here is quite simple:
		 * Just wake up all the exclusive waiters.
		 * Note that the state of the lock could have changed,
		 * so if it fails loop back and retry.
		 */