Moves the idlecoremap to the ksched
[akaros.git] / kern / src / schedule.c
index 667d048..b86df8b 100644 (file)
@@ -17,6 +17,7 @@
 #include <assert.h>
 #include <atomic.h>
 #include <resource.h>
+#include <smp.h>
 #include <sys/queue.h>
 
 // This could be useful for making scheduling decisions.  
  * process is *really* running there. */
 struct proc *pcoremap[MAX_NUM_CPUS];
 
+/* Tracks which cores are idle, similar to the vcoremap.  Each value is the
+ * physical coreid of an unallocated core. */
+spinlock_t idle_lock = SPINLOCK_INITIALIZER;
+uint32_t idlecoremap[MAX_NUM_CPUS];
+uint32_t num_idlecores = 0;
+uint32_t num_mgmtcores = 1;
+
 void schedule_init(void)
 {
        TAILQ_INIT(&proc_runnablelist);
+
+       /* Ghetto old idle core init */
+       /* Init idle cores. Core 0 is the management core. */
+       spin_lock(&idle_lock);
+#ifdef __CONFIG_DISABLE_SMT__
+       /* assumes core0 is the only management core (NIC and monitor functionality
+        * are run there too.  it just adds the odd cores to the idlecoremap */
+       assert(!(num_cpus % 2));
+       // TODO: consider checking x86 for machines that actually hyperthread
+       num_idlecores = num_cpus >> 1;
+ #ifdef __CONFIG_ARSC_SERVER__
+       // Dedicate one core (core 2) to sysserver, might be able to share wit NIC
+       num_mgmtcores++;
+       assert(num_cpus >= num_mgmtcores);
+       send_kernel_message(2, (amr_t)arsc_server, 0,0,0, KMSG_ROUTINE);
+ #endif
+       for (int i = 0; i < num_idlecores; i++)
+               idlecoremap[i] = (i * 2) + 1;
+#else
+       // __CONFIG_DISABLE_SMT__
+       #ifdef __CONFIG_NETWORKING__
+       num_mgmtcores++; // Next core is dedicated to the NIC
+       assert(num_cpus >= num_mgmtcores);
+       #endif
+       #ifdef __CONFIG_APPSERVER__
+       #ifdef __CONFIG_DEDICATED_MONITOR__
+       num_mgmtcores++; // Next core dedicated to running the kernel monitor
+       assert(num_cpus >= num_mgmtcores);
+       // Need to subtract 1 from the num_mgmtcores # to get the cores index
+       send_kernel_message(num_mgmtcores-1, (amr_t)monitor, 0,0,0, KMSG_ROUTINE);
+       #endif
+       #endif
+ #ifdef __CONFIG_ARSC_SERVER__
+       // Dedicate one core (core 2) to sysserver, might be able to share with NIC
+       num_mgmtcores++;
+       assert(num_cpus >= num_mgmtcores);
+       send_kernel_message(num_mgmtcores-1, (amr_t)arsc_server, 0,0,0, KMSG_ROUTINE);
+ #endif
+       num_idlecores = num_cpus - num_mgmtcores;
+       for (int i = 0; i < num_idlecores; i++)
+               idlecoremap[i] = i + num_mgmtcores;
+#endif /* __CONFIG_DISABLE_SMT__ */
+       spin_unlock(&idle_lock);
        return;
 }
 
@@ -90,6 +141,50 @@ void schedule(void)
        return;
 }
 
+/* Helper function to return a core to the idlemap.  It causes some more lock
+ * acquisitions (like in a for loop), but it's a little easier.  Plus, one day
+ * we might be able to do this without locks (for the putting). */
+void put_idle_core(uint32_t coreid)
+{
+       spin_lock(&idle_lock);
+       idlecoremap[num_idlecores++] = coreid;
+       spin_unlock(&idle_lock);
+}
+
+/* Normally it'll be the max number of CG cores ever */
+uint32_t max_vcores(struct proc *p)
+{
+#ifdef __CONFIG_DISABLE_SMT__
+       return num_cpus >> 1;
+#else
+       return MAX(1, num_cpus - num_mgmtcores);
+#endif /* __CONFIG_DISABLE_SMT__ */
+}
+
+/* Ghetto old interface, hacked out of resource.c.  It doesn't even care about
+ * the proc yet, but in general the whole core_request bit needs reworked. */
+uint32_t proc_wants_cores(struct proc *p, uint32_t *pc_arr, uint32_t amt_new)
+{
+       uint32_t num_granted;
+       /* You should do something smarter than just giving the stuff out.  Like
+        * take in to account priorities, node locations, etc */
+       spin_lock(&idle_lock);
+       if (num_idlecores >= amt_new) {
+               for (int i = 0; i < amt_new; i++) {
+                       // grab the last one on the list
+                       pc_arr[i] = idlecoremap[num_idlecores - 1];
+                       num_idlecores--;
+               }
+               num_granted = amt_new;
+       } else {
+               /* In this case, you might want to preempt or do other fun things... */
+               num_granted = 0;
+       }
+       spin_unlock(&idle_lock);
+       return num_granted;
+}
+
+/************** Debugging **************/
 void dump_proclist(struct proc_list *list)
 {
        struct proc *p;
@@ -97,3 +192,12 @@ void dump_proclist(struct proc_list *list)
                printk("PID: %d\n", p->pid);
        return;
 }
+
+void print_idlecoremap(void)
+{
+       spin_lock(&idle_lock);
+       printk("There are %d idle cores.\n", num_idlecores);
+       for (int i = 0; i < num_idlecores; i++)
+               printk("idlecoremap[%d] = %d\n", i, idlecoremap[i]);
+       spin_unlock(&idle_lock);
+}