Fixes up syscall_blockon functions (XCC)
[akaros.git] / user / parlib / event.c
index 52e3ad0..bb21a65 100644 (file)
@@ -7,16 +7,17 @@
 
 #include <ros/event.h>
 #include <ros/procdata.h>
-#include <ucq.h>
-#include <bitmask.h>
-#include <vcore.h>
+#include <parlib/ucq.h>
+#include <parlib/bitmask.h>
+#include <parlib/vcore.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <errno.h>
-#include <parlib.h>
+#include <parlib/parlib.h>
 #include <event.h>
-#include <uthread.h>
+#include <parlib/uthread.h>
+#include <parlib/spinlock.h>
 
 /* For remote VCPD mbox event handling */
 __thread bool __vc_handle_an_mbox = FALSE;
@@ -164,9 +165,44 @@ unsigned int get_event_type(struct event_mbox *ev_mbox)
 
 /* Actual Event Handling */
 
-/* List of handlers, process-wide, that the 2LS should fill in.  They all must
- * return (don't context switch to a u_thread) */
-handle_event_t ev_handlers[MAX_NR_EVENT];
+/* List of handler lists, process-wide.  They all must return (don't context
+ * switch to a u_thread) */
+struct ev_handler *ev_handlers[MAX_NR_EVENT] = {0};
+spinpdrlock_t ev_h_wlock = SPINPDR_INITIALIZER;
+
+int register_ev_handler(unsigned int ev_type, handle_event_t handler,
+                        void *data)
+{
+       struct ev_handler *new_h = malloc(sizeof(struct ev_handler));
+       if (!new_h)
+               return -1;
+       new_h->func = handler;
+       new_h->data = data;
+       spin_pdr_lock(&ev_h_wlock);
+       new_h->next = ev_handlers[ev_type];
+       wmb();  /* make sure new_h is done before publishing to readers */
+       ev_handlers[ev_type] = new_h;
+       spin_pdr_unlock(&ev_h_wlock);
+       return 0;
+}
+
+int deregister_ev_handler(unsigned int ev_type, handle_event_t handler,
+                          void *data)
+{
+       /* TODO: User-level RCU */
+       printf("Failed to dereg handler, not supported yet!\n");
+}
+
+static void run_ev_handlers(unsigned int ev_type, struct event_msg *ev_msg)
+{
+       struct ev_handler *handler;
+       /* TODO: RCU read lock */
+       handler = ev_handlers[ev_type];
+       while (handler) {
+               handler->func(ev_msg, ev_type, handler->data);
+               handler = handler->next;
+       }
+}
 
 /* Attempts to handle a message.  Returns 1 if we dequeued a msg, 0 o/w. */
 int handle_one_mbox_msg(struct event_mbox *ev_mbox)
@@ -179,8 +215,7 @@ int handle_one_mbox_msg(struct event_mbox *ev_mbox)
        ev_type = local_msg.ev_type;
        assert(ev_type < MAX_NR_EVENT);
        printd("[event] UCQ (mbox %08p), ev_type: %d\n", ev_mbox, ev_type);
-       if (ev_handlers[ev_type])
-               ev_handlers[ev_type](&local_msg, ev_type, 0);
+       run_ev_handlers(ev_type, &local_msg);
        return 1;
 }
 
@@ -193,8 +228,7 @@ int handle_mbox(struct event_mbox *ev_mbox)
        uint32_t vcoreid = vcore_id();
        void bit_handler(unsigned int bit) {
                printd("[event] Bit: ev_type: %d\n", bit);
-               if (ev_handlers[bit])
-                       ev_handlers[bit](0, bit, 0);
+               run_ev_handlers(bit, 0);
                retval = 1;
                /* Consider checking the queue for incoming messages while we're here */
        }
@@ -247,7 +281,7 @@ void handle_ev_ev(struct event_msg *ev_msg, unsigned int ev_type, void *data)
        handle_event_q(ev_q);
 }
 
-/* Attempts to handle events, if notif_pending.  The kernel always sets
+/* Handles VCPD events (public and private).  The kernel always sets
  * notif_pending after posting a message to either public or private mailbox.
  * When this returns, as far as we are concerned, notif_pending is FALSE.
  * However, a concurrent kernel writer could have reset it to true.  This is
@@ -259,12 +293,10 @@ int handle_events(uint32_t vcoreid)
 {
        struct preempt_data *vcpd = vcpd_of(vcoreid);
        int retval = 0;
-       if (vcpd->notif_pending) {
-               vcpd->notif_pending = FALSE;
-               wrmb(); /* prevent future reads from happening before notif_p write */
-               retval += handle_mbox(&vcpd->ev_mbox_private);
-               retval += handle_mbox(&vcpd->ev_mbox_public);
-       }
+       vcpd->notif_pending = FALSE;
+       wrmb(); /* prevent future reads from happening before notif_p write */
+       retval += handle_mbox(&vcpd->ev_mbox_private);
+       retval += handle_mbox(&vcpd->ev_mbox_public);
        return retval;
 }