From 9dda14459dc0b1bb02a2ad92098dad4815b321eb Mon Sep 17 00:00:00 2001 From: davidxu Date: Mon, 19 Dec 2005 08:26:09 +0000 Subject: [PATCH] Fix a bug in slice calculation code, current code uses hz but sched_clock() is called by state clock. Submitted by: taku at tackymt dot homeip dot net --- sys/kern/sched_ule.c | 50 +++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c index e5fe68aafef0..701235393a62 100644 --- a/sys/kern/sched_ule.c +++ b/sys/kern/sched_ule.c @@ -69,6 +69,9 @@ SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, ""); static void sched_setup(void *dummy); SYSINIT(sched_setup, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, sched_setup, NULL) +static void sched_initticks(void *dummy); +SYSINIT(sched_initticks, SI_SUB_CLOCKS, SI_ORDER_THIRD, sched_initticks, NULL) + static SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler"); SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "ule", 0, @@ -81,7 +84,7 @@ static int slice_max = 10; SYSCTL_INT(_kern_sched, OID_AUTO, slice_max, CTLFLAG_RW, &slice_max, 0, ""); int realstathz; -int tickincr = 1; +int tickincr = 1 << 10; /* * The following datastructures are allocated within their parent structure @@ -921,6 +924,11 @@ sched_setup(void *dummy) int i; #endif + /* + * To avoid divide-by-zero, we set realstathz a dummy value + * in case which sched_clock() called before sched_initticks(). + */ + realstathz = hz; slice_min = (hz/100); /* 10ms */ slice_max = (hz/7); /* ~140ms */ @@ -1011,6 +1019,26 @@ sched_setup(void *dummy) mtx_unlock_spin(&sched_lock); } +/* ARGSUSED */ +static void +sched_initticks(void *dummy) +{ + mtx_lock_spin(&sched_lock); + realstathz = stathz ? stathz : hz; + slice_min = (realstathz/100); /* 10ms */ + slice_max = (realstathz/7); /* ~140ms */ + + tickincr = (hz << 10) / realstathz; + /* + * XXX This does not work for values of stathz that are much + * larger than hz. + */ + if (tickincr == 0) + tickincr = 1; + mtx_unlock_spin(&sched_lock); +} + + /* * Scale the scheduling priority according to the "interactivity" of this * process. @@ -1492,7 +1520,7 @@ sched_fork_ksegrp(struct thread *td, struct ksegrp *child) child->kg_runtime = kg->kg_runtime; child->kg_user_pri = kg->kg_user_pri; sched_interact_fork(child); - kg->kg_runtime += tickincr << 10; + kg->kg_runtime += tickincr; sched_interact_update(kg); } @@ -1615,22 +1643,6 @@ sched_clock(struct thread *td) if (kseq->ksq_assigned) kseq_assign(kseq); /* Potentially sets NEEDRESCHED */ #endif - /* - * sched_setup() apparently happens prior to stathz being set. We - * need to resolve the timers earlier in the boot so we can avoid - * calculating this here. - */ - if (realstathz == 0) { - realstathz = stathz ? stathz : hz; - tickincr = hz / realstathz; - /* - * XXX This does not work for values of stathz that are much - * larger than hz. - */ - if (tickincr == 0) - tickincr = 1; - } - ke = td->td_kse; kg = ke->ke_ksegrp; @@ -1653,7 +1665,7 @@ sched_clock(struct thread *td) * We used a tick charge it to the ksegrp so that we can compute our * interactivity. */ - kg->kg_runtime += tickincr << 10; + kg->kg_runtime += tickincr; sched_interact_update(kg); /*