more smp_call_function with checklists
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 21 Apr 2009 03:14:26 +0000 (20:14 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 22 Apr 2009 05:12:48 +0000 (22:12 -0700)
actual use of "wait" and initial testing.

kern/init.c
kern/smp.c
kern/smp.h
kern/testing.c
kern/testing.h

index 0e8ba20..2180dc7 100644 (file)
@@ -51,18 +51,19 @@ void kernel_init(multiboot_info_t *mboot_info)
        timer_init();
        // this returns when all other cores are done and ready to receive IPIs
        smp_boot();
-       
+
+       test_smp_call_functions();
        panic("Don't Panic");
+
        test_checklists();
        test_barrier();
-
        test_print_info();
        test_ipi_sending();
        test_pit();
        test_barrier();
        test_print_info();
        test_ipi_sending();
-       
+
        //ENV_CREATE(user_faultread);
        //ENV_CREATE(user_faultreadkernel);
        //ENV_CREATE(user_faultwrite);
index 5131f52..359505d 100644 (file)
@@ -218,7 +218,9 @@ static void smp_call_function(uint8_t type, uint8_t dest, isr_t handler, bool wa
        int8_t state = 0;
        uint8_t vector;
 
-wait = 1;
+// need a check to make sure the core we are trying to send to exists!  
+// if you call sending to something that never answers, we'll never be able to 
+// reuse our vector (which is a problem even if it exists....)
 
        // build the mask based on the type and destination
        INIT_CHECKLIST_MASK(handler_mask, MAX_NUM_CPUS);
@@ -299,20 +301,19 @@ wait = 1;
 
 // I'd rather have these functions take an arbitrary function and arguments...
 // Right now, I build a handler that just calls whatever I want, which is
-// another layer of indirection.  Might like some ability to specify if
-// we want to wait or not.
-void smp_call_function_self(isr_t handler, uint8_t vector)
+// another layer of indirection.
+void smp_call_function_self(isr_t handler, bool wait)
 {
-       smp_call_function(1, 0, handler, vector);
+       smp_call_function(1, 0, handler, wait);
 }
 
-void smp_call_function_all(isr_t handler, uint8_t vector)
+void smp_call_function_all(isr_t handler, bool wait)
 {
-       smp_call_function(2, 0, handler, vector);
+       smp_call_function(2, 0, handler, wait);
 }
 
-void smp_call_function_single(uint8_t dest, isr_t handler, uint8_t vector)
+void smp_call_function_single(uint8_t dest, isr_t handler, bool wait)
 {
-       smp_call_function(4, dest, handler, vector);
+       smp_call_function(4, dest, handler, wait);
 }
 
index 2090f7d..e3bc67c 100644 (file)
@@ -24,8 +24,8 @@ typedef struct handler_wrapper {
 
 void smp_boot(void);
 
-void smp_call_function_self(isr_t handler, uint8_t vector);
-void smp_call_function_all(isr_t handler, uint8_t vector);
-void smp_call_function_single(uint8_t dest, isr_t handler, uint8_t vector);
+void smp_call_function_self(isr_t handler, bool wait);
+void smp_call_function_all(isr_t handler, bool wait);
+void smp_call_function_single(uint8_t dest, isr_t handler, bool wait);
 
 #endif /* !ROS_INC_SMP_H */
index de87098..d44f83e 100644 (file)
@@ -274,6 +274,90 @@ void test_checklists(void)
 
 }
 
+volatile uint32_t a = 0, b = 0, c = 0;
+
+void test_A_incrementer_handler(struct Trapframe *tf)
+{
+       atomic_inc(&a);
+}
+
+void test_B_incrementer_handler(struct Trapframe *tf)
+{
+       atomic_inc(&b);
+}
+
+void test_C_incrementer_handler(struct Trapframe *tf)
+{
+       atomic_inc(&c);
+}
+
+void test_null_handler(struct Trapframe *tf)
+{
+       asm volatile("nop");
+}
+
+void test_smp_call_functions(void)
+{
+       uint8_t me = lapic_get_id();
+       printk("\nCore %d: SMP Call Self (nowait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_self(test_hello_world_handler, 0);
+       printk("\nCore %d: SMP Call Self (wait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_self(test_hello_world_handler, 1);
+       printk("\nCore %d: SMP Call All (nowait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_all(test_hello_world_handler, 0);
+       printk("\nCore %d: SMP Call All (wait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_all(test_hello_world_handler, 1);
+       printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_single(1, test_hello_world_handler, 0);
+       smp_call_function_single(2, test_hello_world_handler, 0);
+       smp_call_function_single(3, test_hello_world_handler, 0);
+       smp_call_function_single(4, test_hello_world_handler, 0);
+       smp_call_function_single(5, test_hello_world_handler, 0);
+       smp_call_function_single(6, test_hello_world_handler, 0);
+       smp_call_function_single(7, test_hello_world_handler, 0);
+       printk("\nCore %d: SMP Call Self (wait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_self(test_hello_world_handler, 1);
+       printk("\nCore %d: SMP Call All-Else Individually, in order (wait):\n", me);
+       printk("---------------------\n");
+       smp_call_function_single(1, test_hello_world_handler, 1);
+       smp_call_function_single(2, test_hello_world_handler, 1);
+       smp_call_function_single(3, test_hello_world_handler, 1);
+       smp_call_function_single(4, test_hello_world_handler, 1);
+       smp_call_function_single(5, test_hello_world_handler, 1);
+       smp_call_function_single(6, test_hello_world_handler, 1);
+       smp_call_function_single(7, test_hello_world_handler, 1);
+       printk("\nTesting to see if any IPI-functions are dropped when not waiting:\n");
+       printk("A: %d, B: %d, C: %d (should be 0,0,0)\n", a, b, c);
+       smp_call_function_all(test_A_incrementer_handler, 0);
+       smp_call_function_all(test_B_incrementer_handler, 0);
+       smp_call_function_all(test_C_incrementer_handler, 0);
+       // if i can clobber a previous IPI, the interleaving might do it
+       smp_call_function_single(1, test_A_incrementer_handler, 0);
+       smp_call_function_single(2, test_B_incrementer_handler, 0);
+       smp_call_function_single(3, test_C_incrementer_handler, 0);
+       smp_call_function_single(4, test_A_incrementer_handler, 0);
+       smp_call_function_single(5, test_B_incrementer_handler, 0);
+       smp_call_function_single(6, test_C_incrementer_handler, 0);
+       smp_call_function_all(test_A_incrementer_handler, 0);
+       smp_call_function_single(3, test_C_incrementer_handler, 0);
+       smp_call_function_all(test_B_incrementer_handler, 0);
+       smp_call_function_single(1, test_A_incrementer_handler, 0);
+       smp_call_function_all(test_C_incrementer_handler, 0);
+       smp_call_function_single(2, test_B_incrementer_handler, 0);
+       // wait, so we're sure the others finish before printing.
+       // without this, we could (and did) get 19,18,19, since the B_inc
+       // handler didn't finish yet
+       smp_call_function_self(test_null_handler, 1);
+       printk("A: %d, B: %d, C: %d (should be 19,19,19)\n", a, b, c);
+       printk("Done\n");
+}
+
 /* Helper Functions */
 
 void test_hello_world_handler(trapframe_t *tf)
index 73712cf..ab6e1e7 100644 (file)
@@ -18,6 +18,7 @@ void test_interrupts_irqsave(void);
 void test_bitmasks(void);
 void test_checklists(void);
 void test_pit(void);
+void test_smp_call_functions(void);
 
 void test_hello_world_handler(trapframe_t *tf);
 void test_print_info_handler(trapframe_t *tf);