Refactor to move alloc stuff to corealloc.c (6/7)
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 29 Sep 2015 01:22:25 +0000 (18:22 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 24 Nov 2015 19:48:50 +0000 (14:48 -0500)
This commit moves the primary logic of the next_core() and sort_idles()
functions from schedule.c into corealloc.c. These are one off functions
to make 'pcoreid' the next core chosen by the core allocation algorithm
(so long as no provisioned cores are still idle), and to sort the idle
core list for debugging. These functions only really make sense for this
simple core request algorithm. We should revisit their usefulness once
we start to add in more sophisticated core allocation policies.

Signed-off-by: Kevin Klues <klueska@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/corerequest.h
kern/include/schedule.h
kern/src/corealloc.c
kern/src/monitor.c
kern/src/schedule.c

index 8db875a..74c91e8 100644 (file)
@@ -57,6 +57,13 @@ int __get_any_idle_core(void);
 int __get_specific_idle_core(int coreid);
 void __put_idle_core(int coreid);
 
+/* One off functions to make 'pcoreid' the next core chosen by the core
+ * allocation algorithm (so long as no provisioned cores are still idle), and
+ * to sort the idle core list for debugging. This code assumes that the
+ * scheduler that uses it holds a lock for the duration of the call. */
+void __next_core_to_alloc(uint32_t pcoreid);
+void __sort_idle_cores(void);
+
 /* Provision a core to proc p. This code assumes that the scheduler that uses
  * it holds a lock for the duration of the call. */
 void __provision_core(struct proc *p, struct sched_pcore *spc);
index 50415d0..5fc7c5a 100644 (file)
@@ -91,5 +91,5 @@ void sched_diag(void);
 void print_idlecoremap(void);
 void print_resources(struct proc *p);
 void print_all_resources(void);
-void next_core(uint32_t pcoreid);
-void sort_idles(void);
+void next_core_to_alloc(uint32_t pcoreid);
+void sort_idle_cores(void);
index 4493a8b..134f511 100644 (file)
@@ -160,3 +160,51 @@ void __put_idle_core(int coreid)
        assert((coreid >= 0) && (coreid < num_cores));
        TAILQ_INSERT_TAIL(&idlecores, spc, alloc_next);
 }
