Adds interfaces to get/put CG cores for the kernel
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 6 Jan 2015 17:55:38 +0000 (12:55 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 6 Jan 2015 20:04:04 +0000 (15:04 -0500)
For things like the ARSCs, NIX mode, or whatever else you want.  This takes a
core out of the idle list, meaning MCPs will not receive them.

If a core was idle (unallocated) but provisioned, these interfaces will not
choose those cores.  It would mess up other parts of the ksched.

kern/include/schedule.h
kern/src/schedule.c

index da56045..0220893 100644 (file)
@@ -78,6 +78,16 @@ void cpu_bored(void);
  * inappropriate, since we need to know which specific core is now free. */
 void avail_res_changed(int res_type, long change);
 
+/* Get and put idle CG cores.  Getting a core removes it from the idle list, and
+ * the kernel can do whatever it wants with it.  All this means is that the
+ * ksched won't hand out that core to a process.  This will not give out
+ * provisioned cores.
+ *
+ * The gets return the coreid on success, -1 or -error on failure. */
+int get_any_idle_core(void);
+int get_this_idle_core(int coreid);
+void put_idle_core(int coreid);
+
 /************** Proc's view of the world **************/
 /* How many vcores p will think it can have */
 uint32_t max_vcores(struct proc *p);
index ceff708..280e74f 100644 (file)
@@ -580,6 +580,61 @@ void avail_res_changed(int res_type, long change)
        printk("[kernel] ksched doesn't track any resources yet!\n");
 }
 
+int get_any_idle_core(void)
+{
+       struct sched_pcore *spc;
+       int ret = -1;
+       spin_lock(&sched_lock);
+       while ((spc = TAILQ_FIRST(&idlecores))) {
+               /* Don't take cores that are provisioned to a process */
+               if (spc->prov_proc)
+                       continue;
+               assert(!spc->alloc_proc);
+               TAILQ_REMOVE(&idlecores, spc, alloc_next);
+               ret = spc2pcoreid(spc);
+               break;
+       }
+       spin_unlock(&sched_lock);
+       return ret;
+}
+
+/* TODO: if we end up using this a lot, track CG-idleness as a property of the
+ * SPC instead of doing a linear search. */
+static bool __spc_is_idle(struct sched_pcore *spc)
+{
+       struct sched_pcore *i;
+       TAILQ_FOREACH(i, &idlecores, alloc_next) {
+               if (spc == i)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
+int get_this_idle_core(int coreid)
+{
+       struct sched_pcore *spc = pcoreid2spc(coreid);
+       int ret = -1;
+       assert((0 <= coreid) && (coreid < num_cpus));
+       spin_lock(&sched_lock);
+       if (__spc_is_idle(pcoreid2spc(coreid)) && !spc->prov_proc) {
+               assert(!spc->alloc_proc);
+               TAILQ_REMOVE(&idlecores, spc, alloc_next);
+               ret = coreid;
+       }
+       spin_unlock(&sched_lock);
+       return ret;
+}
+
+/* similar to __sched_put_idle_core, but without the prov tracking */
+void put_idle_core(int coreid)
+{
+       struct sched_pcore *spc = pcoreid2spc(coreid);
+       assert((0 <= coreid) && (coreid < num_cpus));
+       spin_lock(&sched_lock);
+       TAILQ_INSERT_TAIL(&idlecores, spc, alloc_next);
+       spin_unlock(&sched_lock);
+}
+
 /* Normally it'll be the max number of CG cores ever */
 uint32_t max_vcores(struct proc *p)
 {