FreeBSD/sys/kern/kern_umtx.c
/*
 * Sleep on a PI mutex.
 */
Sleep on a PI mutex.
Sleep on a PI mutex .
static int
umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi, uint32_t owner,
    const char *wmesg, struct abs_timeout *timo, bool shared)
{
	struct umtxq_chain *uc;
	struct thread *td, *td1;
	struct umtx_q *uq1;
	int error, pri;
	error = 0;
	td = uq->uq_thread;
	KASSERT(td == curthread, ("inconsistent uq_thread"));
	uc = umtxq_getchain(&uq->uq_key);
	UMTXQ_LOCKED_ASSERT(uc);
	KASSERT(uc->uc_busy != 0, ("umtx chain is not busy"));
	umtxq_insert(uq);
	mtx_lock(&umtx_lock);
	if (pi->pi_owner == NULL) {
		mtx_unlock(&umtx_lock);
		td1 = tdfind(owner, shared ? -1 : td->td_proc->p_pid);
		mtx_lock(&umtx_lock);
		if (td1 != NULL) {
			if (pi->pi_owner == NULL)
				umtx_pi_setowner(pi, td1);
			PROC_UNLOCK(td1->td_proc);
		}
	}
	TAILQ_FOREACH(uq1, &pi->pi_blocked, uq_lockq) {
		pri = UPRI(uq1->uq_thread);
		if (pri > UPRI(td))
			break;
	}
	if (uq1 != NULL)
		TAILQ_INSERT_BEFORE(uq1, uq, uq_lockq);
	else
		TAILQ_INSERT_TAIL(&pi->pi_blocked, uq, uq_lockq);
	uq->uq_pi_blocked = pi;
	thread_lock(td);
	td->td_flags |= TDF_UPIBLOCKED;
	thread_unlock(td);
	umtx_propagate_priority(td);
	mtx_unlock(&umtx_lock);
	umtxq_unbusy(&uq->uq_key);
	error = umtxq_sleep(uq, wmesg, timo);
	umtxq_remove(uq);
	mtx_lock(&umtx_lock);
	uq->uq_pi_blocked = NULL;
	thread_lock(td);
	td->td_flags &= ~TDF_UPIBLOCKED;
	thread_unlock(td);
	TAILQ_REMOVE(&pi->pi_blocked, uq, uq_lockq);
	umtx_repropagate_priority(pi);
	mtx_unlock(&umtx_lock);
	umtxq_unlock(&uq->uq_key);
	return (error);
}
static int umtxq_sleep_pi ( struct umtx_q * uq , struct umtx_pi * pi , uint32_t owner , const char * wmesg , struct abs_timeout * timo , bool shared ) { struct umtxq_chain * uc ; struct thread * td , * td1 ; struct umtx_q * uq1 ; int error , pri ; error = 0 ; td = uq -> uq_thread ; KASSERT ( td == curthread , ( " " ) ) ; uc = umtxq_getchain ( & uq -> uq_key ) ; UMTXQ_LOCKED_ASSERT ( uc ) ; KASSERT ( uc -> uc_busy != 0 , ( " " ) ) ; umtxq_insert ( uq ) ; mtx_lock ( & umtx_lock ) ; if ( pi -> pi_owner == NULL ) { mtx_unlock ( & umtx_lock ) ; td1 = tdfind ( owner , shared ? -1 : td -> td_proc -> p_pid ) ; mtx_lock ( & umtx_lock ) ; if ( td1 != NULL ) { if ( pi -> pi_owner == NULL ) umtx_pi_setowner ( pi , td1 ) ; PROC_UNLOCK ( td1 -> td_proc ) ; } } TAILQ_FOREACH ( uq1 , & pi -> pi_blocked , uq_lockq ) { pri = UPRI ( uq1 -> uq_thread ) ; if ( pri > UPRI ( td ) ) break ; } if ( uq1 != NULL ) TAILQ_INSERT_BEFORE ( uq1 , uq , uq_lockq ) ; else TAILQ_INSERT_TAIL ( & pi -> pi_blocked , uq , uq_lockq ) ; uq -> uq_pi_blocked = pi ; thread_lock ( td ) ; td -> td_flags |= TDF_UPIBLOCKED ; thread_unlock ( td ) ; umtx_propagate_priority ( td ) ; mtx_unlock ( & umtx_lock ) ; umtxq_unbusy ( & uq -> uq_key ) ; error = umtxq_sleep ( uq , wmesg , timo ) ; umtxq_remove ( uq ) ; mtx_lock ( & umtx_lock ) ; uq -> uq_pi_blocked = NULL ; thread_lock ( td ) ; td -> td_flags &= ~ TDF_UPIBLOCKED ; thread_unlock ( td ) ; TAILQ_REMOVE ( & pi -> pi_blocked , uq , uq_lockq ) ; umtx_repropagate_priority ( pi ) ; mtx_unlock ( & umtx_lock ) ; umtxq_unlock ( & uq -> uq_key ) ; return ( error ) ; }
Sleep on a PI mutex.
Sleep on a PI mutex .