It is possible a lower priority thread lending priority to higher priority
thread, in old code, it is ignored, however the lending should always be
recorded, add field td_lend_user_pri to fix the problem, if a thread does
not have borrowed priority, its value is PRI_MAX.

MFC after: 1 week
This commit is contained in:
davidxu 2010-12-09 02:42:02 +00:00
parent 9eb44e2a50
commit 171976dba2
7 changed files with 36 additions and 32 deletions

View File

@ -460,6 +460,7 @@ proc0_init(void *dummy __unused)
td->td_pri_class = PRI_TIMESHARE;
td->td_user_pri = PUSER;
td->td_base_user_pri = PUSER;
td->td_lend_user_pri = PRI_MAX;
td->td_priority = PVM;
td->td_base_pri = PUSER;
td->td_oncpu = 0;

View File

@ -543,6 +543,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp)
td2->td_sigstk = td->td_sigstk;
td2->td_sigmask = td->td_sigmask;
td2->td_flags = TDF_INMEM;
td2->td_lend_user_pri = PRI_MAX;
#ifdef VIMAGE
td2->td_vnet = NULL;

View File

@ -110,6 +110,7 @@ thread_ctor(void *mem, int size, void *arg, int flags)
* end of a context switch.
*/
td->td_critnest = 1;
td->td_lend_user_pri = PRI_MAX;
EVENTHANDLER_INVOKE(thread_ctor, td);
#ifdef AUDIT
audit_thread_alloc(td);

View File

@ -1407,17 +1407,19 @@ umtx_propagate_priority(struct thread *td)
for (;;) {
td = pi->pi_owner;
if (td == NULL)
if (td == NULL || td == curthread)
return;
MPASS(td->td_proc != NULL);
MPASS(td->td_proc->p_magic == P_MAGIC);
if (UPRI(td) <= pri)
return;
thread_lock(td);
sched_lend_user_prio(td, pri);
if (td->td_lend_user_pri > pri)
sched_lend_user_prio(td, pri);
else {
thread_unlock(td);
break;
}
thread_unlock(td);
/*
@ -3587,8 +3589,8 @@ umtx_thread_cleanup(struct thread *td)
pi->pi_owner = NULL;
TAILQ_REMOVE(&uq->uq_pi_contested, pi, pi_link);
}
thread_lock(td);
td->td_flags &= ~TDF_UBORROWING;
thread_unlock(td);
mtx_unlock_spin(&umtx_lock);
thread_lock(td);
sched_unlend_user_prio(td, PRI_MAX);
thread_unlock(td);
}

View File

@ -879,25 +879,23 @@ sched_prio(struct thread *td, u_char prio)
void
sched_user_prio(struct thread *td, u_char prio)
{
u_char oldprio;
THREAD_LOCK_ASSERT(td, MA_OWNED);
td->td_base_user_pri = prio;
if (td->td_flags & TDF_UBORROWING && td->td_user_pri <= prio)
if (td->td_lend_user_pri <= prio)
return;
oldprio = td->td_user_pri;
td->td_user_pri = prio;
}
void
sched_lend_user_prio(struct thread *td, u_char prio)
{
u_char oldprio;
THREAD_LOCK_ASSERT(td, MA_OWNED);
td->td_flags |= TDF_UBORROWING;
oldprio = td->td_user_pri;
td->td_user_pri = prio;
if (prio < td->td_lend_user_pri)
td->td_lend_user_pri = prio;
if (prio < td->td_user_pri)
td->td_user_pri = prio;
}
void
@ -907,12 +905,11 @@ sched_unlend_user_prio(struct thread *td, u_char prio)
THREAD_LOCK_ASSERT(td, MA_OWNED);
base_pri = td->td_base_user_pri;
if (prio >= base_pri) {
td->td_flags &= ~TDF_UBORROWING;
sched_user_prio(td, base_pri);
} else {
sched_lend_user_prio(td, prio);
}
td->td_lend_user_pri = prio;
if (prio > base_pri)
td->td_user_pri = base_pri;
else
td->td_user_pri = prio;
}
void

View File

@ -1677,8 +1677,8 @@ sched_user_prio(struct thread *td, u_char prio)
{
td->td_base_user_pri = prio;
if (td->td_flags & TDF_UBORROWING && td->td_user_pri <= prio)
return;
if (td->td_lend_user_pri <= prio)
return;
td->td_user_pri = prio;
}
@ -1687,8 +1687,10 @@ sched_lend_user_prio(struct thread *td, u_char prio)
{
THREAD_LOCK_ASSERT(td, MA_OWNED);
td->td_flags |= TDF_UBORROWING;
td->td_user_pri = prio;
if (prio < td->td_lend_user_pri)
td->td_lend_user_pri = prio;
if (prio < td->td_user_pri)
td->td_user_pri = prio;
}
void
@ -1698,12 +1700,11 @@ sched_unlend_user_prio(struct thread *td, u_char prio)
THREAD_LOCK_ASSERT(td, MA_OWNED);
base_pri = td->td_base_user_pri;
if (prio >= base_pri) {
td->td_flags &= ~TDF_UBORROWING;
sched_user_prio(td, base_pri);
} else {
sched_lend_user_prio(td, prio);
}
td->td_lend_user_pri = prio;
if (prio > base_pri)
td->td_user_pri = base_pri;
else
td->td_user_pri = prio;
}
/*

View File

@ -214,6 +214,7 @@ struct thread {
lwpid_t td_tid; /* (b) Thread ID. */
sigqueue_t td_sigqueue; /* (c) Sigs arrived, not delivered. */
#define td_siglist td_sigqueue.sq_signals
u_char td_lend_user_pri; /* (t) Lend user pri. */
/* Cleared during fork1() */
#define td_startzero td_flags
@ -343,7 +344,7 @@ do { \
#define TDF_CANSWAP 0x00000040 /* Thread can be swapped. */
#define TDF_SLEEPABORT 0x00000080 /* sleepq_abort was called. */
#define TDF_KTH_SUSP 0x00000100 /* kthread is suspended */
#define TDF_UBORROWING 0x00000200 /* Thread is borrowing user pri. */
#define TDF_UNUSED09 0x00000200 /* --available-- */
#define TDF_BOUNDARY 0x00000400 /* Thread suspended at user boundary */
#define TDF_ASTPENDING 0x00000800 /* Thread has some asynchronous events. */
#define TDF_TIMOFAIL 0x00001000 /* Timeout from sleep after we were awake. */