summaryrefslogtreecommitdiffstats
path: root/sys/kern/sched_4bsd.c
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>2004-09-03 07:42:31 +0000
committerjulian <julian@FreeBSD.org>2004-09-03 07:42:31 +0000
commit373bbfc18445a9c3d361d56b73a25f76cbb6fb62 (patch)
treee4c143c3e33969a9055f5fb7df29532156d2a7ea /sys/kern/sched_4bsd.c
parentee581aec84758a98f561f58a0da3f17a02c9a97a (diff)
downloadFreeBSD-src-373bbfc18445a9c3d361d56b73a25f76cbb6fb62.zip
FreeBSD-src-373bbfc18445a9c3d361d56b73a25f76cbb6fb62.tar.gz
Move 4bsd specific experimental IP code into the 4bsd file.
Move the sysctls into kern.sched
Diffstat (limited to 'sys/kern/sched_4bsd.c')
-rw-r--r--sys/kern/sched_4bsd.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index 043514b..8175b9e 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -101,6 +101,7 @@ static void sched_setup(void *dummy);
static void maybe_resched(struct thread *td);
static void updatepri(struct ksegrp *kg);
static void resetpriority(struct ksegrp *kg);
+static int forward_wakeup(int cpunum);
static struct kproc_desc sched_kp = {
"schedcpu",
@@ -160,6 +161,44 @@ SYSCTL_PROC(_kern_sched, OID_AUTO, quantum, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof sched_quantum, sysctl_kern_quantum, "I",
"Roundrobin scheduling quantum in microseconds");
+/* Enable forwarding of wakeups to all other cpus */
+SYSCTL_NODE(_kern_sched, OID_AUTO, ipiwakeup, CTLFLAG_RD, NULL, "Kernel SMP");
+
+static int forward_wakeup_enabled = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, enabled, CTLFLAG_RW,
+ &forward_wakeup_enabled, 0,
+ "Forwarding of wakeup to idle CPUs");
+
+static int forward_wakeups_requested = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, requested, CTLFLAG_RD,
+ &forward_wakeups_requested, 0,
+ "Requests for Forwarding of wakeup to idle CPUs");
+
+static int forward_wakeups_delivered = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, delivered, CTLFLAG_RD,
+ &forward_wakeups_delivered, 0,
+ "Completed Forwarding of wakeup to idle CPUs");
+
+static int forward_wakeup_use_mask = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, usemask, CTLFLAG_RW,
+ &forward_wakeup_use_mask, 0,
+ "Use the mask of idle cpus");
+
+static int forward_wakeup_use_loop = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, useloop, CTLFLAG_RW,
+ &forward_wakeup_use_loop, 0,
+ "Use a loop to find idle cpus");
+
+static int forward_wakeup_use_single = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, onecpu, CTLFLAG_RW,
+ &forward_wakeup_use_single, 0,
+ "Only signal one idle cpu");
+
+static int forward_wakeup_use_htt = 0;
+SYSCTL_INT(_kern_sched_ipiwakeup, OID_AUTO, htt2, CTLFLAG_RW,
+ &forward_wakeup_use_htt, 0,
+ "account for htt");
+
/*
* Arrange to reschedule if necessary, taking the priorities and
* schedulers into account.
@@ -694,6 +733,93 @@ sched_wakeup(struct thread *td)
setrunqueue(td, SRQ_BORING);
}
+/* enable HTT_2 if you have a 2-way HTT cpu.*/
+static int
+forward_wakeup(int cpunum)
+{
+ cpumask_t map, me, dontuse;
+ cpumask_t map2;
+ struct pcpu *pc;
+ cpumask_t id, map3;
+
+ mtx_assert(&sched_lock, MA_OWNED);
+
+ CTR0(KTR_SMP, "forward_wakeup()");
+
+ if ((!forward_wakeup_enabled) ||
+ (forward_wakeup_use_mask == 0 && forward_wakeup_use_loop == 0))
+ return (0);
+ if (!smp_started || cold || panicstr)
+ return (0);
+
+ forward_wakeups_requested++;
+
+/*
+ * check the idle mask we received against what we calculated before
+ * in the old version.
+ */
+ me = PCPU_GET(cpumask);
+ /*
+ * don't bother if we should be doing it ourself..
+ */
+ if ((me & idle_cpus_mask) && (cpunum == NOCPU || me == (1 << cpunum)))
+ return (0);
+
+ dontuse = me | stopped_cpus | hlt_cpus_mask;
+ map3 = 0;
+ if (forward_wakeup_use_loop) {
+ SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ id = pc->pc_cpumask;
+ if ( (id & dontuse) == 0 &&
+ pc->pc_curthread == pc->pc_idlethread) {
+ map3 |= id;
+ }
+ }
+ }
+
+ if (forward_wakeup_use_mask) {
+ map = 0;
+ map = idle_cpus_mask & ~dontuse;
+
+ /* If they are both on, compare and use loop if different */
+ if (forward_wakeup_use_loop) {
+ if (map != map3) {
+ printf("map (%02X) != map3 (%02X)\n",
+ map, map3);
+ map = map3;
+ }
+ }
+ } else {
+ map = map3;
+ }
+ /* If we only allow a specific CPU, then mask off all the others */
+ if (cpunum != NOCPU) {
+ KASSERT((cpunum <= mp_maxcpus),("forward_wakeup: bad cpunum."));
+ map &= (1 << cpunum);
+ } else {
+ /* Try choose an idle die. */
+ if (forward_wakeup_use_htt) {
+ map2 = (map & (map >> 1)) & 0x5555;
+ if (map2) {
+ map = map2;
+ }
+ }
+
+ /* set only one bit */
+ if (forward_wakeup_use_single) {
+ map = map & ((~map) + 1);
+ }
+ }
+ if (map) {
+ forward_wakeups_delivered++;
+ ipi_selected(map, IPI_AST);
+ return (1);
+ }
+ if (cpunum == NOCPU)
+ printf("forward_wakeup: Idle processor not found\n");
+ return (0);
+}
+
void
sched_add(struct thread *td, int flags)
{
OpenPOWER on IntegriCloud