sys_halt_core() and an idle process
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 22 Apr 2010 00:16:46 +0000 (17:16 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:43 +0000 (17:35 -0700)
Schedule the idle process after busybox or whatever, and it will halt
the core for 5 sec and yield.

Note the timer_interrupt() will fire too, and that the syscall takes no
precautions about any outstanding per-core timers.

You need to reinstall your kernel headers.

13 files changed:
kern/arch/i686/apic.c
kern/arch/i686/smp_boot.c
kern/arch/sparc/smp.c
kern/arch/sparc/timer.c
kern/include/ros/bits/syscall.h
kern/include/timing.h
kern/include/trap.h
kern/src/Makefrag
kern/src/kfs.c
kern/src/syscall.c
tests/idle.c [new file with mode: 0644]
user/include/parlib.h
user/parlib/syscall.c

index 57bbee8..8f3b4e9 100644 (file)
@@ -90,7 +90,7 @@ void lapic_set_timer(uint32_t usec, bool periodic)
                          LAPIC_TIMER_DEFAULT_DIVISOR);
 }
 
-void set_timer(uint32_t usec)
+void set_core_timer(uint32_t usec)
 {
        if (usec)
                lapic_set_timer(usec, TRUE);
index 7a290ca..81fe732 100644 (file)
@@ -317,6 +317,6 @@ void smp_percpu_init(void)
        /* 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);
+       set_core_timer(TIMER_uSEC);
 #endif
 }
index 3f2f8ad..8e95f9b 100644 (file)
@@ -160,7 +160,6 @@ void smp_percpu_init(void)
 #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);
+       set_core_timer(TIMER_uSEC);
 #endif
 }
index ba85b97..4bee962 100644 (file)
@@ -19,6 +19,12 @@ timer_init(void)
 }
 
 void
+set_core_timer(uint32_t usec)
+{
+       set_timer(usec);
+}
+
+void
 set_timer(uint32_t usec)
 {
        uint32_t clocks =  (uint64_t)usec*TSC_HZ/1000000;
index 67d78f1..a2a155c 100644 (file)
@@ -34,6 +34,7 @@
 #define SYS_resource_req                       24
 #define SYS_notify                                     25
 #define SYS_self_notify                                26
+#define SYS_halt_core                          27
 
 /* Platform specific syscalls */
 #define SYS_serial_read                                75
index 5ee9f08..0edd068 100644 (file)
@@ -5,8 +5,4 @@
 
 void udelay(uint64_t usec);
 
-// arm the programmable interrupt timer.
-// usec=0 disables it.
-void set_timer(uint32_t usec);
-
 #endif
index 64a8df9..041a0c6 100644 (file)
@@ -32,7 +32,9 @@ register_interrupt_handler(handler_t SSOMELOCK (CT(NUM_INTERRUPT_HANDLERS)table)
                            poly_isr_t handler, TV(t) data);
 void print_trapframe(trapframe_t *tf);
 void page_fault_handler(trapframe_t *tf);
-/* Generic per-core timer interrupt handler */
+/* Generic per-core timer interrupt handler.  set_percore_timer() will fire the
+ * timer_interrupt(). */
+void set_core_timer(uint32_t usec);
 void timer_interrupt(struct trapframe *tf, void *data);
 
 void sysenter_init(void);
index 5ff229c..9dd077d 100644 (file)
@@ -62,7 +62,8 @@ KERN_APPFILES += \
                  $(TESTS_DIR)/hello \
                  $(TESTS_DIR)/mhello \
                  $(TESTS_DIR)/manycore_test \
-                 $(TESTS_DIR)/pthread_test
+                 $(TESTS_DIR)/pthread_test \
+                 $(TESTS_DIR)/idle
 endif
 
 KERN_LDFLAGS   := $(KERN_LDFLAGS) -L$(OBJDIR)/$(KERN_DIR) \
index dbd79b0..9d56593 100644 (file)
@@ -50,6 +50,7 @@ DECL_PROG(hello);
 DECL_PROG(mhello);
 DECL_PROG(manycore_test);
 DECL_PROG(pthread_test);
+DECL_PROG(idle);
 DECL_FILE(kfs_test_txt);
 DECL_FILE(hello_txt);
 #endif
@@ -67,6 +68,7 @@ struct kfs_entry kfs[MAX_KFS_FILES] = {
        KFS_PENTRY(mhello)
        KFS_PENTRY(manycore_test)
        KFS_PENTRY(pthread_test)
+       KFS_PENTRY(idle)
        KFS_FENTRY(kfs_test_txt)
        KFS_FENTRY(hello_txt)
 #endif
index c0964f7..15e35a0 100644 (file)
@@ -619,6 +619,19 @@ static int sys_self_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
        return 0;
 }
 
+/* This will set a local timer for usec, then shut down the core */
+static int sys_halt_core(struct proc *p, unsigned int usec)
+{
+       /* TODO: ought to check and see if a timer was already active, etc, esp so
+        * userspace can't turn off timers.  also note we will also call whatever
+        * timer_interrupt() will do, though all we care about is just
+        * self_ipi/interrupting. */
+       set_core_timer(usec);
+       cpu_halt();
+
+       return 0;
+}
+
 /************** Platform Specific Syscalls **************/
 
 //Read a buffer over the serial port
@@ -1058,6 +1071,7 @@ intreg_t syscall(struct proc *p, uintreg_t syscallno, uintreg_t a1,
                [SYS_resource_req] = (syscall_t)resource_req,
                [SYS_notify] = (syscall_t)sys_notify,
                [SYS_self_notify] = (syscall_t)sys_self_notify,
+               [SYS_halt_core] = (syscall_t)sys_halt_core,
        #ifdef __CONFIG_SERIAL_IO__
                [SYS_serial_read] = (syscall_t)sys_serial_read,
                [SYS_serial_write] = (syscall_t)sys_serial_write,
diff --git a/tests/idle.c b/tests/idle.c
new file mode 100644 (file)
index 0000000..bb370e7
--- /dev/null
@@ -0,0 +1,13 @@
+#include <parlib.h>
+#include <rstdio.h>
+
+/* This will keep a core from spinning forever, but will also allow it to still
+ * schedule() and run _S processes. */
+int main(int argc, char** argv)
+{
+       while (1) {
+               sys_halt_core(5000000); // 5 sec, adjust accordingly
+               sys_yield(0);
+       }
+       return 0;
+}
index 00b45cb..3d3bb16 100644 (file)
@@ -50,6 +50,7 @@ void *COUNT(length) sys_mmap(void *SNT addr, size_t length, int prot, int flags,
 int         sys_notify(int pid, unsigned int notif, struct notif_event *ne);
 int         sys_self_notify(uint32_t vcoreid, unsigned int notif,
                             struct notif_event *ne);
+int         sys_halt_core(unsigned int usec);
 
 #endif // !ASSEMBLER
 
index 8a23d11..1a4fb2c 100644 (file)
@@ -144,3 +144,8 @@ int sys_self_notify(uint32_t vcoreid, unsigned int notif,
 {
        return ros_syscall(SYS_self_notify, vcoreid, notif, ne, 0, 0);
 }
+
+int sys_halt_core(unsigned int usec)
+{
+       return ros_syscall(SYS_halt_core, usec, 0, 0, 0, 0);
+}