Replaces BCQs with UCQs (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 28 Jul 2011 22:28:19 +0000 (15:28 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:05 +0000 (17:36 -0700)
This doesn't change anything extra.  For instance, the overflow
detection and handling code is still in place.

Reinstall your kernel headers, etc, though you shouldn't need a full
cross compiler rebuild.

kern/include/ros/event.h
kern/include/ros/ucq.h
kern/src/event.c
user/parlib/event.c
user/parlib/vcore.c

index c1cad8e..c708c5b 100644 (file)
@@ -9,8 +9,8 @@
 
 #include <ros/common.h>
 #include <ros/atomic.h>
-#include <ros/bcq_struct.h>
 #include <ros/arch/trapframe.h>
+/* #include <ros/ucq.h> included below */
 
 /* Event Delivery Flags from the process to the kernel */
 #define EVENT_IPI                              0x001   /* IPI the core */
@@ -51,18 +51,16 @@ struct event_msg {
        uint64_t                                        ev_arg4;
 };
 
-/* Random numbers */
-#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);
+/* Including here since ucq.h needs to know about struct event_msg */
+#include <ros/ucq.h>
 
 /* Structure for storing / receiving event messages.  An overflow causes the
  * bit of the event to get set in the bitmap.  You can also have just the bit
  * sent (and no message). */
 struct event_mbox {
-       struct event_msg_bcq            ev_msgs;
+       struct ucq                                      ev_msgs;
        uint8_t                                         ev_bitmap[(MAX_NR_EVENT - 1) / 8 + 1];
+       /* this will go away in a commit or two: TODO */
        unsigned int                            ev_overflows;
 };
 
@@ -97,16 +95,4 @@ struct preempt_data {
        struct event_mbox                       ev_mbox;
 };
 
-/* Structs for different types of events that need parameters. */
-// TODO: think about this a bit.  And don't want to make them til we need them.
-
-/* Example: want the vcoreid of what was lost. */
-struct ev_vcore_revoke {
-       uint16_t                                        type;
-       uint16_t                                        pad1;
-       uint32_t                                        vcoreid;
-       void                                            *pad3;
-       uint64_t                                        pad4;
-};
-
 #endif /* ROS_INC_EVENT_H */
index 11e9fd5..d855e8a 100644 (file)
@@ -19,9 +19,9 @@
 #define ROS_INC_UCQ_H
 
 #include <ros/common.h>
-#include <ros/event.h>
 #include <ros/atomic.h>
 #include <ros/arch/mmu.h>
+/* #include <ros/event.h> included below */
 
 /* The main UCQ structure, contains indexes and start points (for the indexes),
  * etc. */
@@ -43,6 +43,9 @@ struct ucq_page_header {
        atomic_t                                        nr_cons;                /* like an inverted refcnt */
 };
 
+/* Including here since event.h needs to know about struct ucq */
+#include <ros/event.h>
+
 struct msg_container {
        struct event_msg                        ev_msg;
        bool                                            ready;                  /* kernel has written */
index 6a7632a..7b5065b 100644 (file)
@@ -5,7 +5,7 @@
  * Kernel utility functions for sending events and notifications (IPIs) to
  * processes. */
 
-#include <ros/bcq.h>
+#include <ucq.h>
 #include <bitmask.h>
 #include <event.h>
 #include <atomic.h>
@@ -32,21 +32,15 @@ static struct event_mbox *get_proc_ev_mbox(uint32_t vcoreid)
 static void post_ev_msg(struct event_mbox *mbox, struct event_msg *msg,
                         int ev_flags)
 {
+       struct proc *p = current;
        printd("Sending event type %d\n", msg->ev_type);
        /* Sanity check */
-       assert(current);
+       assert(p);
        /* If they just want a bit (NOMSG), just set the bit */
        if (ev_flags & EVENT_NOMSG) {
                SET_BITMASK_BIT_ATOMIC(mbox->ev_bitmap, msg->ev_type);
        } else {
-               /* Enqueue returns 0 on success.  On failure, set a bit. */
-               if (bcq_enqueue(&mbox->ev_msgs, msg, NR_BCQ_EVENTS, NR_BCQ_EV_LOOPS)) {
-                       atomic_inc((atomic_t)&mbox->ev_overflows); // careful here
-                       SET_BITMASK_BIT_ATOMIC(mbox->ev_bitmap, msg->ev_type);
-                       /* Catch "lots" of overflows that aren't acknowledged */
-                       if (mbox->ev_overflows > 10000)
-                               warn("proc %d has way too many overflows", current->pid);
-               }
+               send_ucq_msg(&mbox->ev_msgs, p, msg);
        }
 }
 
index 8f7de31..477811a 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <ros/event.h>
 #include <ros/procdata.h>
-#include <ros/bcq.h>
+#include <ucq.h>
 #include <bitmask.h>
 #include <vcore.h>
 #include <stdlib.h>
@@ -120,8 +120,8 @@ unsigned int event_clear_overflows(struct event_queue *ev_q)
 unsigned int get_event_type(struct event_mbox *ev_mbox)
 {
        struct event_msg local_msg = {0};
-       /* BCQ returns 0 on success, so this will dequeue and return the type. */
-       if (!bcq_dequeue(&ev_mbox->ev_msgs, &local_msg, NR_BCQ_EVENTS)) {
+       /* UCQ returns 0 on success, so this will dequeue and return the type. */
+       if (!get_ucq_msg(&ev_mbox->ev_msgs, &local_msg)) {
                return local_msg.ev_type;
        }
        if (BITMASK_IS_CLEAR(&ev_mbox->ev_bitmap, MAX_NR_EVENT))
@@ -152,9 +152,9 @@ int handle_mbox_msgs(struct event_mbox *ev_mbox)
        unsigned int ev_type;
        uint32_t vcoreid = vcore_id();
        /* Try to dequeue, dispatch whatever you get. */
-       while (!bcq_dequeue(&ev_mbox->ev_msgs, &local_msg, NR_BCQ_EVENTS)) {
+       while (!get_ucq_msg(&ev_mbox->ev_msgs, &local_msg)) {
                ev_type = local_msg.ev_type;
-               printd("BCQ: ev_type: %d\n", ev_type);
+               printd("UCQ: ev_type: %d\n", ev_type);
                if (ev_handlers[ev_type])
                        ev_handlers[ev_type](&local_msg, ev_type, FALSE);       /* no overflow*/
                check_preempt_pending(vcoreid);
index 8f4bb30..e51abd8 100644 (file)
@@ -12,6 +12,7 @@
 #include <glibc-tls.h>
 #include <event.h>
 #include <uthread.h>
+#include <ucq.h>
 #include <ros/arch/membar.h>
 
 /* starting with 1 since we alloc vcore0's stacks and TLS in vcore_init(). */
@@ -100,6 +101,7 @@ static int allocate_transition_stack(int id)
 int vcore_init()
 {
        static int initialized = 0;
+       uintptr_t mmap_block;
        if(initialized)
                return 0;
 
@@ -114,6 +116,22 @@ int vcore_init()
        if(allocate_transition_stack(0) || allocate_transition_tls(0))
                goto vcore_init_tls_fail;
 
+       /* Initialize our VCPD event queues' ucqs, two pages per vcore */
+       mmap_block = (uintptr_t)mmap(0, PGSIZE * 2 * max_vcores(),
+                                    PROT_WRITE | PROT_READ,
+                                    MAP_POPULATE, -1, 0);
+       /* Yeah, this doesn't fit in the error-handling scheme, but this whole
+        * system doesn't really handle failure, and needs a rewrite involving less
+        * mmaps/munmaps. */
+       assert(mmap_block);
+       /* Note we may end up doing vcore 0's elsewhere, for _Ss, or else have a
+        * separate ev_q for that. */
+       for (int i = 0; i < max_vcores(); i++) {
+               /* two pages each from the big block */
+               ucq_init(&__procdata.vcore_preempt_data[i].ev_mbox.ev_msgs,
+                        mmap_block + (2 * i    ) * PGSIZE, 
+                        mmap_block + (2 * i + 1) * PGSIZE); 
+       }
        assert(!in_vcore_context());
        initialized = 1;
        return 0;