+
+/* One off function to make 'pcoreid' the next core chosen by the core
+ * allocation algorithm (so long as no provisioned cores are still idle).
+ * This code assumes that the scheduler that uses it holds a lock for the
+ * duration of the call. */
+void __next_core_to_alloc(uint32_t pcoreid)
+{
+       struct sched_pcore *spc_i;
+       bool match = FALSE;
+
+       TAILQ_FOREACH(spc_i, &idlecores, alloc_next) {
+               if (spc2pcoreid(spc_i) == pcoreid) {
+                       match = TRUE;
+                       break;
+               }
+       }
+       if (match) {
+               TAILQ_REMOVE(&idlecores, spc_i, alloc_next);
+               TAILQ_INSERT_HEAD(&idlecores, spc_i, alloc_next);
+               printk("Pcore %d will be given out next (from the idles)\n", pcoreid);
+       }
+}
+
+/* One off function to sort the idle core list for debugging in the kernel
+ * monitor. This code assumes that the scheduler that uses it holds a lock
+ * for the duration of the call. */
+void __sort_idle_cores(void)
+{
+       struct sched_pcore *spc_i, *spc_j, *temp;
+       struct sched_pcore_tailq sorter = TAILQ_HEAD_INITIALIZER(sorter);
+       bool added;
+
+       TAILQ_CONCAT(&sorter, &idlecores, alloc_next);
+       TAILQ_FOREACH_SAFE(spc_i, &sorter, alloc_next, temp) {
+               TAILQ_REMOVE(&sorter, spc_i, alloc_next);
+               added = FALSE;
+               /* don't need foreach_safe since we break after we muck with the list */
+               TAILQ_FOREACH(spc_j, &idlecores, alloc_next) {
+                       if (spc_i < spc_j) {
+                               TAILQ_INSERT_BEFORE(spc_j, spc_i, alloc_next);
+                               added = TRUE;
+                               break;
+                       }
+               }
+               if (!added)
+                       TAILQ_INSERT_TAIL(&idlecores, spc_i, alloc_next);
+       }
+}
index 05bf595..6b98e48 100644 (file)
@@ -1193,13 +1193,13 @@ usage:
        } else if (!strcmp(argv[1], "resources")) {
                print_all_resources();
        } else if (!strcmp(argv[1], "sort")) {
-               sort_idles();
+               sort_idle_cores();
        } else if (!strcmp(argv[1], "nc")) {
                if (argc != 3) {
                        printk("Need a pcore number.\n");
                        return 1;
                }
-               next_core(strtol(argv[2], 0, 0));
+               next_core_to_alloc(strtol(argv[2], 0, 0));
        } else {
                printk("Bad option %s\n", argv[1]);
                goto usage;
index fa976b3..a30a382 100644 (file)
@@ -579,8 +579,8 @@ static void __core_request(struct proc *p, uint32_t amt_needed)
                 * it must be provisioned to p, but not allocated to it. We need to try
                 * to preempt. After this block, the core will be track_dealloc'd and
                 * on the idle list (regardless of whether we had to preempt or not) */
-               if (spc_i->alloc_proc) {
-                       proc_to_preempt = spc_i->alloc_proc;
+               if (get_alloc_proc(spc_i)) {
+                       proc_to_preempt = get_alloc_proc(spc_i);
                        /* would break both preemption and maybe the later decref */
                        assert(proc_to_preempt != p);
                        /* need to keep a valid, external ref when we unlock */
@@ -596,7 +596,7 @@ static void __core_request(struct proc *p, uint32_t amt_needed)
                                 * idle CBs).  the core is not on the idle core list.  (if we
                                 * ever have proc alloc lists, it'll still be on the old proc's
                                 * list). */
-                               assert(spc_i->alloc_proc);
+                               assert(get_alloc_proc(spc_i));
                                /* regardless of whether or not it is still prov to p, we need
                                 * to note its dealloc.  we are doing some excessive checking of
                                 * p == prov_proc, but using this helper is a lot clearer. */
@@ -604,12 +604,12 @@ static void __core_request(struct proc *p, uint32_t amt_needed)
                        } else {
                                /* the preempt failed, which should only happen if the pcore was
                                 * unmapped (could be dying, could be yielding, but NOT
-                                * preempted).  whoever unmapped it also triggered (or will
-                                * soon trigger) a track_core_dealloc and put it on the idle
-                                * list.  Our signal for this is spc_i->alloc_proc being 0. We
-                                * need to spin and let whoever is trying to free the core grab
-                                * the ksched lock.  We could use an 'ignore_next_idle' flag
-                                * per sched_pcore, but it's not critical anymore.
+                                * preempted).  whoever unmapped it also triggered (or will soon
+                                * trigger) a track_core_dealloc and put it on the idle list.
+                                * Our signal for this is get_alloc_proc() being 0. We need to
+                                * spin and let whoever is trying to free the core grab the
+                                * ksched lock.  We could use an 'ignore_next_idle' flag per
+                                * sched_pcore, but it's not critical anymore.
                                 *
                                 * Note, we're relying on us being the only preemptor - if the
                                 * core was unmapped by *another* preemptor, there would be no
@@ -618,7 +618,7 @@ static void __core_request(struct proc *p, uint32_t amt_needed)
                                 * allocator, the pcore could have been put on the idle list and
                                 * then quickly removed/allocated. */
                                cmb();
-                               while (spc_i->alloc_proc) {
+                               while (get_alloc_proc(spc_i)) {
                                        /* this loop should be very rare */
                                        spin_unlock(&sched_lock);
                                        udelay(1);
@@ -629,7 +629,7 @@ static void __core_request(struct proc *p, uint32_t amt_needed)
                        proc_decref(proc_to_preempt);
                        /* might not be prov to p anymore (rare race).  spc_i is idle - we
                         * might get it later, or maybe we'll give it to its rightful proc*/
-                       if (spc_i->prov_proc != p)
+                       if (get_prov_proc(spc_i) != p)
                                continue;
                }
                /* At this point, the pcore is idle, regardless of how we got here
@@ -766,45 +766,16 @@ void print_all_resources(void)
        spin_unlock(&pid_hash_lock);
 }
 
-void next_core(uint32_t pcoreid)
+void next_core_to_alloc(uint32_t pcoreid)
 {
-       struct sched_pcore *spc_i;
-       bool match = FALSE;
        spin_lock(&sched_lock);
-       TAILQ_FOREACH(spc_i, &idlecores, alloc_next) {
-               if (spc2pcoreid(spc_i) == pcoreid) {
-                       match = TRUE;
-                       break;
-               }
-       }
-       if (match) {
-               TAILQ_REMOVE(&idlecores, spc_i, alloc_next);
-               TAILQ_INSERT_HEAD(&idlecores, spc_i, alloc_next);
-               printk("Pcore %d will be given out next (from the idles)\n", pcoreid);
-       }
+       __next_core_to_alloc(pcoreid);
        spin_unlock(&sched_lock);
 }
 
-void sort_idles(void)
+void sort_idle_cores(void)
 {
-       struct sched_pcore *spc_i, *spc_j, *temp;
-       struct sched_pcore_tailq sorter = TAILQ_HEAD_INITIALIZER(sorter);
-       bool added;
        spin_lock(&sched_lock);
-       TAILQ_CONCAT(&sorter, &idlecores, alloc_next);
-       TAILQ_FOREACH_SAFE(spc_i, &sorter, alloc_next, temp) {
-               TAILQ_REMOVE(&sorter, spc_i, alloc_next);
-               added = FALSE;
-               /* don't need foreach_safe since we break after we muck with the list */
-               TAILQ_FOREACH(spc_j, &idlecores, alloc_next) {
-                       if (spc_i < spc_j) {
-                               TAILQ_INSERT_BEFORE(spc_j, spc_i, alloc_next);
-                               added = TRUE;
-                               break;
-                       }
-               }
-               if (!added)
-                       TAILQ_INSERT_TAIL(&idlecores, spc_i, alloc_next);
-       }
+       __sort_idle_cores();
        spin_unlock(&sched_lock);
 }