alarm: Do not hold the tchain lock during handlers
[akaros.git] / kern / src / schedule.c
index 2490c52..4804885 100644 (file)
@@ -16,6 +16,7 @@
 #include <alarm.h>
 #include <sys/queue.h>
 #include <arsc_server.h>
+#include <hashtable.h>
 
 /* Process Lists.  'unrunnable' is a holding list for SCPs that are running or
  * waiting or otherwise not considered for sched decisions. */
@@ -78,12 +79,6 @@ static void set_ksched_alarm(void)
        set_alarm(&per_cpu_info[core_id()].tchain, &ksched_waiter);
 }
 
-/* Need a kmsg to just run the sched, but not to rearm */
-static void __just_sched(uint32_t srcid, long a0, long a1, long a2)
-{
-       run_scheduler();
-}
-
 /* RKM alarm, to run the scheduler tick (not in interrupt context) and reset the
  * alarm.  Note that interrupts will be disabled, but this is not the same as
  * interrupt context.  We're a routine kmsg, which means the core is in a
@@ -92,10 +87,12 @@ static void __ksched_tick(struct alarm_waiter *waiter)
 {
        /* TODO: imagine doing some accounting here */
        run_scheduler();
-       /* Set our alarm to go off, incrementing from our last tick (instead of
-        * setting it relative to now, since some time has passed since the alarm
-        * first went off.  Note, this may be now or in the past! */
-       set_awaiter_inc(&ksched_waiter, TIMER_TICK_USEC);
+       /* Set our alarm to go off, relative to now.  This means we might lag a bit,
+        * and our ticks won't match wall clock time.  But if we do incremental,
+        * we'll actually punish the next process because the kernel took too long
+        * for the previous process.  Ultimately, if we really care, we should
+        * account for the actual time used. */
+       set_awaiter_rel(&ksched_waiter, TIMER_TICK_USEC);
        set_alarm(&per_cpu_info[core_id()].tchain, &ksched_waiter);
 }
 
@@ -109,6 +106,9 @@ void schedule_init(void)
        spin_unlock(&sched_lock);
 
 #ifdef CONFIG_ARSC_SERVER
+       /* Most likely we'll have a syscall and a process that dedicates itself to
+        * running this.  Or if it's a kthread, we don't need a core. */
+       #error "Find a way to get a core.  Probably a syscall to run a server."
        int arsc_coreid = get_any_idle_core();
        assert(arsc_coreid >= 0);
        send_kernel_message(arsc_coreid, arsc_server, 0, 0, 0, KMSG_ROUTINE);
@@ -247,10 +247,6 @@ void __sched_scp_wakeup(struct proc *p)
        if (!management_core()) {
                /* TODO: pick a better core and only send if halted.
                 *
-                * FYI, a POKE on x86 might lose a rare race with halt code, since the
-                * poke handler does not abort halts.  if this happens, the next timer
-                * IRQ would wake up the core.
-                *
                 * ideally, we'd know if a specific mgmt core is sleeping and wake it
                 * up.  o/w, we could interrupt an already-running mgmt core that won't
                 * get to our new proc anytime soon.  also, by poking core 0, a
@@ -299,8 +295,7 @@ static bool __schedule_scp(void)
                        /* process might be dying, with a KMSG to clean it up waiting on
                         * this core.  can't do much, so we'll attempt to restart */
                        if (proc_is_dying(pcpui->owning_proc)) {
-                               send_kernel_message(core_id(), __just_sched, 0, 0, 0,
-                                                   KMSG_ROUTINE);
+                               run_as_rkm(run_scheduler);
                                spin_unlock(&pcpui->owning_proc->proc_lock);
                                return FALSE;
                        }
@@ -497,30 +492,6 @@ 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)
-{
-       spin_lock(&sched_lock);
-       int ret = __get_any_idle_core();
-       spin_unlock(&sched_lock);
-       return ret;
-}
-
-int get_specific_idle_core(int coreid)
-{
-       spin_lock(&sched_lock);
-       int ret = __get_specific_idle_core(coreid);
-       spin_unlock(&sched_lock);
-       return ret;
-}
-
-/* similar to __sched_put_idle_core, but without the prov tracking */
-void put_idle_core(int coreid)
-{
-       spin_lock(&sched_lock);
-       __put_idle_core(coreid);
-       spin_unlock(&sched_lock);
-}
-
 /* This deals with a request for more cores.  The amt of new cores needed is
  * passed in.  The ksched lock is held, but we are free to unlock if we want
  * (and we must, if calling out of the ksched to anything high-level).