Exp: per-core runqueues and timer ticks
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 20 Apr 2010 18:03:25 +0000 (11:03 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:43 +0000 (17:35 -0700)
This is for the experiment with traditional style process work.  There
are per-core runqueues and a local timer tick to call a basic schedule
function (FCFS).  It's all #ifdef'd by __CONFIG_EXPER_TRADPROC__.

Makeconfig
Makelocal.template
kern/arch/i686/smp_boot.c
kern/arch/i686/trap.c
kern/arch/sparc/smp.c
kern/arch/sparc/timer.c
kern/arch/sparc/timer.h
kern/include/smp.h
kern/include/trap.h
kern/src/smp.c
kern/src/timer.c

index a60d038..89127c3 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_E1000_MMIO_HACK:=           -D__CONFIG_E1000_MMIO_HACK__
 CONFIG_E1000_ON_BOXBORO:=          -DE1000_MMIO_ADDR=0x9bb20000
 CONFIG_E1000_ON_S142:=             -DE1000_MMIO_ADDR=0xfbee0000
 CONFIG_DISABLE_MPTABLES:=          -D__CONFIG_DISABLE_MPTABLES__
+CONFIG_EXPER_TRADPROC:=            -D__CONFIG_EXPER_TRADPROC__
 
 # Userspace configuration parameters
 # By default, each of these options will be turned off
index 88b2695..37adece 100644 (file)
 #KERN_CFLAGS += $(CONFIG_PAGE_COLORING)
 #KERN_CFLAGS += $(CONFIG_APPSERVER)
 #KERN_CFLAGS += $(CONFIG_DEMAND_PAGING)
+#KERN_CFLAGS += $(CONFIG_NOMTRRS)
+#KERN_CFLAGS += $(CONFIG_E1000_MMIO_HACK)
+#KERN_CFLAGS += $(CONFIG_E1000_ON_BOXBORO)
+#KERN_CFLAGS += $(CONFIG_E1000_ON_S142)
+#KERN_CFLAGS += $(CONFIG_DISABLE_MPTABLES)
+#KERN_CFLAGS += $(CONFIG_EXPER_TRADPROC))
 #KERN_CFLAGS += -DDEVELOPER_NAME=waterman
 #KERN_CFLAGS += -DDEVELOPER_NAME=brho
 
index 2cd0eab..7a290ca 100644 (file)
@@ -311,4 +311,12 @@ void smp_percpu_init(void)
        STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
        spinlock_init(&per_cpu_info[coreid].routine_amsg_lock);
        STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
+#ifdef __CONFIG_EXPER_TRADPROC__
+       spinlock_init(&per_cpu_info[coreid].runqueue_lock);
+       TAILQ_INIT(&per_cpu_info[coreid].runqueue);
+       /* set a per-core timer interrupt to go off and call local_schedule every
+        * TIMER_uSEC microseconds.  The handler is registered independently of
+        * EXPER_TRADPROC, in line with what sparc does. */
+       lapic_set_timer(TIMER_uSEC, TRUE);
+#endif
 }
index 1a5e290..cc6201f 100644 (file)
@@ -134,6 +134,9 @@ idt_init(void)
        mask_lapic_lvt(LAPIC_LVT_LINT0);
        // and turn it on
        lapic_enable();
+       /* register the generic timer_interrupt() handler for the per-core timers */
+       register_interrupt_handler(interrupt_handlers, LAPIC_TIMER_DEFAULT_VECTOR,
+                                  timer_interrupt, NULL);
 }
 
 void
index 21c33e8..3f2f8ad 100644 (file)
@@ -157,4 +157,10 @@ void smp_percpu_init(void)
        STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
        spinlock_init(&per_cpu_info[coreid].routine_amsg_lock);
        STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
+#ifdef __CONFIG_EXPER_TRADPROC__
+       spinlock_init(&per_cpu_info[coreid].runqueue_lock);
+       TAILQ_INIT(&per_cpu_info[coreid].runqueue);
+       /* set a per-core periodic timer interrupt to go off every TIMER_uSEC usec*/
+       set_timer(TIMER_uSEC);
+#endif
 }
index 71cf85e..ba85b97 100644 (file)
 system_timing_t system_timing = {0};
 
 void
