summaryrefslogtreecommitdiffstats
path: root/sys/kern/sched_ule.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/sched_ule.c')
-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