* Remove a procedural layer in the scheduler clock code by having
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 27 Jun 2005 18:38:03 +0000 (18:38 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 27 Jun 2005 18:38:03 +0000 (18:38 +0000)
  kern_clock call the usched scheduler clock function directly.

* Move p_estcpu to scheduler-specific code.

* Have kern_synch's one-second timer call into the scheduler instead of
  trying to figure it out itself.

* Decay p_estcpu whenever a user process is scheduled as well as once
  per second, leading to (hopefully) better performance under load and
  better handling of adverse conditions (a nice +20 process running in the
  face of a nice -20 process).

* No longer assume that one second has elapsed in the one-second callback.
  Instead calculate the elapsed time on a per-process basis.  This should
  reduce instances of batch processes 'glitching' interactive processes.

* Remove the old round-robin code and instead just have the scheduler
  figure it out internally in the scheduler clock function.

* Revamp the scheduler algorithms, making everything #define constant
  driven.  Retain the NICE-based base-priority and decay algorithms but
  narrow the decay range from the process nice value.  Retain the child
  estcpu inheritance algorithm.

Feedback-provided-by: walt <wa1ter@myrealbox.com>
14 files changed:
bin/ps/keyword.c
sys/emulation/posix4/ksched.c
sys/i386/include/smp.h
sys/kern/kern_clock.c
sys/kern/kern_fork.c
sys/kern/kern_sched.c
sys/kern/kern_synch.c
sys/kern/tty.c
sys/platform/pc32/include/smp.h
sys/sys/globaldata.h
sys/sys/proc.h
sys/sys/usched.h
sys/vm/vm_pageout.c
usr.bin/w/proc_compare.c

index 62b2322..7963db6 100644 (file)
@@ -32,7 +32,7 @@
  *
  * @(#)keyword.c       8.5 (Berkeley) 4/2/94
  * $FreeBSD: src/bin/ps/keyword.c,v 1.24.2.3 2002/10/10 20:05:32 jmallett Exp $
- * $DragonFly: src/bin/ps/keyword.c,v 1.18 2005/06/26 04:36:34 dillon Exp $
+ * $DragonFly: src/bin/ps/keyword.c,v 1.19 2005/06/27 18:38:01 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -90,7 +90,7 @@ static const VAR var[] = {
        {"caught", "", "sigcatch", 0, NULL, NULL, 0, 0, 0, NULL, NULL},
        {"command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16, 0, 0, NULL,
                NULL},
-       {"cpu", "CPU", NULL, 0, pvar, NULL, 3, POFF(p_estcpu), UINT, "d", NULL},
+       {"cpu", "CPU", NULL, 0, pvar, NULL, 3, POFF(p_usdata.bsd4.estcpu), UINT, "d", NULL},
        {"lastcpu", "C", NULL, 0, pvar, NULL, 3, EOFF(e_cpuid), UINT, "d", NULL},
        {"cputime", "", "time", 0, NULL, NULL, 0, 0, 0, NULL, NULL},
        {"f", "F", NULL, 0, pvar, NULL, 7, POFF(p_flag), INT, "x", NULL},
index bcf3612..aef99e7 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/posix4/ksched.c,v 1.7.2.1 2000/05/16 06:58:13 dillon Exp $
- * $DragonFly: src/sys/emulation/posix4/Attic/ksched.c,v 1.4 2004/03/30 19:14:18 dillon Exp $
+ * $DragonFly: src/sys/emulation/posix4/Attic/ksched.c,v 1.5 2005/06/27 18:38:02 dillon Exp $
  */
 
 /* ksched: Soft real time scheduling based on "rtprio".
@@ -58,7 +58,7 @@ int ksched_attach(struct ksched **p)
        struct ksched *ksched= p31b_malloc(sizeof(*ksched));
 
        ksched->rr_interval.tv_sec = 0;
-       ksched->rr_interval.tv_nsec = 1000000000L / roundrobin_interval();
+       ksched->rr_interval.tv_nsec = 1000000000L / 10; /* XXX */
 
        *p = ksched;
        return 0;
index 8f835ad..c59a38b 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $
- * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.11 2004/03/01 06:33:16 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.12 2005/06/27 18:37:55 dillon Exp $
  *
  */
 
@@ -109,7 +109,6 @@ int stop_cpus               (u_int);
 void   ap_init                 (void);
 int    restart_cpus            (u_int);
 void   forward_signal          (struct proc *);
-void   forward_roundrobin      (void);
 #ifdef APIC_INTR_REORDER
 void   set_lapic_isrloc        (int, int);
 #endif /* APIC_INTR_REORDER */
index 1386a32..1abba49 100644 (file)
@@ -70,7 +70,7 @@
  *
  *     @(#)kern_clock.c        8.5 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/kern_clock.c,v 1.105.2.10 2002/10/17 13:19:40 maxim Exp $
- * $DragonFly: src/sys/kern/kern_clock.c,v 1.43 2005/06/06 15:02:27 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_clock.c,v 1.44 2005/06/27 18:37:57 dillon Exp $
  */
 
 #include "opt_ntp.h"
@@ -625,9 +625,11 @@ statclock(systimer_t info, struct intrframe *frame)
 }
 
 /*
- * The scheduler clock typically runs at a 20Hz rate.  NOTE! systimer,
+ * The scheduler clock typically runs at a 50Hz rate.  NOTE! systimer,
  * the MP lock might not be held.  We can safely manipulate parts of curproc
  * but that's about it.
+ *
+ * Each cpu has its own scheduler clock.
  */
 static void
 schedclock(systimer_t info, struct intrframe *frame)
@@ -638,9 +640,18 @@ schedclock(systimer_t info, struct intrframe *frame)
        struct vmspace *vm;
        long rss;
 
-       schedulerclock(NULL);   /* mpsafe */
+       if ((p = lwkt_preempted_proc()) != NULL) {
+               /*
+                * Account for cpu time used and hit the scheduler.  Note
+                * that this call MUST BE MP SAFE, and the BGL IS NOT HELD
+                * HERE.
+                */
+                p->p_usched->schedulerclock(p, info->periodic, info->time);
+       }
        if ((p = curproc) != NULL) {
-               /* Update resource usage integrals and maximums. */
+               /*
+                * Update resource usage integrals and maximums.
+                */
                if ((pstats = p->p_stats) != NULL &&
                    (ru = &pstats->p_ru) != NULL &&
                    (vm = p->p_vmspace) != NULL) {
index 11951d8..e4f60cf 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_fork.c 8.6 (Berkeley) 4/8/94
  * $FreeBSD: src/sys/kern/kern_fork.c,v 1.72.2.14 2003/06/26 04:15:10 silby Exp $
- * $DragonFly: src/sys/kern/kern_fork.c,v 1.35 2005/06/26 04:36:31 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_fork.c,v 1.36 2005/06/27 18:37:57 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -510,8 +510,12 @@ again:
 
        /*
         * Inherit the scheduler and initialize scheduler-related fields. 
+        * Set cpbase to the last timeout that occured (not the upcoming
+        * timeout).
         */
        p2->p_usched = p1->p_usched;
+       p2->p_cpbase = mycpu->gd_schedclock.time - 
+                       mycpu->gd_schedclock.periodic;
        p2->p_usched->heuristic_forking(p1, p2);
 
        /*
index 9631a82..399ac08 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/posix4/ksched.c,v 1.7.2.1 2000/05/16 06:58:13 dillon Exp $
- * $DragonFly: src/sys/kern/kern_sched.c,v 1.4 2004/03/30 19:14:18 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_sched.c,v 1.5 2005/06/27 18:38:02 dillon Exp $
  */
 
 /* ksched: Soft real time scheduling based on "rtprio".
@@ -58,7 +58,7 @@ int ksched_attach(struct ksched **p)
        struct ksched *ksched= p31b_malloc(sizeof(*ksched));
 
        ksched->rr_interval.tv_sec = 0;
-       ksched->rr_interval.tv_nsec = 1000000000L / roundrobin_interval();
+       ksched->rr_interval.tv_nsec = 1000000000L / 10; /* XXX */
 
        *p = ksched;
        return 0;
index edf5226..94c1731 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_synch.c        8.9 (Berkeley) 5/19/95
  * $FreeBSD: src/sys/kern/kern_synch.c,v 1.87.2.6 2002/10/13 07:29:53 kbyanc Exp $
- * $DragonFly: src/sys/kern/kern_synch.c,v 1.46 2005/06/26 22:03:22 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_synch.c,v 1.47 2005/06/27 18:37:57 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -72,7 +72,6 @@ int   ncpus2, ncpus2_shift, ncpus2_mask;
 int    safepri;
 
 static struct callout loadav_callout;
-static struct callout roundrobin_callout;
 static struct callout schedcpu_callout;
 
 struct loadavg averunnable =
@@ -89,9 +88,7 @@ static fixpt_t cexp[3] = {
 
 static void    endtsleep (void *);
 static void    loadav (void *arg);
-static void    roundrobin (void *arg);
 static void    schedcpu (void *arg);
-static void    updatepri (struct proc *p);
 
 /*
  * Adjust the scheduler quantum.  The quantum is specified in microseconds.
@@ -116,105 +113,48 @@ sysctl_kern_quantum(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_kern, OID_AUTO, quantum, CTLTYPE_INT|CTLFLAG_RW,
        0, sizeof sched_quantum, sysctl_kern_quantum, "I", "");
 
-int 
-roundrobin_interval(void)
-{
-       return (sched_quantum);
-}
-
-/*
- * Force switch among equal priority processes every 100ms. 
- *
- * WARNING!  The MP lock is not held on ipi message remotes.
- */
-#ifdef SMP
-
-static void
-roundrobin_remote(void *arg)
-{
-       struct proc *p = lwkt_preempted_proc();
-       if (p == NULL || RTP_PRIO_NEED_RR(p->p_rtprio.type))
-               need_user_resched();
-}
-
-#endif
-
-static void
-roundrobin(void *arg)
-{
-       struct proc *p = lwkt_preempted_proc();
-       if (p == NULL || RTP_PRIO_NEED_RR(p->p_rtprio.type))
-               need_user_resched();
-#ifdef SMP
-       lwkt_send_ipiq_mask(mycpu->gd_other_cpus, roundrobin_remote, NULL);
-#endif
-       callout_reset(&roundrobin_callout, sched_quantum, roundrobin, NULL);
-}
-
-#ifdef SMP
-
-void
-resched_cpus(u_int32_t mask)
-{
-       lwkt_send_ipiq_mask(mask, roundrobin_remote, NULL);
-}
-
-#endif
-
-/*
- * The load average is scaled by FSCALE (2048 typ).  The estimated cpu is
- * incremented at a rate of ESTCPUFREQ per second (50hz typ), but this is
- * divided up across all cpu bound processes running in the system so an
- * individual process will get less under load.  ESTCPULIM typicaly caps
- * out at ESTCPUMAX (around 376, or 11 nice levels).
- *
- * Generally speaking the decay equation needs to break-even on growth
- * at the limit at all load levels >= 1.0, so if the estimated cpu for
- * a process increases by (ESTVCPUFREQ / load) per second, then the decay
- * should reach this value when estcpu reaches ESTCPUMAX.  That calculation
- * is:
- *
- *     ESTCPUMAX * decay = ESTCPUFREQ / load
- *     decay = ESTCPUFREQ / (load * ESTCPUMAX)
- *     decay = estcpu * 0.053 / load
- *
- * If the load is less then 1.0 we assume a load of 1.0.
- */
-
-#define cload(loadav)  ((loadav) < FSCALE ? FSCALE : (loadav))
-
-/* decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing */
-static fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */
-SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, "");
-
-/* kernel uses `FSCALE', userland (SHOULD) use kern.fscale */
-static int     fscale __unused = FSCALE;
-SYSCTL_INT(_kern, OID_AUTO, fscale, CTLFLAG_RD, 0, FSCALE, "");
-
 /*
  * If `ccpu' is not equal to `exp(-1/20)' and you still want to use the
  * faster/more-accurate formula, you'll have to estimate CCPU_SHIFT below
  * and possibly adjust FSHIFT in "param.h" so that (FSHIFT >= CCPU_SHIFT).
  *
  * To estimate CCPU_SHIFT for exp(-1/20), the following formula was used:
- *     1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits).
+ *     1 - exp(-1/20) ~= 0.0487 ~= 0.0488 == 1 (fixed pt, *11* bits).
  *
  * If you don't want to bother with the faster/more-accurate formula, you
  * can set CCPU_SHIFT to (FSHIFT + 1) which will use a slower/less-accurate
  * (more general) method of calculating the %age of CPU used by a process.
+ *
+ * decay 95% of `p_pctcpu' in 60 seconds; see CCPU_SHIFT before changing 
+ */
+#define CCPU_SHIFT     11
+
+static fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */
+SYSCTL_INT(_kern, OID_AUTO, ccpu, CTLFLAG_RD, &ccpu, 0, "");
+
+/*
+ * kernel uses `FSCALE', userland (SHOULD) use kern.fscale 
  */
-#define        CCPU_SHIFT      11
+static int     fscale __unused = FSCALE;
+SYSCTL_INT(_kern, OID_AUTO, fscale, CTLFLAG_RD, 0, FSCALE, "");
 
 /*
  * Recompute process priorities, once a second.
+ *
+ * Since the userland schedulers are typically event oriented, if the
+ * estcpu calculation at wakeup() time is not sufficient to make a
+ * process runnable relative to other processes in the system we have
+ * a 1-second recalc to help out.
+ *
+ * This code also allows us to store sysclock_t data in the process structure
+ * without fear of an overrun, since sysclock_t are guarenteed to hold 
+ * several seconds worth of count.
  */
 /* ARGSUSED */
 static void
 schedcpu(void *arg)
 {
-       fixpt_t loadfac = averunnable.ldavg[0];
        struct proc *p;
-       int ndecay;
 
        FOREACH_PROC_IN_SYSTEM(p) {
                /*
@@ -222,66 +162,19 @@ schedcpu(void *arg)
                 * (if sleeping).  We ignore overflow; with 16-bit int's
                 * (remember them?) overflow takes 45 days.
                 */
+               crit_enter();
                p->p_swtime++;
                if (p->p_stat == SSLEEP || p->p_stat == SSTOP)
                        p->p_slptime++;
-               p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT;
-
-               /*
-                * If the process has slept the entire second,
-                * stop recalculating its priority until it wakes up.
-                */
-               if (p->p_slptime > 1)
-                       continue;
-               /* prevent state changes and protect run queue */
-               crit_enter();
-
-               /*
-                * p_pctcpu is only for ps.
-                */
-#if    (FSHIFT >= CCPU_SHIFT)
-               p->p_pctcpu += (ESTCPUFREQ == 100)?
-                       ((fixpt_t) p->p_cpticks) << (FSHIFT - CCPU_SHIFT):
-                       100 * (((fixpt_t) p->p_cpticks)
-                               << (FSHIFT - CCPU_SHIFT)) / ESTCPUFREQ;
-#else
-               p->p_pctcpu += ((FSCALE - ccpu) *
-                       (p->p_cpticks * FSCALE / ESTCPUFREQ)) >> FSHIFT;
-#endif
-               /*
-                * A single cpu-bound process with a system load of 1.0 will
-                * increment cpticks by ESTCPUFREQ per second.  Scale
-                * cpticks by the load to normalize it relative to 
-                * ESTCPUFREQ.  This gives us an indication as to what
-                * proportional percentage of available cpu the process has
-                * used with a nominal range of 0 to ESTCPUFREQ.
-                *
-                * It should be noted that since the load average is a
-                * trailing indicator, a jump in the load will cause this
-                * calculation to be higher then normal.  This is desireable
-                * because it penalizes the processes responsible for the
-                * spike.
-                */
-               ndecay = (int)((p->p_cpticks * cload(loadfac)) >> FSHIFT);
 
                /*
-                * Reduce p_estcpu based on the amount of cpu that could
-                * have been used but wasn't.  Convert ndecay from the
-                * amount used to the amount not used, and scale with our
-                * nice value.
-                *
-                * The nice scaling determines how much the nice value
-                * effects the cpu the process gets.
+                * Only recalculate processes that are active or have slept
+                * less then 2 seconds.  The schedulers understand this.
                 */
-               ndecay = ESTCPUFREQ - ndecay;
-               ndecay -= p->p_nice * (ESTCPUMAX / 16) / PRIO_MAX;
-
-               p->p_cpticks = 0;
-               if (ndecay > 0) {
-                       if (ndecay > p->p_estcpu / 2)
-                               ndecay = p->p_estcpu / 2;
-                       p->p_estcpu -= ndecay;
-                       p->p_usched->resetpriority(p);
+               if (p->p_slptime <= 1) {
+                       p->p_usched->recalculate(p);
+               } else {
+                       p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT;
                }
                crit_exit();
        }
@@ -290,25 +183,26 @@ schedcpu(void *arg)
 }
 
 /*
- * Recalculate the priority of a process after it has slept for a while.
- * For all load averages >= 1 and max p_estcpu of 255, sleeping for at
- * least six times the loadfactor will decay p_estcpu to zero.
+ * This is only used by ps.  Generate a cpu percentage use over
+ * a period of one second.
  */
-static void
-updatepri(struct proc *p)
+void
+updatepcpu(struct proc *p, int cpticks, int ttlticks)
 {
-       int ndecay;
-
-       ndecay = p->p_slptime * ESTCPUFREQ;
-       if (ndecay > 0) {
-               if (p->p_estcpu > ndecay)
-                       p->p_estcpu -= ndecay;
-               else
-                       p->p_estcpu = 0;
-               p->p_usched->resetpriority(p);
+       fixpt_t acc;
+       int remticks;
+
+       acc = (cpticks << FSHIFT) / ttlticks;
+       if (ttlticks >= ESTCPUFREQ) {
+               p->p_pctcpu = acc;
+       } else {
+               remticks = ESTCPUFREQ - ttlticks;
+               p->p_pctcpu = (acc * ttlticks + p->p_pctcpu * remticks) /
+                               ESTCPUFREQ;
        }
 }
 
+
 /*
  * We're only looking at 7 bits of the address; everything is
  * aligned to 4, lots of things are aligned to greater powers
@@ -534,19 +428,13 @@ restart:
                        TAILQ_REMOVE(qp, td, td_threadq);
                        td->td_wchan = NULL;
                        if ((p = td->td_proc) != NULL && p->p_stat == SSLEEP) {
-                               /* OPTIMIZED EXPANSION OF setrunnable(p); */
-                               if (p->p_slptime > 1)
-                                       updatepri(p);
-                               p->p_slptime = 0;
                                p->p_stat = SRUN;
                                if (p->p_flag & P_INMEM) {
                                        /*
                                         * LWKT scheduled now, there is no
                                         * userland runq interaction until
                                         * the thread tries to return to user
-                                        * mode.
-                                        *
-                                        * setrunqueue(p); 
+                                        * mode.  We do NOT call setrunqueue().
                                         */
                                        lwkt_schedule(td);
                                } else {
@@ -667,18 +555,16 @@ setrunnable(struct proc *p)
        /*
         * The process is controlled by LWKT at this point, we do not mess
         * around with the userland scheduler until the thread tries to 
-        * return to user mode.
+        * return to user mode.  We do not clear p_slptime or call
+        * setrunqueue().
         */
-       if (p->p_flag & P_INMEM)
+       if (p->p_flag & P_INMEM) {
                lwkt_schedule(p->p_thread);
-       crit_exit();
-       if (p->p_slptime > 1)
-               updatepri(p);
-       p->p_slptime = 0;
-       if ((p->p_flag & P_INMEM) == 0) {
+       } else {
                p->p_flag |= P_SWAPINREQ;
                wakeup((caddr_t)&proc0);
        }
+       crit_exit();
 }
 
 /*
@@ -775,46 +661,10 @@ static void
 sched_setup(void *dummy)
 {
        callout_init(&loadav_callout);
-       callout_init(&roundrobin_callout);
        callout_init(&schedcpu_callout);
 
        /* Kick off timeout driven events by calling first time. */
-       roundrobin(NULL);
        schedcpu(NULL);
        loadav(NULL);
 }
 
-/*
- * We adjust the priority of the current process.  The priority of
- * a process gets worse as it accumulates CPU time.  The cpu usage
- * estimator (p_estcpu) is increased here.  resetpriority() will
- * compute a different priority each time p_estcpu increases by
- * INVERSE_ESTCPU_WEIGHT * (until MAXPRI is reached).
- *
- * The cpu usage estimator ramps up quite quickly when the process is 
- * running (linearly), and decays away exponentially, at a rate which
- * is proportionally slower when the system is busy.  The basic principle
- * is that the system will 90% forget that the process used a lot of CPU
- * time in 5 * loadav seconds.  This causes the system to favor processes
- * which haven't run much recently, and to round-robin among other processes.
- *
- * WARNING! called from a fast-int or an IPI, the MP lock MIGHT NOT BE HELD
- * and we cannot block.
- */
-void
-schedulerclock(void *dummy)
-{
-       struct thread *td;
-       struct proc *p;
-
-       td = curthread;
-       if ((p = td->td_proc) != NULL) {
-               p->p_cpticks++;         /* cpticks runs at ESTCPUFREQ */
-               p->p_estcpu = ESTCPULIM(p->p_estcpu + 1);
-               if (try_mplock()) {
-                       p->p_usched->resetpriority(p);
-                       rel_mplock();
-               }
-       }
-}
-
index ce79b5e..cc94e17 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)tty.c       8.8 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/tty.c,v 1.129.2.5 2002/03/11 01:32:31 dd Exp $
- * $DragonFly: src/sys/kern/tty.c,v 1.17 2005/06/06 15:02:28 dillon Exp $
+ * $DragonFly: src/sys/kern/tty.c,v 1.18 2005/06/27 18:37:57 dillon Exp $
  */
 
 /*-
@@ -2452,7 +2452,7 @@ ttyinfo(tp)
  *
  *     1) Only foreground processes are eligible - implied.
  *     2) Runnable processes are favored over anything else.  The runner
- *        with the highest cpu utilization is picked (p_estcpu).  Ties are
+ *        with the highest cpu utilization is picked (p_cpticks).  Ties are
  *        broken by picking the highest pid.
  *     3) The sleeper with the shortest sleep time is next.  With ties,
  *        we pick out just "short-term" sleepers (P_SINTR == 0).
@@ -2483,9 +2483,9 @@ proc_compare(p1, p2)
                /*
                 * tie - favor one with highest recent cpu utilization
                 */
-               if (p2->p_estcpu > p1->p_estcpu)
+               if (p2->p_cpticks > p1->p_cpticks)
                        return (1);
-               if (p1->p_estcpu > p2->p_estcpu)
+               if (p1->p_cpticks > p2->p_cpticks)
                        return (0);
                return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
        }
index 6ddabd1..fd2691f 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $
- * $DragonFly: src/sys/platform/pc32/include/smp.h,v 1.11 2004/03/01 06:33:16 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/include/smp.h,v 1.12 2005/06/27 18:37:55 dillon Exp $
  *
  */
 
@@ -109,7 +109,6 @@ int stop_cpus               (u_int);
 void   ap_init                 (void);
 int    restart_cpus            (u_int);
 void   forward_signal          (struct proc *);
-void   forward_roundrobin      (void);
 #ifdef APIC_INTR_REORDER
 void   set_lapic_isrloc        (int, int);
 #endif /* APIC_INTR_REORDER */
index 3ff577c..0dbb473 100644 (file)
@@ -55,7 +55,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/globaldata.h,v 1.11.2.1 2000/05/16 06:58:10 dillon Exp $
- * $DragonFly: src/sys/sys/globaldata.h,v 1.35 2005/03/27 19:25:10 dillon Exp $
+ * $DragonFly: src/sys/sys/globaldata.h,v 1.36 2005/06/27 18:37:59 dillon Exp $
  */
 
 #ifndef _SYS_GLOBALDATA_H_
@@ -139,7 +139,7 @@ struct globaldata {
        struct lwkt_ipiq *gd_ipiq;              /* array[ncpu] of ipiq's */
        struct lwkt_ipiq gd_cpusyncq;           /* ipiq for cpu synchro */
        short           gd_upri;                /* userland scheduler helper */
-       short           gd_unused01;
+       short           gd_rrcount;             /* userland scheduler helper */
        struct thread   gd_schedthread;         /* userland scheduler helper */
        struct thread   gd_idlethread;
        SLGlobalData    gd_slab;                /* slab allocator */
index f9b49d6..7fec237 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)proc.h      8.15 (Berkeley) 5/19/95
  * $FreeBSD: src/sys/sys/proc.h,v 1.99.2.9 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/sys/proc.h,v 1.60 2005/06/26 22:03:23 dillon Exp $
+ * $DragonFly: src/sys/sys/proc.h,v 1.61 2005/06/27 18:37:59 dillon Exp $
  */
 
 #ifndef _SYS_PROC_H_
@@ -63,6 +63,7 @@
 #ifdef _KERNEL
 #include <sys/globaldata.h>
 #endif
+#include <sys/systimer.h>
 #include <sys/usched.h>
 #include <machine/proc.h>              /* Machine-dependent proc substruct. */
 
@@ -167,9 +168,11 @@ struct     proc {
 
        struct vmspace  *p_vmspace;     /* Address space. */
 
-       /* scheduling */
-       u_int           p_estcpu;       /* Time averaged value of p_cpticks. */
-       int             p_cpticks;      /* Ticks of cpu time. */
+       /*
+        * Scheduling.
+        */
+       sysclock_t      p_cpticks;      /* cpu used in sched clock ticks */
+       sysclock_t      p_cpbase;       /* Measurement base */
        fixpt_t         p_pctcpu;       /* %cpu for this process */
        u_int           p_swtime;       /* Time swapped in or out. */
        u_int           p_slptime;      /* Time since last blocked. */
@@ -374,8 +377,6 @@ extern struct thread *pagethread, *updatethread;
  * the maximum ESTCPU value, and the weighting factor for nice values.  A
  * cpu bound program's estcpu will increase to ESTCPUMAX - 1.
  */
-#define ESTCPUMAX      128
-#define ESTCPULIM(v)   min((v), ESTCPUMAX)
 #define ESTCPUFREQ     50
 
 extern u_long ps_arg_cache_limit;
@@ -392,6 +393,7 @@ extern struct vm_zone *proc_zone;
 
 int    enterpgrp (struct proc *p, pid_t pgid, int mksess);
 void   fixjobc (struct proc *p, struct pgrp *pgrp, int entering);
+void   updatepcpu(struct proc *, int, int);
 int    inferior (struct proc *p);
 int    leavepgrp (struct proc *p);
 void   sess_hold(struct session *sp);
@@ -400,9 +402,6 @@ void        mi_switch (struct proc *p);
 void   procinit (void);
 void   relscurproc(struct proc *curp);
 int    p_trespass (struct ucred *cr1, struct ucred *cr2);
-int    roundrobin_interval (void);
-void   resched_cpus(u_int32_t mask);
-void   schedulerclock (void *dummy);
 void   setrunnable (struct proc *);
 void   clrrunnable (struct proc *, int stat);
 void   sleepinit (void);
index 40c89d8..68f4fe1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Userland scheduler API
  * 
- * $DragonFly: src/sys/sys/usched.h,v 1.3 2005/06/26 22:03:23 dillon Exp $
+ * $DragonFly: src/sys/sys/usched.h,v 1.4 2005/06/27 18:37:59 dillon Exp $
  */
 
 #ifndef _SYS_USCHED_H_
@@ -25,6 +25,8 @@ struct usched {
     void (*select_curproc)(struct globaldata *);
     void (*setrunqueue)(struct proc *);
     void (*remrunqueue)(struct proc *);
+    void (*schedulerclock)(struct proc *, sysclock_t, sysclock_t);
+    void (*recalculate)(struct proc *);
     void (*resetpriority)(struct proc *);
     void (*heuristic_forking)(struct proc *, struct proc *);
     void (*heuristic_exiting)(struct proc *, struct proc *);
@@ -38,7 +40,8 @@ union usched_data {
        short   priority;       /* lower is better */
        char    interactive;    /* (currently not used) */
        char    rqindex;
-       u_int   childscpu;
+       int     childscpu;
+       int     estcpu;         /* dynamic priority modification */
     } bsd4;
 
     int                pad[4];         /* PAD for future expansion */
index cb9ee45..5481994 100644 (file)
@@ -66,7 +66,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/vm/vm_pageout.c,v 1.151.2.15 2002/12/29 18:21:04 dillon Exp $
- * $DragonFly: src/sys/vm/vm_pageout.c,v 1.13 2005/06/25 20:03:32 dillon Exp $
+ * $DragonFly: src/sys/vm/vm_pageout.c,v 1.14 2005/06/27 18:38:00 dillon Exp $
  */
 
 /*
@@ -1163,7 +1163,6 @@ rescan0:
                }
                if (bigproc != NULL) {
                        killproc(bigproc, "out of swap space");
-                       bigproc->p_estcpu = 0;
                        bigproc->p_nice = PRIO_MIN;
                        bigproc->p_usched->resetpriority(bigproc);
                        wakeup(&vmstats.v_free_count);
index d4ab3e6..7fb0363 100644 (file)
@@ -32,7 +32,7 @@
  *
  * @(#)proc_compare.c  8.2 (Berkeley) 9/23/93
  *
- * $DragonFly: src/usr.bin/w/proc_compare.c,v 1.4 2003/11/21 22:46:15 dillon Exp $
+ * $DragonFly: src/usr.bin/w/proc_compare.c,v 1.5 2005/06/27 18:38:03 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -84,9 +84,9 @@ proc_compare(register struct proc *p1, register struct proc *p2)
                /*
                 * tie - favor one with highest recent cpu utilization
                 */
-               if (p2->p_estcpu > p1->p_estcpu)
+               if (p2->p_usdata.bsd4.estcpu > p1->p_usdata.bsd4.estcpu)
                        return (1);
-               if (p1->p_estcpu > p2->p_estcpu)
+               if (p1->p_usdata.bsd4.estcpu > p2->p_usdata.bsd4.estcpu)
                        return (0);
                return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
        }