Rip out the old network stack. It's in the way.
[akaros.git] / kern / src / testing.c
index 7c7a072..73c3e2c 100644 (file)
@@ -40,6 +40,7 @@
 #include <setjmp.h>
 #include <apipe.h>
 #include <rwlock.h>
+#include <rendez.h>
 
 #define l1 (available_caches.l1)
 #define l2 (available_caches.l2)
 
 void test_ipi_sending(void)
 {
-       extern handler_t (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
        int8_t state = 0;
 
-       register_interrupt_handler(interrupt_handlers, I_TESTING,
-                                  test_hello_world_handler, NULL);
+       register_raw_irq(I_TESTING, test_hello_world_handler, NULL);
        enable_irqsave(&state);
        cprintf("\nCORE 0 sending broadcast\n");
        send_broadcast_ipi(I_TESTING);
@@ -89,7 +88,7 @@ void test_ipi_sending(void)
 // Note this never returns and will muck with any other timer work
 void test_pic_reception(void)
 {
-       register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
+       register_raw_irq(0x20, test_hello_world_handler, NULL);
        pit_set_timer(100,TIMER_RATEGEN); // totally arbitrary time
        pic_unmask_irq(0);
        cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
@@ -102,7 +101,7 @@ void test_pic_reception(void)
 
 void test_ioapic_pit_reroute(void) 
 {
-       register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
+       register_raw_irq(0x20, test_hello_world_handler, NULL);
        ioapic_route_irq(0, 3); 
 
        cprintf("Starting pit on core 3....\n");
@@ -551,8 +550,7 @@ void test_smp_call_functions(void)
 #ifdef CONFIG_X86
 void test_lapic_status_bit(void)
 {
-       register_interrupt_handler(interrupt_handlers, I_TESTING,
-                                  test_incrementer_handler, &a);
+       register_raw_irq(I_TESTING, test_incrementer_handler, &a);
        #define NUM_IPI 100000
        atomic_set(&a,0);
        printk("IPIs received (should be 0): %d\n", a);
@@ -654,8 +652,7 @@ void test_pit(void)
 
        atomic_t waiting;
        atomic_init(&waiting, 1);
-       register_interrupt_handler(interrupt_handlers, I_TESTING,
-                                  test_waiting_handler, &waiting);
+       register_raw_irq(I_TESTING, test_waiting_handler, &waiting);
        while(atomic_read(&waiting))
                cpu_relax();
        cprintf("End now\n");
@@ -755,7 +752,7 @@ void test_kmalloc(void)
        void *bufs[NUM_KMALLOC_CACHES + 1];     
        size_t size;
        for (int i = 0; i < NUM_KMALLOC_CACHES + 1; i++){
-               size = (KMALLOC_SMALLEST << i) - KMALLOC_OFFSET;
+               size = (KMALLOC_SMALLEST << i) - sizeof(struct kmalloc_tag);
                bufs[i] = kmalloc(size, 0);
                printk("Size %d, Addr = %p\n", size, bufs[i]);
        }
@@ -1045,7 +1042,7 @@ void test_ucq(void)
        /* Should never return from schedule (env_pop in there) also note you may
         * not get the process you created, in the event there are others floating
         * around that are runnable */
-       schedule();
+       run_scheduler();
        smp_idle();
        assert(0);
 }
@@ -1430,9 +1427,9 @@ static void __test_try_halt(uint32_t srcid, long a0, long a1, long a2)
        printk("Returned from halting on core 1\n");
 }
 
-/* x86 test, making sure our cpu_halt() and irq_handler() work.  If you want to
+/* x86 test, making sure our cpu_halt() and handle_irq() work.  If you want to
  * see it fail, you'll probably need to put a nop in the asm for cpu_halt(), and
- * comment out abort_halt() in irq_handler(). */
+ * comment out abort_halt() in handle_irq(). */
 void test_abort_halt(void)
 {
 #ifdef CONFIG_X86
@@ -1605,7 +1602,7 @@ void __attribute__((noinline)) __longjmp_wrapper(struct jmpbuf* jb)
 {
        asm ("");
        printk("Starting: %s\n", __FUNCTION__);
-       longjmp(jb, 1);
+       longjmp(jb, (void *)1);
        // Should never get here
        printk("Exiting: %s\n", __FUNCTION__); 
 }
@@ -1768,3 +1765,121 @@ void test_rwlock(void)
                cpu_relax();
        printk("rwlock test complete\n");
 }
+
+/* Funcs and global vars for test_rv() */
+static struct rendez local_rv;
+static struct rendez *rv = &local_rv;
+/* reusing state and counter from test_cv... */
+
+static int __rendez_cond(void *arg)
+{
+       return *(bool*)arg;
+}
+
+void __test_rv_wakeup(uint32_t srcid, long a0, long a1, long a2)
+{
+       if (atomic_read(&counter) % 4)
+               cv_signal(cv);
+       else
+               cv_broadcast(cv);
+       atomic_dec(&counter);
+}
+
+void __test_rv_sleeper(uint32_t srcid, long a0, long a1, long a2)
+{
+       rendez_sleep(rv, __rendez_cond, (void*)&state);
+       atomic_dec(&counter);
+}
+
+void __test_rv_sleeper_timeout(uint32_t srcid, long a0, long a1, long a2)
+{
+       /* half-assed amount of time. */
+       rendez_sleep_timeout(rv, __rendez_cond, (void*)&state, a0);
+       atomic_dec(&counter);
+}
+
+void test_rv(void)
+{
+       int nr_msgs;
+
+       rendez_init(rv);
+       /* Test 0: signal without waiting */
+       rendez_wakeup(rv);
+       kthread_yield();
+       printk("test_rv: wakeup without sleeping complete\n");
+
+       /* Test 1: a few sleepers */
+       nr_msgs = num_cpus - 1; /* not using cpu 0 */
+       atomic_init(&counter, nr_msgs);
+       state = FALSE;
+       for (int i = 1; i < num_cpus; i++)
+               send_kernel_message(i, __test_rv_sleeper, 0, 0, 0, KMSG_ROUTINE);
+       udelay(1000000);
+       cmb();
+       state = TRUE;
+       rendez_wakeup(rv);
+       /* broadcast probably woke up the waiters on our core.  since we want to
+        * spin on their completion, we need to yield for a bit. */
+       kthread_yield();
+       while (atomic_read(&counter))
+               cpu_relax();
+       printk("test_rv: bulk wakeup complete\n");
+
+       /* Test 2: different types of sleepers / timeouts */
+       state = FALSE;
+       nr_msgs = 0x500;        /* any more than 0x20000 could go OOM */
+       atomic_init(&counter, nr_msgs);
+       for (int i = 0; i < nr_msgs; i++) {
+               int cpu = (i % (num_cpus - 1)) + 1;
+               /* timeouts from 0ms ..5000ms (enough that they should wake via cond */
+               if (atomic_read(&counter) % 5)
+                       send_kernel_message(cpu, __test_rv_sleeper_timeout, i * 4, 0, 0,
+                                           KMSG_ROUTINE);
+               else
+                       send_kernel_message(cpu, __test_rv_sleeper, 0, 0, 0, KMSG_ROUTINE);
+       }
+       kthread_yield();        /* run whatever messages we sent to ourselves */
+       state = TRUE;
+       while (atomic_read(&counter)) {
+               cpu_relax();
+               rendez_wakeup(rv);
+               udelay(1000000);
+               kthread_yield();        /* run whatever messages we sent to ourselves */
+       }
+       assert(!rv->cv.nr_waiters);
+       printk("test_rv: lots of sleepers/timeouts complete\n");
+}
+
+/* Cheap test for the alarm internal management */
+void test_alarm(void)
+{
+       uint64_t now = tsc2usec(read_tsc());
+       struct alarm_waiter await1, await2;
+       struct timer_chain *tchain = &per_cpu_info[0].tchain;
+       void shouldnt_run(struct alarm_waiter *awaiter)
+       {
+               printk("Crap, %p ran!\n", awaiter);
+       }
+       void empty_run(struct alarm_waiter *awaiter)
+       {
+               printk("Yay, %p ran (hopefully twice)!\n", awaiter);
+       }
+       /* Test basic insert, move, remove */
+       init_awaiter(&await1, shouldnt_run);
+       set_awaiter_abs(&await1, now + 1000000000);
+       set_alarm(tchain, &await1);
+       reset_alarm_abs(tchain, &await1, now + 1000000000 - 50);
+       reset_alarm_abs(tchain, &await1, now + 1000000000 + 50);
+       unset_alarm(tchain, &await1);
+       /* Test insert of one that fired already */
+       init_awaiter(&await2, empty_run);
+       set_awaiter_rel(&await2, 1);
+       set_alarm(tchain, &await2);
+       enable_irq();
+       udelay(1000);
+       reset_alarm_abs(tchain, &await2, now + 10);
+       udelay(1000);
+       unset_alarm(tchain, &await2);
+
+       printk("%s complete\n", __FUNCTION__);
+}