summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2003-11-02 03:36:33 +0000
committerjeff <jeff@FreeBSD.org>2003-11-02 03:36:33 +0000
commit5fcee8c60b42ee012f00e5b0f21067ddfc66394c (patch)
tree2efa7e9f1716dad5e0cbc73cdcb09e8ff5b4da9f /sys/kern
parent8375bf2481b1c33dd87f2c93d08e5bd0d7392829 (diff)
downloadFreeBSD-src-5fcee8c60b42ee012f00e5b0f21067ddfc66394c.zip
FreeBSD-src-5fcee8c60b42ee012f00e5b0f21067ddfc66394c.tar.gz
- Change sched_interact_update() to only accept slp+runtime values between
0 and SCHED_SLP_RUN_MAX * 2. This allows us to simplify the algorithm quite a bit. Before, it dealt with arbitrary values which required us to do nasty integer division tricks that didn't quite work out correctly. - Chnage sched_wakeup() to detect conditions where the slp+runtime could exceed SCHED_SLP_RUN_MAX * 2. This can happen if we go to sleep for longer than 6 seconds. In this case, we'll just clear the runtime and set the sleep time to the max. - Define a new function, sched_interact_fork() which updates the slp+runtime of a newly forked thread. We want to limit the amount of history retained from the parent so that we learn the child's behavior quickly. We don't, however want to decay it to nothing. Previously, we would simply divide each parameter by 100 whenever we forked. After a few forks the values would reach 0 and tasks would not be considered interactive. - Add another KTR entry, cleanup some existing entries. - Remove a useless sched_interact_update() from sched_priority(). This is already done by the callers that require it.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/sched_ule.c83
1 files changed, 56 insertions, 27 deletions
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index dfef1e0..a46274c 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -150,12 +150,12 @@ struct td_sched *thread0_sched = &td_sched;
*
* SLP_RUN_MAX: Maximum amount of sleep time + run time we'll accumulate
* before throttling back.
- * SLP_RUN_THROTTLE: Divisor for reducing slp/run time at fork time.
+ * SLP_RUN_FORK: Maximum slp+run time to inherit at fork time.
* INTERACT_MAX: Maximum interactivity value. Smaller is better.
* INTERACT_THRESH: Threshhold for placement on the current runq.
*/
#define SCHED_SLP_RUN_MAX ((hz * 5) << 10)
-#define SCHED_SLP_RUN_THROTTLE (100)
+#define SCHED_SLP_RUN_FORK ((hz / 2) << 10)
#define SCHED_INTERACT_MAX (100)
#define SCHED_INTERACT_HALF (SCHED_INTERACT_MAX / 2)
#define SCHED_INTERACT_THRESH (30)
@@ -240,6 +240,7 @@ static void sched_slice(struct kse *ke);
static void sched_priority(struct ksegrp *kg);
static int sched_interact_score(struct ksegrp *kg);
static void sched_interact_update(struct ksegrp *kg);
+static void sched_interact_fork(struct ksegrp *kg);
static void sched_pctcpu_update(struct kse *ke);
/* Operations on per processor queues */
@@ -788,26 +789,48 @@ sched_slice(struct kse *ke)
ke, ke->ke_slice, kg->kg_nice, kseq->ksq_nicemin,
kseq->ksq_loads[PRI_TIMESHARE], SCHED_INTERACTIVE(kg));
- /*
- * Check to see if we need to scale back the slp and run time
- * in the kg. This will cause us to forget old interactivity
- * while maintaining the current ratio.
- */
- sched_interact_update(kg);
-
return;
}
+/*
+ * This routine enforces a maximum limit on the amount of scheduling history
+ * kept. It is called after either the slptime or runtime is adjusted.
+ * This routine will not operate correctly when slp or run times have been
+ * adjusted to more than double their maximum.
+ */
static void
sched_interact_update(struct ksegrp *kg)
{
- int ratio;
+ int sum;
+
+ sum = kg->kg_runtime + kg->kg_slptime;
+ if (sum < SCHED_SLP_RUN_MAX)
+ return;
+ /*
+ * If we have exceeded by more than 1/5th then the algorithm below
+ * will not bring us back into range. Dividing by two here forces
+ * us into the range of [3/5 * SCHED_INTERACT_MAX, SCHED_INTERACT_MAX]
+ */
+ if (sum > (SCHED_INTERACT_MAX / 5) * 6) {
+ kg->kg_runtime /= 2;
+ kg->kg_slptime /= 2;
+ return;
+ }
+ kg->kg_runtime = (kg->kg_runtime / 5) * 4;
+ kg->kg_slptime = (kg->kg_slptime / 5) * 4;
+}
- if ((kg->kg_runtime + kg->kg_slptime) > SCHED_SLP_RUN_MAX) {
- ratio = ((SCHED_SLP_RUN_MAX * 15) / (kg->kg_runtime +
- kg->kg_slptime ));
- kg->kg_runtime = (kg->kg_runtime * ratio) / 16;
- kg->kg_slptime = (kg->kg_slptime * ratio) / 16;
+static void
+sched_interact_fork(struct ksegrp *kg)
+{
+ int ratio;
+ int sum;
+
+ sum = kg->kg_runtime + kg->kg_slptime;
+ if (sum > SCHED_SLP_RUN_FORK) {
+ ratio = sum / SCHED_SLP_RUN_FORK;
+ kg->kg_runtime /= ratio;
+ kg->kg_slptime /= ratio;
}
}
@@ -891,7 +914,7 @@ sched_pickcpu(void)
}
}
- CTR1(KTR_RUNQ, "sched_pickcpu: %d", cpu);
+ CTR1(KTR_ULE, "sched_pickcpu: %d", cpu);
return (cpu);
}
#endif
@@ -1025,9 +1048,14 @@ sched_wakeup(struct thread *td)
int hzticks;
kg = td->td_ksegrp;
- hzticks = ticks - td->td_slptime;
- kg->kg_slptime += hzticks << 10;
- sched_interact_update(kg);
+ hzticks = (ticks - td->td_slptime) << 10;
+ if (hzticks >= SCHED_SLP_RUN_MAX) {
+ kg->kg_slptime = SCHED_SLP_RUN_MAX;
+ kg->kg_runtime = 1;
+ } else {
+ kg->kg_slptime += hzticks;
+ sched_interact_update(kg);
+ }
sched_priority(kg);
if (td->td_kse)
sched_slice(td->td_kse);
@@ -1070,17 +1098,19 @@ sched_fork_kse(struct kse *ke, struct kse *child)
void
sched_fork_ksegrp(struct ksegrp *kg, struct ksegrp *child)
{
-
PROC_LOCK_ASSERT(child->kg_proc, MA_OWNED);
- /* XXX Need something better here */
- child->kg_slptime = kg->kg_slptime / SCHED_SLP_RUN_THROTTLE;
- child->kg_runtime = kg->kg_runtime / SCHED_SLP_RUN_THROTTLE;
+ child->kg_slptime = kg->kg_slptime;
+ child->kg_runtime = kg->kg_runtime;
+ child->kg_user_pri = kg->kg_user_pri;
+ child->kg_nice = kg->kg_nice;
+ sched_interact_fork(child);
kg->kg_runtime += tickincr << 10;
sched_interact_update(kg);
- child->kg_user_pri = kg->kg_user_pri;
- child->kg_nice = kg->kg_nice;
+ CTR6(KTR_ULE, "sched_fork_ksegrp: %d(%d, %d) - %d(%d, %d)",
+ kg->kg_proc->p_pid, kg->kg_slptime, kg->kg_runtime,
+ child->kg_proc->p_pid, child->kg_slptime, child->kg_runtime);
}
void
@@ -1122,7 +1152,6 @@ sched_class(struct ksegrp *kg, int class)
void
sched_exit(struct proc *p, struct proc *child)
{
- /* XXX Need something better here */
mtx_assert(&sched_lock, MA_OWNED);
sched_exit_kse(FIRST_KSE_IN_PROC(p), FIRST_KSE_IN_PROC(child));
sched_exit_ksegrp(FIRST_KSEGRP_IN_PROC(p), FIRST_KSEGRP_IN_PROC(child));
@@ -1366,7 +1395,7 @@ sched_add(struct thread *td)
ke->ke_slice = SCHED_SLICE_MIN;
break;
default:
- panic("Unknown pri class.\n");
+ panic("Unknown pri class.");
break;
}
#ifdef SMP
OpenPOWER on IntegriCloud