Print this page
11909 THREAD_KPRI_RELEASE does nothing of the sort
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
*** 19,29 ****
* CDDL HEADER END
*/
/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2013, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
! * Copyright 2019 Joyent, Inc.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
*** 1371,1382 ****
* Skip the thread if it is no longer in the FSS class or
* is running with kernel mode priority.
*/
if (t->t_cid != fss_cid)
goto next;
- if ((fssproc->fss_flags & FSSKPRI) != 0)
- goto next;
fssproj = FSSPROC2FSSPROJ(fssproc);
if (fssproj == NULL)
goto next;
--- 1371,1380 ----
*** 1887,1897 ****
cfssproc->fss_tp = ct;
cfssproc->fss_nice = pfssproc->fss_nice;
cpucaps_sc_init(&cfssproc->fss_caps);
cfssproc->fss_flags =
! pfssproc->fss_flags & ~(FSSKPRI | FSSBACKQ | FSSRESTORE);
ct->t_cldata = (void *)cfssproc;
ct->t_schedflag |= TS_RUNQMATCH;
thread_unlock(pt);
fssproj->fssp_threads++;
--- 1885,1895 ----
cfssproc->fss_tp = ct;
cfssproc->fss_nice = pfssproc->fss_nice;
cpucaps_sc_init(&cfssproc->fss_caps);
cfssproc->fss_flags =
! pfssproc->fss_flags & ~(FSSBACKQ | FSSRESTORE);
ct->t_cldata = (void *)cfssproc;
ct->t_schedflag |= TS_RUNQMATCH;
thread_unlock(pt);
fssproj->fssp_threads++;
*** 1938,1948 ****
fssproc = FSSPROC(t);
fss_newpri(fssproc, B_FALSE);
fssproc->fss_timeleft = fss_quantum;
t->t_pri = fssproc->fss_umdpri;
ASSERT(t->t_pri >= 0 && t->t_pri <= fss_maxglobpri);
- fssproc->fss_flags &= ~FSSKPRI;
THREAD_TRANSITION(t);
/*
* We don't want to call fss_setrun(t) here because it may call
* fss_active, which we don't need.
--- 1936,1945 ----
*** 2037,2051 ****
fssproc->fss_uprilim = reqfssuprilim;
fssproc->fss_upri = reqfssupri;
fssproc->fss_nice = nice;
fss_newpri(fssproc, B_FALSE);
- if ((fssproc->fss_flags & FSSKPRI) != 0) {
- thread_unlock(t);
- return (0);
- }
-
fss_change_priority(t, fssproc);
thread_unlock(t);
return (0);
}
--- 2034,2043 ----
*** 2156,2166 ****
if (t->t_state == TS_RUN && (t->t_schedflag & TS_LOAD) == 0) {
time_t swapout_time;
swapout_time = (ddi_get_lbolt() - t->t_stime) / hz;
! if (INHERITED(t) || (fssproc->fss_flags & FSSKPRI)) {
epri = (long)DISP_PRIO(t) + swapout_time;
} else {
/*
* Threads which have been out for a long time,
* have high user mode priority and are associated
--- 2148,2158 ----
if (t->t_state == TS_RUN && (t->t_schedflag & TS_LOAD) == 0) {
time_t swapout_time;
swapout_time = (ddi_get_lbolt() - t->t_stime) / hz;
! if (INHERITED(t)) {
epri = (long)DISP_PRIO(t) + swapout_time;
} else {
/*
* Threads which have been out for a long time,
* have high user mode priority and are associated
*** 2188,2206 ****
* based on if the swapper is in softswap or hardswap mode.
*/
static pri_t
fss_swapout(kthread_t *t, int flags)
{
- fssproc_t *fssproc = FSSPROC(t);
long epri = -1;
proc_t *pp = ttoproc(t);
time_t swapin_time;
ASSERT(THREAD_LOCK_HELD(t));
if (INHERITED(t) ||
- (fssproc->fss_flags & FSSKPRI) ||
(t->t_proc_flag & TP_LWPEXIT) ||
(t->t_state & (TS_ZOMB|TS_FREE|TS_STOPPED|TS_ONPROC|TS_WAIT)) ||
!(t->t_schedflag & TS_LOAD) ||
!(SWAP_OK(t)))
return (-1);
--- 2180,2196 ----
*** 2239,2280 ****
return ((pri_t)epri);
}
/*
! * If thread is currently at a kernel mode priority (has slept) and is
! * returning to the userland we assign it the appropriate user mode priority
! * and time quantum here. If we're lowering the thread's priority below that
! * of other runnable threads then we will set runrun via cpu_surrender() to
! * cause preemption.
*/
static void
fss_trapret(kthread_t *t)
{
- fssproc_t *fssproc = FSSPROC(t);
cpu_t *cp = CPU;
ASSERT(THREAD_LOCK_HELD(t));
ASSERT(t == curthread);
ASSERT(cp->cpu_dispthread == t);
ASSERT(t->t_state == TS_ONPROC);
- t->t_kpri_req = 0;
- if (fssproc->fss_flags & FSSKPRI) {
/*
- * If thread has blocked in the kernel
- */
- THREAD_CHANGE_PRI(t, fssproc->fss_umdpri);
- cp->cpu_dispatch_pri = DISP_PRIO(t);
- ASSERT(t->t_pri >= 0 && t->t_pri <= fss_maxglobpri);
- fssproc->fss_flags &= ~FSSKPRI;
-
- if (DISP_MUST_SURRENDER(t))
- cpu_surrender(t);
- }
-
- /*
* Swapout lwp if the swapper is waiting for this thread to reach
* a safe point.
*/
if (t->t_schedflag & TS_SWAPENQ) {
thread_unlock(t);
--- 2229,2251 ----
return ((pri_t)epri);
}
/*
! * Run swap-out checks when returning to userspace.
*/
static void
fss_trapret(kthread_t *t)
{
cpu_t *cp = CPU;
ASSERT(THREAD_LOCK_HELD(t));
ASSERT(t == curthread);
ASSERT(cp->cpu_dispthread == t);
ASSERT(t->t_state == TS_ONPROC);
/*
* Swapout lwp if the swapper is waiting for this thread to reach
* a safe point.
*/
if (t->t_schedflag & TS_SWAPENQ) {
thread_unlock(t);
*** 2297,2336 ****
ASSERT(t == curthread);
ASSERT(THREAD_LOCK_HELD(curthread));
ASSERT(t->t_state == TS_ONPROC);
/*
- * If preempted in the kernel, make sure the thread has a kernel
- * priority if needed.
- */
- lwp = curthread->t_lwp;
- if (!(fssproc->fss_flags & FSSKPRI) && lwp != NULL && t->t_kpri_req) {
- fssproc->fss_flags |= FSSKPRI;
- THREAD_CHANGE_PRI(t, minclsyspri);
- ASSERT(t->t_pri >= 0 && t->t_pri <= fss_maxglobpri);
- t->t_trapret = 1; /* so that fss_trapret will run */
- aston(t);
- }
-
- /*
* This thread may be placed on wait queue by CPU Caps. In this case we
* do not need to do anything until it is removed from the wait queue.
* Do not enforce CPU caps on threads running at a kernel priority
*/
if (CPUCAPS_ON()) {
(void) cpucaps_charge(t, &fssproc->fss_caps,
CPUCAPS_CHARGE_ENFORCE);
! if (!(fssproc->fss_flags & FSSKPRI) && CPUCAPS_ENFORCE(t))
return;
}
/*
* If preempted in user-land mark the thread as swappable because it
* cannot be holding any kernel locks.
*/
ASSERT(t->t_schedflag & TS_DONT_SWAP);
if (lwp != NULL && lwp->lwp_state == LWP_USER)
t->t_schedflag &= ~TS_DONT_SWAP;
/*
* Check to see if we're doing "preemption control" here. If
--- 2268,2295 ----
ASSERT(t == curthread);
ASSERT(THREAD_LOCK_HELD(curthread));
ASSERT(t->t_state == TS_ONPROC);
/*
* This thread may be placed on wait queue by CPU Caps. In this case we
* do not need to do anything until it is removed from the wait queue.
* Do not enforce CPU caps on threads running at a kernel priority
*/
if (CPUCAPS_ON()) {
(void) cpucaps_charge(t, &fssproc->fss_caps,
CPUCAPS_CHARGE_ENFORCE);
! if (CPUCAPS_ENFORCE(t))
return;
}
/*
* If preempted in user-land mark the thread as swappable because it
* cannot be holding any kernel locks.
*/
ASSERT(t->t_schedflag & TS_DONT_SWAP);
+ lwp = ttolwp(t);
if (lwp != NULL && lwp->lwp_state == LWP_USER)
t->t_schedflag &= ~TS_DONT_SWAP;
/*
* Check to see if we're doing "preemption control" here. If
*** 2344,2354 ****
* be preempted.
*/
if (t->t_schedctl && schedctl_get_nopreempt(t)) {
if (fssproc->fss_timeleft > -SC_MAX_TICKS) {
DTRACE_SCHED1(schedctl__nopreempt, kthread_t *, t);
- if (!(fssproc->fss_flags & FSSKPRI)) {
/*
* If not already remembered, remember current
* priority for restoration in fss_yield().
*/
if (!(fssproc->fss_flags & FSSRESTORE)) {
--- 2303,2312 ----
*** 2355,2365 ****
fssproc->fss_scpri = t->t_pri;
fssproc->fss_flags |= FSSRESTORE;
}
THREAD_CHANGE_PRI(t, fss_maxumdpri);
t->t_schedflag |= TS_DONT_SWAP;
- }
schedctl_set_yield(t, 1);
setfrontdq(t);
return;
} else {
if (fssproc->fss_flags & FSSRESTORE) {
--- 2313,2322 ----
*** 2372,2390 ****
* Fall through and be preempted below.
*/
}
}
! flags = fssproc->fss_flags & (FSSBACKQ | FSSKPRI);
if (flags == FSSBACKQ) {
fssproc->fss_timeleft = fss_quantum;
fssproc->fss_flags &= ~FSSBACKQ;
setbackdq(t);
- } else if (flags == (FSSBACKQ | FSSKPRI)) {
- fssproc->fss_flags &= ~FSSBACKQ;
- setbackdq(t);
} else {
setfrontdq(t);
}
}
--- 2329,2344 ----
* Fall through and be preempted below.
*/
}
}
! flags = fssproc->fss_flags & FSSBACKQ;
if (flags == FSSBACKQ) {
fssproc->fss_timeleft = fss_quantum;
fssproc->fss_flags &= ~FSSBACKQ;
setbackdq(t);
} else {
setfrontdq(t);
}
}
*** 2402,2427 ****
fss_active(t);
fssproc->fss_timeleft = fss_quantum;
fssproc->fss_flags &= ~FSSBACKQ;
- /*
- * If previously were running at the kernel priority then keep that
- * priority and the fss_timeleft doesn't matter.
- */
- if ((fssproc->fss_flags & FSSKPRI) == 0)
THREAD_CHANGE_PRI(t, fssproc->fss_umdpri);
if (t->t_disp_time != ddi_get_lbolt())
setbackdq(t);
else
setfrontdq(t);
}
/*
! * Prepare thread for sleep. We reset the thread priority so it will run at the
! * kernel priority level when it wakes up.
*/
static void
fss_sleep(kthread_t *t)
{
fssproc_t *fssproc = FSSPROC(t);
--- 2356,2375 ----
fss_active(t);
fssproc->fss_timeleft = fss_quantum;
fssproc->fss_flags &= ~FSSBACKQ;
THREAD_CHANGE_PRI(t, fssproc->fss_umdpri);
if (t->t_disp_time != ddi_get_lbolt())
setbackdq(t);
else
setfrontdq(t);
}
/*
! * Prepare thread for sleep.
*/
static void
fss_sleep(kthread_t *t)
{
fssproc_t *fssproc = FSSPROC(t);
*** 2435,2469 ****
* Account for time spent on CPU before going to sleep.
*/
(void) CPUCAPS_CHARGE(t, &fssproc->fss_caps, CPUCAPS_CHARGE_ENFORCE);
fss_inactive(t);
-
- /*
- * Assign a system priority to the thread and arrange for it to be
- * retained when the thread is next placed on the run queue (i.e.,
- * when it wakes up) instead of being given a new pri. Also arrange
- * for trapret processing as the thread leaves the system call so it
- * will drop back to normal priority range.
- */
- if (t->t_kpri_req) {
- THREAD_CHANGE_PRI(t, minclsyspri);
- fssproc->fss_flags |= FSSKPRI;
- t->t_trapret = 1; /* so that fss_trapret will run */
- aston(t);
- } else if (fssproc->fss_flags & FSSKPRI) {
- /*
- * The thread has done a THREAD_KPRI_REQUEST(), slept, then
- * done THREAD_KPRI_RELEASE() (so no t_kpri_req is 0 again),
- * then slept again all without finishing the current system
- * call so trapret won't have cleared FSSKPRI
- */
- fssproc->fss_flags &= ~FSSKPRI;
- THREAD_CHANGE_PRI(t, fssproc->fss_umdpri);
- if (DISP_MUST_SURRENDER(curthread))
- cpu_surrender(t);
- }
t->t_stime = ddi_get_lbolt(); /* time stamp for the swapper */
}
/*
* A tick interrupt has ocurrend on a running thread. Check to see if our
--- 2383,2392 ----
*** 2501,2531 ****
* Keep track of thread's project CPU usage. Note that projects
* get charged even when threads are running in the kernel.
* Do not surrender CPU if running in the SYS class.
*/
if (CPUCAPS_ON()) {
! cpucaps_enforce = cpucaps_charge(t,
! &fssproc->fss_caps, CPUCAPS_CHARGE_ENFORCE) &&
! !(fssproc->fss_flags & FSSKPRI);
}
- /*
- * A thread's execution time for threads running in the SYS class
- * is not tracked.
- */
- if ((fssproc->fss_flags & FSSKPRI) == 0) {
- /*
- * If thread is not in kernel mode, decrement its fss_timeleft
- */
if (--fssproc->fss_timeleft <= 0) {
pri_t new_pri;
/*
! * If we're doing preemption control and trying to
! * avoid preempting this thread, just note that the
! * thread should yield soon and let it keep running
! * (unless it's been a while).
*/
if (t->t_schedctl && schedctl_get_nopreempt(t)) {
if (fssproc->fss_timeleft > -SC_MAX_TICKS) {
DTRACE_SCHED1(schedctl__nopreempt,
kthread_t *, t);
--- 2424,2445 ----
* Keep track of thread's project CPU usage. Note that projects
* get charged even when threads are running in the kernel.
* Do not surrender CPU if running in the SYS class.
*/
if (CPUCAPS_ON()) {
! cpucaps_enforce = cpucaps_charge(t, &fssproc->fss_caps,
! CPUCAPS_CHARGE_ENFORCE);
}
if (--fssproc->fss_timeleft <= 0) {
pri_t new_pri;
/*
! * If we're doing preemption control and trying to avoid
! * preempting this thread, just note that the thread should
! * yield soon and let it keep running (unless it's been a
! * while).
*/
if (t->t_schedctl && schedctl_get_nopreempt(t)) {
if (fssproc->fss_timeleft > -SC_MAX_TICKS) {
DTRACE_SCHED1(schedctl__nopreempt,
kthread_t *, t);
*** 2539,2552 ****
fss_newpri(fssproc, B_TRUE);
new_pri = fssproc->fss_umdpri;
ASSERT(new_pri >= 0 && new_pri <= fss_maxglobpri);
/*
! * When the priority of a thread is changed, it may
! * be necessary to adjust its position on a sleep queue
! * or dispatch queue. The function thread_change_pri
! * accomplishes this.
*/
if (thread_change_pri(t, new_pri, 0)) {
if ((t->t_schedflag & TS_LOAD) &&
(lwp = t->t_lwp) &&
lwp->lwp_state == LWP_USER)
--- 2453,2466 ----
fss_newpri(fssproc, B_TRUE);
new_pri = fssproc->fss_umdpri;
ASSERT(new_pri >= 0 && new_pri <= fss_maxglobpri);
/*
! * When the priority of a thread is changed, it may be
! * necessary to adjust its position on a sleep queue or
! * dispatch queue. The function thread_change_pri accomplishes
! * this.
*/
if (thread_change_pri(t, new_pri, 0)) {
if ((t->t_schedflag & TS_LOAD) &&
(lwp = t->t_lwp) &&
lwp->lwp_state == LWP_USER)
*** 2556,2572 ****
call_cpu_surrender = B_TRUE;
}
} else if (t->t_state == TS_ONPROC &&
t->t_pri < t->t_disp_queue->disp_maxrunpri) {
/*
! * If there is a higher-priority thread which is
! * waiting for a processor, then thread surrenders
! * the processor.
*/
call_cpu_surrender = B_TRUE;
}
- }
if (cpucaps_enforce && 2 * fssproc->fss_timeleft > fss_quantum) {
/*
* The thread used more than half of its quantum, so assume that
* it used the whole quantum.
--- 2470,2484 ----
call_cpu_surrender = B_TRUE;
}
} else if (t->t_state == TS_ONPROC &&
t->t_pri < t->t_disp_queue->disp_maxrunpri) {
/*
! * If there is a higher-priority thread which is waiting for a
! * processor, then thread surrenders the processor.
*/
call_cpu_surrender = B_TRUE;
}
if (cpucaps_enforce && 2 * fssproc->fss_timeleft > fss_quantum) {
/*
* The thread used more than half of its quantum, so assume that
* it used the whole quantum.
*** 2616,2652 ****
t->t_stime = ddi_get_lbolt(); /* time stamp for the swapper */
fssproc = FSSPROC(t);
fssproc->fss_flags &= ~FSSBACKQ;
! if (fssproc->fss_flags & FSSKPRI) {
! /*
! * If we already have a kernel priority assigned, then we
! * just use it.
! */
! setbackdq(t);
! } else if (t->t_kpri_req) {
! /*
! * Give thread a priority boost if we were asked.
! */
! fssproc->fss_flags |= FSSKPRI;
! THREAD_CHANGE_PRI(t, minclsyspri);
! setbackdq(t);
! t->t_trapret = 1; /* so that fss_trapret will run */
! aston(t);
! } else {
! /*
! * Otherwise, we recalculate the priority.
! */
if (t->t_disp_time == ddi_get_lbolt()) {
setfrontdq(t);
} else {
fssproc->fss_timeleft = fss_quantum;
THREAD_CHANGE_PRI(t, fssproc->fss_umdpri);
setbackdq(t);
}
- }
}
/*
* fss_donice() is called when a nice(1) command is issued on the thread to
* alter the priority. The nice(1) command exists in Solaris for compatibility.
--- 2528,2545 ----
t->t_stime = ddi_get_lbolt(); /* time stamp for the swapper */
fssproc = FSSPROC(t);
fssproc->fss_flags &= ~FSSBACKQ;
! /* Recalculate the priority. */
if (t->t_disp_time == ddi_get_lbolt()) {
setfrontdq(t);
} else {
fssproc->fss_timeleft = fss_quantum;
THREAD_CHANGE_PRI(t, fssproc->fss_umdpri);
setbackdq(t);
}
}
/*
* fss_donice() is called when a nice(1) command is issued on the thread to
* alter the priority. The nice(1) command exists in Solaris for compatibility.