Skip to content

Instantly share code, notes, and snippets.

@farhaven
Created October 23, 2012 10:28
Show Gist options
  • Save farhaven/3938075 to your computer and use it in GitHub Desktop.
Save farhaven/3938075 to your computer and use it in GitHub Desktop.
Index: arch/amd64/amd64/identcpu.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/identcpu.c,v
retrieving revision 1.41
diff -u -r1.41 identcpu.c
--- arch/amd64/amd64/identcpu.c 9 Oct 2012 09:16:09 -0000 1.41
+++ arch/amd64/amd64/identcpu.c 23 Oct 2012 10:27:44 -0000
@@ -210,6 +210,8 @@
void via_nano_setup(struct cpu_info *ci);
+void cpu_topology(struct cpu_info *ci);
+
void
via_nano_setup(struct cpu_info *ci)
{
@@ -479,4 +481,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.74
diff -u -r1.74 cpu.h
--- arch/amd64/include/cpu.h 9 Oct 2012 04:40:36 -0000 1.74
+++ arch/amd64/include/cpu.h 23 Oct 2012 10:27:44 -0000
@@ -102,6 +102,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.23
diff -u -r1.23 specialreg.h
--- arch/amd64/include/specialreg.h 9 Oct 2012 09:16:09 -0000 1.23
+++ arch/amd64/include/specialreg.h 23 Oct 2012 10:27:44 -0000
@@ -218,10 +218,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 23 Oct 2012 10:27:46 -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 23 Oct 2012 10:27:46 -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 23 Oct 2012 10:27:46 -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,19 @@
cpuset_add(&sched_idle_cpus, ci);
cpu_idle_enter();
- while (spc->spc_whichqs == 0) {
+
+ while (curcpu_is_idle()) {
if (spc->spc_schedflags & SPCF_SHOULDHALT &&
- (spc->spc_schedflags & SPCF_HALTED) == 0) {
+ (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);
+ 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 +232,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 +249,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 +280,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 +299,7 @@
spl0();
delay(10);
SCHED_LOCK(s);
- goto again;
- }
+ }
KASSERT(p);
p->p_stat = SRUN;
}
@@ -441,15 +437,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 +496,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 +539,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 23 Oct 2012 10:27:46 -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 23 Oct 2012 10:27:46 -0000
@@ -77,33 +77,20 @@
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) {
- /*
- * The process has already been through a roundrobin
- * without switching and may be hogging the CPU.
- * Indicate that the process should yield.
- */
- atomic_setbits_int(&spc->spc_schedflags,
- SPCF_SHOULDYIELD);
- } else {
- atomic_setbits_int(&spc->spc_schedflags,
- SPCF_SEENRR);
- }
+ atomic_setbits_int(&spc->spc_schedflags, SPCF_SHOULDYIELD);
}
if (spc->spc_nrun)
@@ -252,8 +239,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 +290,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 +319,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();
@@ -409,7 +397,7 @@
* Process is about to yield the CPU; clear the appropriate
* scheduling flags.
*/
- atomic_clearbits_int(&spc->spc_schedflags, SPCF_SWITCHCLEAR);
+ atomic_clearbits_int(&spc->spc_schedflags, SPCF_SHOULDYIELD);
nextproc = sched_chooseproc();
@@ -531,8 +519,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 +551,36 @@
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_usrpri + 1) * rrticks_init) << (voluntary ? 2 : 3);
+ // ((p->p_p->ps_nice + 1) * rrticks_init) << (voluntary? 2: 3);
+ struct timeval offset = {
+ .tv_sec = offset_msec / 1000,
+ .tv_usec = (offset_msec % 1000) * 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 23 Oct 2012 10:27:47 -0000
@@ -48,6 +48,7 @@
#include <sys/mutex.h> /* For struct mutex */
#include <sys/resource.h> /* For struct rusage */
#include <machine/atomic.h>
+#include <sys/tree.h>
#ifdef _KERNEL
#define __need_process
@@ -247,8 +248,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 +282,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 23 Oct 2012 10:27:47 -0000
@@ -69,7 +69,10 @@
#ifndef _SYS_SCHED_H_
#define _SYS_SCHED_H_
+#ifdef _KERNEL
#include <sys/queue.h>
+#include <sys/tree.h>
+#endif
/*
* Posix defines a <sched.h> which may want to include <sys/sched.h>
@@ -87,11 +90,9 @@
#define CP_IDLE 4
#define CPUSTATES 5
-#define SCHED_NQS 32 /* 32 run queues. */
-
+#ifdef _KERNEL
/*
* Per-CPU scheduler state.
- * XXX - expose to userland for now.
*/
struct schedstate_percpu {
struct timeval spc_runtime; /* time curproc started running */
@@ -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,27 +107,20 @@
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;
-
#ifdef notyet
struct proc *spc_reaper; /* dead proc reaper */
#endif
LIST_HEAD(,proc) spc_deadproc;
-};
-#ifdef _KERNEL
+ RB_HEAD(prochead, proc) spc_runq;
+};
/* spc_flags */
-#define SPCF_SEENRR 0x0001 /* process has seen roundrobin() */
-#define SPCF_SHOULDYIELD 0x0002 /* process should yield the CPU */
-#define SPCF_SWITCHCLEAR (SPCF_SEENRR|SPCF_SHOULDYIELD)
-#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 SPCF_SHOULDYIELD 0x0001 /* process should yield the CPU */
+#define SPCF_SHOULDHALT 0x0002 /* CPU should be vacated */
+#define SPCF_HALTED 0x0004 /* CPU has been halted */
+
+#define ESTCPULIM(e) min((e), PRIO_MAX)
extern int schedhz; /* ideally: 16 */
extern int rrticks_init; /* ticks per roundrobin() */
@@ -152,13 +145,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 *);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment