MFp4:
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:
parent
9eb44e2a50
commit
171976dba2
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user