vmm: Halt vcore 0 instead of spinning
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 20 Nov 2017 20:09:52 +0000 (15:09 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 22 Nov 2017 16:49:34 +0000 (11:49 -0500)
Spinning limits the sibling core's performance and limits the turbo mode
potential of the rest of the machine.

Instead, we'll mwait on notif_pending or an IPI.  Our ev_qs are already set
up to send IPIs with the notification, so things like syscalls and timers
will work fine.  If the 2LS enqueues a task thread - which are handled by
VC 0 - it'll make sure the vcore wakes up.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/vmm/sched.c

index a1f512a..32c420e 100644 (file)
@@ -297,12 +297,22 @@ static void __attribute__((noreturn)) vmm_sched_entry(void)
 {
        struct vmm_thread *vth;
 
-       if (sched_is_greedy())
+       if (sched_is_greedy()) {
                vth = sched_pick_thread_greedy();
-       else
+               if (!vth) {
+                       /* sys_halt_core will return, but we need to restart the vcore.  We
+                        * might have woke due to an event, and we'll need to handle_events
+                        * and other things dealt with by uthreads. */
+                       if (vcore_id() == 0)
+                               sys_halt_core(0);
+                       /* In greedy mode, yield will abort and we'll just restart */
+                       vcore_yield_or_restart();
+               }
+       } else {
                vth = sched_pick_thread_nice();
-       if (!vth)
-               vcore_yield_or_restart();
+               if (!vth)
+                       vcore_yield_or_restart();
+       }
        stats_run_vth(vth);
        run_uthread((struct uthread*)vth);
 }
@@ -754,6 +764,8 @@ static void enqueue_vmm_thread(struct vmm_thread *vth)
                spin_pdr_lock(&queue_lock);
                TAILQ_INSERT_TAIL(&rnbl_tasks, vth, tq_next);
                spin_pdr_unlock(&queue_lock);
+               if (sched_is_greedy())
+                       vcore_wake(0, false);
                break;
        default:
                panic("Bad vmm_thread type %p\n", vth->type);