Hi people, after a (very) long time of silence on this, here's another go at it. This time, I basically started from scratch and used a bit of code by Christiano Haesberth which had been posted to tech@ a while ago to detect CPU topology on amd64 and take that into account when moving processes between CPUs.
This version has one single queue per CPU, getting rid of a) the one single system wide runqueue and b) the queue for expired processes. This simplifies things a bit and performs just as well as my previous versions (the only difference is the order in which expired procs get selected for running on a CPU). One advantage is that process selection is in O(log n) of the number of processes on the CPU and depends neither on the total number of processes nor the number of expired processes in the runqueue. The factors for the cost of moving a process between hardware threads, cpu dies and cpu packages are guesses now, I think those will have to be tuned further. Sadly, I haven't had access to a multiprocessor machine with a more diverse architecture than "a bunch of cores on the same die". I tested this on some more machines than before; a Core i5, an i7 and my Core 2 Duo and on all machines (perceived) interactivity was improved. The simplest benchmark I used was playing back a 1080p version of Big Buck Bunny with mplayer. All machines I tested on had Intel graphics cards, one GM965 (on the Core2Duo) and the others were Sandy Bridge devices. On all of them, playback was smoother with the i7 being most visible. With the default scheduler, watching the movie was a big pain due to heavy frame-dropping, with my patch, the movie was watchable (with frame dropping only (barely) noticable in scenes with much movement). As before, I'm looking forward to anything you have to comment, especially cool benchmark ideas or the like. -- Gregor Best Index: arch/amd64/amd64/identcpu.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/identcpu.c,v retrieving revision 1.39 diff -u -r1.39 identcpu.c --- arch/amd64/amd64/identcpu.c 19 Sep 2012 20:19:31 -0000 1.39 +++ arch/amd64/amd64/identcpu.c 4 Oct 2012 21:27:55 -0000 @@ -202,6 +202,8 @@ void via_nano_setup(struct cpu_info *ci); +void cpu_topology(struct cpu_info *ci); + void via_nano_setup(struct cpu_info *ci) { @@ -470,4 +472,123 @@ sensordev_install(&ci->ci_sensordev); #endif } + + cpu_topology(ci); +} + +/* + * Base 2 logarithm of an int. returns 0 for 0 (yeye, I know). + */ +static int +log2(unsigned int i) +{ + int ret = 0; + + while (i >>= 1) + ret++; + + return (ret); +} + +static int +mask_width(u_int x) +{ + int bit; + int mask; + int powerof2; + + powerof2 = ((x - 1) & x) == 0; + mask = (x << (1 - powerof2)) - 1; + + /* fls */ + if (mask == 0) + return (0); + for (bit = 1; mask != 1; bit++) + mask = (unsigned int)mask >> 1; + + return (bit); +} + +/* + * Build up cpu topology for given cpu, must run on the core itself. + */ +void +cpu_topology(struct cpu_info *ci) +{ + u_int32_t eax, ebx, ecx, edx; + u_int32_t apicid, max_apicid, max_coreid; + u_int32_t smt_bits, core_bits, pkg_bits; + u_int32_t smt_mask, core_mask, pkg_mask; + + /* We need at least apicid at CPUID 1 */ + CPUID(0, eax, ebx, ecx, edx); + if (eax < 1) + goto no_topology; + + /* Initial apicid */ + CPUID(1, eax, ebx, ecx, edx); + apicid = (ebx >> 24) & 0xff; + + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + /* We need at least apicid at CPUID 0x80000008 */ + CPUID(0x80000000, eax, ebx, ecx, edx); + if (eax < 0x80000008) + goto no_topology; + + CPUID(0x80000008, eax, ebx, ecx, edx); + core_bits = (ecx >> 12) & 0xf; + if (core_bits == 0) + goto no_topology; + /* So coreidsize 2 gives 3, 3 gives 7... */ + core_mask = (1 << core_bits) - 1; + /* Core id is the least significant considering mask */ + ci->ci_core_id = apicid & core_mask; + /* Pkg id is the upper remaining bits */ + ci->ci_pkg_id = apicid & ~core_mask; + ci->ci_pkg_id >>= core_bits; + } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + /* We only support leaf 1/4 detection */ + CPUID(0, eax, ebx, ecx, edx); + if (eax < 4) + goto no_topology; + /* Get max_apicid */ + CPUID(1, eax, ebx, ecx, edx); + max_apicid = (ebx >> 16) & 0xff; + /* Get max_coreid */ + CPUID2(4, 0, eax, ebx, ecx, edx); + max_coreid = ((eax >> 26) & 0x3f) + 1; + /* SMT */ + smt_bits = mask_width(max_apicid / max_coreid); + smt_mask = (1 << smt_bits) - 1; + /* Core */ + core_bits = log2(max_coreid); + core_mask = (1 << (core_bits + smt_bits)) - 1; + core_mask ^= smt_mask; + /* Pkg */ + pkg_bits = core_bits + smt_bits; + pkg_mask = -1 << core_bits; + + ci->ci_smt_id = apicid & smt_mask; + ci->ci_core_id = (apicid & core_mask) >> smt_bits; + ci->ci_pkg_id = (apicid & pkg_mask) >> pkg_bits; + } else + goto no_topology; +#ifdef DEBUG + printf("cpu%d: smt %u, core %u, pkg %u " + "(apicid 0x%x, max_apicid 0x%x, max_coreid 0x%x, smt_bits 0x%x, smt_mask 0x%x, " + "core_bits 0x%x, core_mask 0x%x, pkg_bits 0x%x, pkg_mask 0x%x)\n", + ci->ci_cpuid, ci->ci_smt_id, ci->ci_core_id, ci->ci_pkg_id, + apicid, max_apicid, max_coreid, smt_bits, smt_mask, core_bits, + core_mask, pkg_bits, pkg_mask); +#else + printf("cpu%d: smt %u, core %u, package %u\n", ci->ci_cpuid, + ci->ci_smt_id, ci->ci_core_id, ci->ci_pkg_id); + +#endif + return; + /* We can't map, so consider ci_core_id as ci_cpuid */ +no_topology: + ci->ci_smt_id = 0; + ci->ci_core_id = ci->ci_cpuid; + ci->ci_pkg_id = 0; } Index: arch/amd64/include/cpu.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/cpu.h,v retrieving revision 1.73 diff -u -r1.73 cpu.h --- arch/amd64/include/cpu.h 17 Apr 2012 16:02:33 -0000 1.73 +++ arch/amd64/include/cpu.h 4 Oct 2012 21:27:55 -0000 @@ -101,6 +101,11 @@ u_int32_t ci_cflushsz; u_int64_t ci_tsc_freq; +#define ARCH_HAVE_CPU_TOPOLOGY + u_int32_t ci_smt_id; + u_int32_t ci_core_id; + u_int32_t ci_pkg_id; + struct cpu_functions *ci_func; void (*cpu_setup)(struct cpu_info *); void (*ci_info)(struct cpu_info *); Index: arch/amd64/include/specialreg.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/specialreg.h,v retrieving revision 1.22 diff -u -r1.22 specialreg.h --- arch/amd64/include/specialreg.h 24 Aug 2012 02:49:23 -0000 1.22 +++ arch/amd64/include/specialreg.h 4 Oct 2012 21:27:55 -0000 @@ -209,10 +209,14 @@ #define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15) #define CPUID2STEPPING(cpuid) ((cpuid) & 15) -#define CPUID(code, eax, ebx, ecx, edx) \ +#define CPUID2(eax_code, ecx_code, eax, ebx, ecx, edx) \ __asm("cpuid" \ - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ - : "a" (code)); + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ + : "a" (eax_code), "c" (ecx_code)); + +#define CPUID(code, eax, ebx, ecx, edx) \ + CPUID2(code, 0, eax, ebx, ecx, edx) + #define CPUID_LEAF(code, leaf, eax, ebx, ecx, edx) \ __asm("cpuid" \ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ Index: kern/kern_clock.c =================================================================== RCS file: /cvs/src/sys/kern/kern_clock.c,v retrieving revision 1.75 diff -u -r1.75 kern_clock.c --- kern/kern_clock.c 2 Aug 2012 03:18:48 -0000 1.75 +++ kern/kern_clock.c 4 Oct 2012 21:27:58 -0000 @@ -233,7 +233,7 @@ if (stathz == 0) statclock(frame); - if (--ci->ci_schedstate.spc_rrticks <= 0) + if (p && (--(p->p_rrticks) <= 0)) roundrobin(ci); /* Index: kern/kern_proc.c =================================================================== RCS file: /cvs/src/sys/kern/kern_proc.c,v retrieving revision 1.48 diff -u -r1.48 kern_proc.c --- kern/kern_proc.c 10 Apr 2012 15:50:52 -0000 1.48 +++ kern/kern_proc.c 4 Oct 2012 21:27:58 -0000 @@ -398,8 +398,6 @@ p->p_comm, p->p_pid, pst, p->p_flag, P_BITS); (*pr)(" pri=%u, usrpri=%u, nice=%d\n", p->p_priority, p->p_usrpri, p->p_p->ps_nice); - (*pr)(" forw=%p, list=%p,%p\n", - TAILQ_NEXT(p, p_runq), p->p_list.le_next, p->p_list.le_prev); (*pr)(" process=%p user=%p, vmspace=%p\n", p->p_p, p->p_addr, p->p_vmspace); (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u, swtime=%u\n", Index: kern/kern_sched.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sched.c,v retrieving revision 1.27 diff -u -r1.27 kern_sched.c --- kern/kern_sched.c 10 Jul 2012 18:20:37 -0000 1.27 +++ kern/kern_sched.c 4 Oct 2012 21:27:58 -0000 @@ -24,11 +24,22 @@ #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/mutex.h> +#include <sys/tree.h> #include <uvm/uvm_extern.h> #include <sys/malloc.h> +static int +sched_cmp_proc(struct proc *a, struct proc *b) { + if (a == b) + return 0; + if (timercmp(&(a->p_deadline), &(b->p_deadline), <)) + return -1; + return 1; +} + +RB_GENERATE_STATIC(prochead, proc, p_runq, sched_cmp_proc); void sched_kthreads_create(void *); @@ -79,10 +90,8 @@ sched_init_cpu(struct cpu_info *ci) { struct schedstate_percpu *spc = &ci->ci_schedstate; - int i; - for (i = 0; i < SCHED_NQS; i++) - TAILQ_INIT(&spc->spc_qs[i]); + RB_INIT(&spc->spc_runq); spc->spc_idleproc = NULL; @@ -158,18 +167,17 @@ cpuset_add(&sched_idle_cpus, ci); cpu_idle_enter(); - while (spc->spc_whichqs == 0) { - if (spc->spc_schedflags & SPCF_SHOULDHALT && - (spc->spc_schedflags & SPCF_HALTED) == 0) { - cpuset_del(&sched_idle_cpus, ci); - SCHED_LOCK(s); - atomic_setbits_int(&spc->spc_schedflags, - spc->spc_whichqs ? 0 : SPCF_HALTED); - SCHED_UNLOCK(s); - wakeup(spc); - } - cpu_idle_cycle(); + + if (spc->spc_schedflags & SPCF_SHOULDHALT && + (spc->spc_schedflags & SPCF_HALTED) == 0) { + cpuset_del(&sched_idle_cpus, ci); + SCHED_LOCK(s); + atomic_setbits_int(&spc->spc_schedflags, SPCF_HALTED); + SCHED_UNLOCK(s); + wakeup(spc); } + cpu_idle_cycle(); + cpu_idle_leave(); cpuset_del(&sched_idle_cpus, ci); } @@ -222,14 +230,13 @@ setrunqueue(struct proc *p) { struct schedstate_percpu *spc; - int queue = p->p_priority >> 2; SCHED_ASSERT_LOCKED(); spc = &p->p_cpu->ci_schedstate; spc->spc_nrun++; - TAILQ_INSERT_TAIL(&spc->spc_qs[queue], p, p_runq); - spc->spc_whichqs |= (1 << queue); + KASSERT(!RB_FIND(prochead, &spc->spc_runq, p)); + RB_INSERT(prochead, &spc->spc_runq, p); cpuset_add(&sched_queued_cpus, p->p_cpu); if (cpuset_isset(&sched_idle_cpus, p->p_cpu)) @@ -240,38 +247,29 @@ remrunqueue(struct proc *p) { struct schedstate_percpu *spc; - int queue = p->p_priority >> 2; SCHED_ASSERT_LOCKED(); spc = &p->p_cpu->ci_schedstate; spc->spc_nrun--; - TAILQ_REMOVE(&spc->spc_qs[queue], p, p_runq); - if (TAILQ_EMPTY(&spc->spc_qs[queue])) { - spc->spc_whichqs &= ~(1 << queue); - if (spc->spc_whichqs == 0) - cpuset_del(&sched_queued_cpus, p->p_cpu); - } + KASSERT(RB_REMOVE(prochead, &spc->spc_runq, p)); + if (RB_EMPTY(&spc->spc_runq)) + cpuset_del(&sched_queued_cpus, p->p_cpu); } struct proc * sched_chooseproc(void) { struct schedstate_percpu *spc = &curcpu()->ci_schedstate; - struct proc *p; - int queue; + struct proc *p, *p_tmp = NULL; SCHED_ASSERT_LOCKED(); if (spc->spc_schedflags & SPCF_SHOULDHALT) { - if (spc->spc_whichqs) { - for (queue = 0; queue < SCHED_NQS; queue++) { - TAILQ_FOREACH(p, &spc->spc_qs[queue], p_runq) { - remrunqueue(p); - p->p_cpu = sched_choosecpu(p); - setrunqueue(p); - } - } + RB_FOREACH_SAFE(p, prochead, &spc->spc_runq, p_tmp) { + remrunqueue(p); + p->p_cpu = sched_choosecpu(p); + setrunqueue(p); } p = spc->spc_idleproc; KASSERT(p); @@ -280,17 +278,14 @@ return (p); } -again: - if (spc->spc_whichqs) { - queue = ffs(spc->spc_whichqs) - 1; - p = TAILQ_FIRST(&spc->spc_qs[queue]); + if (!RB_EMPTY(&spc->spc_runq)) { + p = RB_MIN(prochead, &spc->spc_runq); remrunqueue(p); sched_noidle++; KASSERT(p->p_stat == SRUN); } else if ((p = sched_steal_proc(curcpu())) == NULL) { - p = spc->spc_idleproc; - if (p == NULL) { - int s; + while ((p = spc->spc_idleproc) == NULL) { + int s; /* * We get here if someone decides to switch during * boot before forking kthreads, bleh. @@ -302,8 +297,7 @@ spl0(); delay(10); SCHED_LOCK(s); - goto again; - } + } KASSERT(p); p->p_stat = SRUN; } @@ -441,15 +435,13 @@ while ((ci = cpuset_first(&set)) != NULL) { struct proc *p; - int queue; int cost; cpuset_del(&set, ci); spc = &ci->ci_schedstate; - queue = ffs(spc->spc_whichqs) - 1; - TAILQ_FOREACH(p, &spc->spc_qs[queue], p_runq) { + RB_FOREACH(p, prochead, &spc->spc_runq) { if (p->p_flag & P_CPUPEG) continue; @@ -502,6 +494,10 @@ int sched_cost_priority = 1; int sched_cost_runnable = 3; int sched_cost_resident = 1; +#ifdef ARCH_HAVE_CPU_TOPOLOGY +int sched_cost_diffcore = 2; /* cost for moving to a different core */ +int sched_cost_diffpkg = 3; /* cost for moving to a different package */ +#endif int sched_proc_to_cpu_cost(struct cpu_info *ci, struct proc *p) @@ -541,6 +537,13 @@ log2(pmap_resident_count(p->p_vmspace->vm_map.pmap)); cost -= l2resident * sched_cost_resident; } + +#ifdef ARCH_HAVE_CPU_TOPOLOGY + if (p->p_cpu->ci_pkg_id != ci->ci_pkg_id) + cost *= sched_cost_diffpkg; + else if (p->p_cpu->ci_core_id != ci->ci_core_id) + cost *= sched_cost_diffcore; +#endif return (cost); } Index: kern/kern_synch.c =================================================================== RCS file: /cvs/src/sys/kern/kern_synch.c,v retrieving revision 1.104 diff -u -r1.104 kern_synch.c --- kern/kern_synch.c 21 Aug 2012 19:51:58 -0000 1.104 +++ kern/kern_synch.c 4 Oct 2012 21:27:58 -0000 @@ -205,7 +205,7 @@ p->p_wmesg = wmesg; p->p_slptime = 0; p->p_priority = prio & PRIMASK; - TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_runq); + TAILQ_INSERT_TAIL(&slpque[LOOKUP(ident)], p, p_slpq); } void @@ -342,7 +342,7 @@ unsleep(struct proc *p) { if (p->p_wchan) { - TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_runq); + TAILQ_REMOVE(&slpque[LOOKUP(p->p_wchan)], p, p_slpq); p->p_wchan = NULL; } } @@ -361,7 +361,7 @@ SCHED_LOCK(s); qp = &slpque[LOOKUP(ident)]; for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) { - pnext = TAILQ_NEXT(p, p_runq); + pnext = TAILQ_NEXT(p, p_slpq); #ifdef DIAGNOSTIC if (p->p_stat != SSLEEP && p->p_stat != SSTOP) panic("wakeup: p_stat is %d", (int)p->p_stat); @@ -369,7 +369,7 @@ if (p->p_wchan == ident) { --n; p->p_wchan = 0; - TAILQ_REMOVE(qp, p, p_runq); + TAILQ_REMOVE(qp, p, p_slpq); if (p->p_stat == SSLEEP) setrunnable(p); } Index: kern/sched_bsd.c =================================================================== RCS file: /cvs/src/sys/kern/sched_bsd.c,v retrieving revision 1.30 diff -u -r1.30 sched_bsd.c --- kern/sched_bsd.c 9 Jul 2012 17:27:32 -0000 1.30 +++ kern/sched_bsd.c 4 Oct 2012 21:27:58 -0000 @@ -77,20 +77,18 @@ timeout_set(&schedcpu_to, schedcpu, &schedcpu_to); - rrticks_init = hz / 10; + rrticks_init = hz / 20; schedcpu(&schedcpu_to); } /* - * Force switch among equal priority processes every 100ms. + * Force switch among equal priority processes every 50ms. */ void roundrobin(struct cpu_info *ci) { struct schedstate_percpu *spc = &ci->ci_schedstate; - spc->spc_rrticks = rrticks_init; - if (ci->ci_curproc != NULL) { if (spc->spc_schedflags & SPCF_SEENRR) { /* @@ -252,8 +250,7 @@ resetpriority(p); if (p->p_priority >= PUSER) { if (p->p_stat == SRUN && - (p->p_priority / SCHED_PPQ) != - (p->p_usrpri / SCHED_PPQ)) { + p->p_priority == p->p_usrpri) { remrunqueue(p); p->p_priority = p->p_usrpri; setrunqueue(p); @@ -304,6 +301,7 @@ SCHED_LOCK(s); p->p_priority = p->p_usrpri; p->p_stat = SRUN; + generate_deadline(p, 1); setrunqueue(p); p->p_ru.ru_nvcsw++; mi_switch(); @@ -332,6 +330,7 @@ p->p_priority = p->p_usrpri; p->p_stat = SRUN; p->p_cpu = sched_choosecpu(p); + generate_deadline(p, 0); setrunqueue(p); p->p_ru.ru_nivcsw++; mi_switch(); @@ -531,8 +530,7 @@ SCHED_ASSERT_LOCKED(); - newpriority = PUSER + p->p_estcpu + - NICE_WEIGHT * (p->p_p->ps_nice - NZERO); + newpriority = PUSER + p->p_estcpu + (p->p_p->ps_nice - NZERO); newpriority = min(newpriority, MAXPRI); p->p_usrpri = newpriority; resched_proc(p, p->p_usrpri); @@ -564,4 +562,33 @@ if (p->p_priority >= PUSER) p->p_priority = p->p_usrpri; SCHED_UNLOCK(s); +} + +void +generate_deadline(struct proc *p, char voluntary) { + /* + * For nice values between 0 and 39 inclusively, the offset lies between + * 32 and 1280 milliseconds for a machine with hz=100. That means that + * processes with nice value=0 (i.e. -20 in userland) will be executed + * 32 milliseconds in the future at the latest. Processes with very + * little priority will be executed 1.28 seconds in the future at the very + * latest. The shift is done to ensure that the lowest possible offset is + * larger than the timeslice, in order to make sure that the scheduler does + * not degenerate to round robin behaviour when more than just a few processes + * with high priority are started. + * + * If the process voluntarily yielded its CPU, we reward it by halving its + * deadline offset. + */ + unsigned int offset_msec = ((p->p_p->ps_nice + 1) * rrticks_init) << (voluntary ? 2 : 3); + struct timeval offset = { + .tv_sec = offset_msec / 1000, + .tv_usec = offset_msec % 1000 + }; + struct timeval now; + microuptime(&now); + + timeradd(&now, &offset, &(p->p_deadline)); + if (!voluntary) + p->p_rrticks = rrticks_init; } Index: sys/proc.h =================================================================== RCS file: /cvs/src/sys/sys/proc.h,v retrieving revision 1.163 diff -u -r1.163 proc.h --- sys/proc.h 11 Sep 2012 15:44:19 -0000 1.163 +++ sys/proc.h 4 Oct 2012 21:27:58 -0000 @@ -247,8 +247,9 @@ #define PS_EXITING _P_EXITING struct proc { - TAILQ_ENTRY(proc) p_runq; + TAILQ_ENTRY(proc) p_slpq; LIST_ENTRY(proc) p_list; /* List of all processes. */ + RB_ENTRY(proc) p_runq; struct process *p_p; /* The process of this thread. */ TAILQ_ENTRY(proc) p_thr_link;/* Threads in a process linkage. */ @@ -280,6 +281,8 @@ int p_sigwait; /* signal handled by sigwait() */ /* scheduling */ + int p_rrticks; + struct timeval p_deadline; u_int p_estcpu; /* Time averaged value of p_cpticks. */ int p_cpticks; /* Ticks of cpu time. */ fixpt_t p_pctcpu; /* %cpu for this process during p_swtime */ Index: sys/sched.h =================================================================== RCS file: /cvs/src/sys/sys/sched.h,v retrieving revision 1.30 diff -u -r1.30 sched.h --- sys/sched.h 16 Nov 2011 20:50:19 -0000 1.30 +++ sys/sched.h 4 Oct 2012 21:27:58 -0000 @@ -70,6 +70,7 @@ #define _SYS_SCHED_H_ #include <sys/queue.h> +#include <sys/tree.h> /* * Posix defines a <sched.h> which may want to include <sys/sched.h> @@ -99,7 +100,6 @@ u_int spc_schedticks; /* ticks for schedclock() */ u_int64_t spc_cp_time[CPUSTATES]; /* CPU state statistics */ u_char spc_curpriority; /* usrpri of curproc */ - int spc_rrticks; /* ticks until roundrobin() */ int spc_pscnt; /* prof/stat counter */ int spc_psdiv; /* prof/stat divisor */ struct proc *spc_idleproc; /* idle proc for this cpu */ @@ -107,8 +107,7 @@ u_int spc_nrun; /* procs on the run queues */ fixpt_t spc_ldavg; /* shortest load avg. for this cpu */ - TAILQ_HEAD(prochead, proc) spc_qs[SCHED_NQS]; - volatile uint32_t spc_whichqs; + RB_HEAD(prochead, proc) spc_runq; #ifdef notyet struct proc *spc_reaper; /* dead proc reaper */ @@ -125,9 +124,7 @@ #define SPCF_SHOULDHALT 0x0004 /* CPU should be vacated */ #define SPCF_HALTED 0x0008 /* CPU has been halted */ -#define SCHED_PPQ (128 / SCHED_NQS) /* priorities per queue */ -#define NICE_WEIGHT 2 /* priorities per nice level */ -#define ESTCPULIM(e) min((e), NICE_WEIGHT * PRIO_MAX - SCHED_PPQ) +#define ESTCPULIM(e) min((e), PRIO_MAX) extern int schedhz; /* ideally: 16 */ extern int rrticks_init; /* ticks per roundrobin() */ @@ -152,13 +149,14 @@ void cpu_idle_cycle(void); void cpu_idle_leave(void); void sched_peg_curproc(struct cpu_info *ci); +void generate_deadline(struct proc *, char); #ifdef MULTIPROCESSOR void sched_start_secondary_cpus(void); void sched_stop_secondary_cpus(void); #endif -#define curcpu_is_idle() (curcpu()->ci_schedstate.spc_whichqs == 0) +#define curcpu_is_idle() (RB_EMPTY(&curcpu()->ci_schedstate.spc_runq)) void sched_init_runqueues(void); void setrunqueue(struct proc *);