Fixes event BCQ bug
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 9 May 2011 20:10:18 +0000 (13:10 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:02 +0000 (17:36 -0700)
BCQs must have a power-of-two number of elements.  Humorously enough,
this has been fucked up for a long time.  The critical fix is in
k/i/r/event.h.  Everything else is some extra debugging / testing code.

kern/include/monitor.h
kern/include/ros/bcq.h
kern/include/ros/event.h
kern/src/monitor.c
kern/src/testing.c

index 6f285b1..8f277df 100644 (file)
@@ -32,5 +32,6 @@ int mon_monitor(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_fs(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_bb(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_alarm(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_bcq(int argc, char **argv, struct trapframe *tf);
 
 #endif // !ROS_KERN_MONITOR_H
index d2684d3..b8a7f76 100644 (file)
@@ -21,7 +21,7 @@
  * blocks and does not need to trust the data structure (which is writable by
  * the consumer).
  *
- * A producer enqueues and item, based on the indexes of the producer and
+ * A producer enqueues an item, based on the indexes of the producer and
  * consumer.  Enqueue cannot block, but can fail if the queue is full or if it
  * fails to enqueue after a certain amount of tries.
  *
@@ -73,6 +73,7 @@
  * bcq_enqueue(&some_bcq, &some_my_type, my_size, num_fails_okay);
  * bcq_dequeue(&some_bcq, &some_my_type, my_size);
  *
+ * They both return 0 on success, or some error code on failure.
  *
  * TODO later:
  * How about an atomic_add_return for the prod?  Now that we use powers of two,
index 7cabd9d..c1cad8e 100644 (file)
@@ -52,7 +52,7 @@ struct event_msg {
 };
 
 /* Random numbers */
-#define NR_BCQ_EVENTS 10               /* nr events in a bcq */
+#define NR_BCQ_EVENTS 16               /* nr events in a bcq (power of 2!) */
 #define NR_BCQ_EV_LOOPS 4              /* how many loops to try to enqueue */
 
 DEFINE_BCQ_TYPES(event_msg, struct event_msg, NR_BCQ_EVENTS);
index 7e985b7..cd4a1fb 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <ros/timer.h>
 #include <ros/memlayout.h>
+#include <ros/event.h>
 
 #define CMDBUF_SIZE    80      // enough for one VGA text line
 
@@ -62,6 +63,7 @@ static command_t (RO commands)[] = {
        { "fs", "Filesystem Diagnostics", mon_fs},
        { "bb", "Try to run busybox (ash)", mon_bb},
        { "alarm", "Alarm Diagnostics", mon_alarm},
+       { "bcq", "BCQ Diagnostics", mon_bcq},
 };
 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
 
@@ -882,3 +884,36 @@ int mon_alarm(int argc, char **argv, struct trapframe *tf)
        }
        return 0;
 }
+
+/* This is ghetto: assumes a VCPD 10 element BCQ.  This is a pain in the ass to
+ * do generically, since size of a struct doesn't tell you its alignment.
+ * (picture a struct with just chars vs one that requires padding due to longer
+ * members).  This just works for event BCQs. */
+int mon_bcq(int argc, char **argv, struct trapframe *tf)
+{
+       if (argc < 2) {
+               printk("Usage: bcq OPTION [KVA_OF_BCQ] \n");
+               printk("\tstatus KVA_OF_BCQ: prints the status of the bcq\n");
+               return 1;
+       }
+       if (!strcmp(argv[1], "status")) {
+               if (argc != 3) {
+                       printk("Give me a bcq.\n");
+                       return 1;
+               }
+               struct event_msg_bcq *bcq =
+                                    (struct event_msg_bcq*)strtol(argv[2], 0, 16);
+               printk("Event BCQ: %08p\n", bcq);
+               printk("\tprod_idx: %08p\n", bcq->hdr.prod_idx);
+               printk("\tcons_pub_idx: %08p\n", bcq->hdr.cons_pub_idx);
+               printk("\tcons_pvt_idx: %08p\n", bcq->hdr.cons_pvt_idx);
+               for (int i = 0; i < NR_BCQ_EVENTS; i++) {
+                       printk("Element %d, rdy_for_cons: %02p\n", i,
+                              bcq->wraps[i].rdy_for_cons);
+               }
+       } else {
+               printk("Bad option\n");
+               return 1;
+       }
+       return 0;
+}
index fac0709..9d01a5e 100644 (file)
@@ -878,6 +878,7 @@ void test_hashtable(void)
 /* Ghetto test, only tests one prod or consumer at a time */
 void test_bcq(void)
 {
+       /* Tests a basic struct */
        struct my_struct {
                int x;
                int y;
@@ -897,44 +898,65 @@ void test_bcq(void)
        bcq_dequeue(&t_bcq, &out_struct, 16);
        printk("out x %d. out y %d\n", out_struct.x, out_struct.y);
        
-       DEFINE_BCQ_TYPES(my, int, 8);
+       /* Tests the BCQ a bit more, esp with overflow */
+       #define NR_ELEM_A_BCQ 8 /* NOTE: this must be a power of 2! */
+       DEFINE_BCQ_TYPES(my, int, NR_ELEM_A_BCQ);
        struct my_bcq a_bcq;
-       bcq_init(&a_bcq, int, 8);
+       bcq_init(&a_bcq, int, NR_ELEM_A_BCQ);
        
        int y = 2;
        int output[100];
        int retval[100];
-       
+
+       /* Helpful debugger */
+       void print_a_bcq(struct my_bcq *bcq)
+       {
+               printk("A BCQ (made of ints): %08p\n", bcq);
+               printk("\tprod_idx: %08p\n", bcq->hdr.prod_idx);
+               printk("\tcons_pub_idx: %08p\n", bcq->hdr.cons_pub_idx);
+               printk("\tcons_pvt_idx: %08p\n", bcq->hdr.cons_pvt_idx);
+               for (int i = 0; i < NR_ELEM_A_BCQ; i++) {
+                       printk("Element %d, rdy_for_cons: %02p\n", i,
+                              bcq->wraps[i].rdy_for_cons);
+               }
+       }
+
+       /* Put in more than it can take */
        for (int i = 0; i < 15; i++) {
                y = i;
-               retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
+               retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
                printk("enqueued: %d, had retval %d \n", y, retval[i]);
        }
+       //print_a_bcq(&a_bcq);
        
+       /* Try to dequeue more than we put in */
        for (int i = 0; i < 15; i++) {
-               retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
+               retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
                printk("dequeued: %d with retval %d\n", output[i], retval[i]);
        }
+       //print_a_bcq(&a_bcq);
        
+       /* Put in some it should be able to take */
        for (int i = 0; i < 3; i++) {
                y = i;
-               retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
+               retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
                printk("enqueued: %d, had retval %d \n", y, retval[i]);
        }
        
+       /* Take those, and then a couple extra */
        for (int i = 0; i < 5; i++) {
-               retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
+               retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
                printk("dequeued: %d with retval %d\n", output[i], retval[i]);
        }
        
+       /* Try some one-for-one */
        for (int i = 0; i < 5; i++) {
                y = i;
-               retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
+               retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
                printk("enqueued: %d, had retval %d \n", y, retval[i]);
-               retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
+               retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
                printk("dequeued: %d with retval %d\n", output[i], retval[i]);
        }
-       
 }
 
 /* rudimentary tests.  does the basics, create, merge, split, etc.  Feel free to