-timer_interrupt(void)
-{
-}
-
-void
 timer_init(void)
 {      
        system_timing.tsc_freq = TSC_HZ;
index 55ac719..4db89da 100644 (file)
@@ -14,5 +14,6 @@ typedef struct system_timing {
 extern system_timing_t system_timing;
 
 void timer_init(void);
+void set_timer(uint32_t usec);
 
 #endif /* !ROS_ARCH_TIMER_H */
index 63ebf1b..6d142f8 100644 (file)
@@ -39,6 +39,10 @@ struct per_cpu_info {
        struct kernel_msg_list NTPTV(a0t) NTPTV(a1t) NTPTV(a2t) immed_amsgs;
        spinlock_t routine_amsg_lock;
        struct kernel_msg_list NTPTV(a0t) NTPTV(a1t) NTPTV(a2t) routine_amsgs;
+#ifdef __CONFIG_EXPER_TRADPROC__
+       spinlock_t runqueue_lock;
+       struct proc_list runqueue;
+#endif
 }__attribute__((aligned(HW_CACHE_ALIGN)));
 
 typedef struct per_cpu_info NTPTV(t) NTPTV(a0t) NTPTV(a1t) NTPTV(a2t) per_cpu_info_t;
@@ -60,4 +64,11 @@ int smp_call_function_single(uint32_t dest, poly_isr_t handler, TV(t) data,
                              handler_wrapper_t** wait_wrapper);
 int smp_call_wait(handler_wrapper_t*SAFE wrapper);
 
+#ifdef __CONFIG_EXPER_TRADPROC__
+
+#define TIMER_uSEC 10000
+void local_schedule(void);
+
+#endif
+
 #endif /* !ROS_INC_SMP_H */
index 079cd2c..64a8df9 100644 (file)
@@ -30,8 +30,10 @@ void
 register_interrupt_handler(handler_t SSOMELOCK (CT(NUM_INTERRUPT_HANDLERS)table)[],
                            uint8_t int_num,
                            poly_isr_t handler, TV(t) data);
-void ( print_trapframe)(trapframe_t *tf);
-void ( page_fault_handler)(trapframe_t *tf);
+void print_trapframe(trapframe_t *tf);
+void page_fault_handler(trapframe_t *tf);
+/* Generic per-core timer interrupt handler */
+void timer_interrupt(struct trapframe *tf, void *data);
 
 void sysenter_init(void);
 extern void sysenter_handler();
index 8ccb931..b6f2887 100644 (file)
@@ -62,3 +62,24 @@ void smp_idle(void)
        }
        assert(0);
 }
+#ifdef __CONFIG_EXPER_TRADPROC__
+/* For experiments with per-core schedulers (traditional).  This checks the
+ * runqueue, and if there is something there, it runs in.  */
+void local_schedule(void)
+{
+       struct per_cpu_info *my_info = &per_cpu_info[core_id()];
+       struct proc *next_to_run;
+
+       printd("Core %d trying to schedule a _S process\n", core_id());
+       spin_lock_irqsave(&my_info->runqueue_lock);
+       next_to_run = TAILQ_FIRST(&my_info->runqueue);
+       if (next_to_run)
+               TAILQ_REMOVE(&my_info->runqueue, next_to_run, proc_link);
+       spin_unlock_irqsave(&my_info->runqueue_lock);
+       if (!next_to_run)
+               return;
+       assert(next_to_run->state = PROC_RUNNABLE_S);
+       proc_run(next_to_run);
+       assert(0); // don't reach this
+}
+#endif
index d708616..a87abda 100644 (file)
@@ -7,6 +7,8 @@
 
 #include <arch/arch.h>
 #include <ros/timer.h>
+#include <stdio.h>
+#include <schedule.h>
 
 /* timing_overhead
  * Any user space process that links to this file will get its own copy.  
@@ -74,3 +76,13 @@ void train_timing()
        }
        timing_overhead = training_overhead;
 }
+
+/* Typical per-core timer interrupt handler.  Note that sparc's timer is
+ * periodic by nature, so if you want it to not be periodic, turn off the alarm
+ * in here. */
+void timer_interrupt(struct trapframe *tf, void *data)
+{
+#ifdef __CONFIG_EXPER_TRADPROC__
+       local_schedule();
+#endif /* __CONFIG_EXPER_TRADPROC__ */
+}