Move register_evq to event.c
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 31 Aug 2015 03:08:23 +0000 (23:08 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 28 Sep 2015 19:14:00 +0000 (15:14 -0400)
Although it was originally used for uthread libraries when blocking
threads on syscalls, it's not particular to uthreads.

tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/syscall.c
user/parlib/event.c
user/parlib/include/event.h
user/parlib/include/uthread.h
user/parlib/uthread.c

index 2f61fc5..9153142 100644 (file)
@@ -36,7 +36,7 @@ struct event_queue __ros_scp_simple_evq =
                     .ev_vcore = 0,
                     .ev_handler = 0 };
 
-/* Helper, from u/p/uthread.c.  Keep it in sync.  (don't want to move this into
+/* Helper, from u/p/event.c.  Keep it in sync.  (don't want to move this into
  * glibc yet). */
 static bool register_evq(struct syscall *sysc, struct event_queue *ev_q)
 {
index a043465..259c5b1 100644 (file)
@@ -205,6 +205,62 @@ unsigned int get_event_type(struct event_mbox *ev_mbox)
        return EV_NONE;
 }
 
+/* Attempts to register ev_q with sysc, so long as sysc is not done/progress.
+ * Returns true if it succeeded, and false otherwise.  False means that the
+ * syscall is done, and does not need an event set (and should be handled
+ * accordingly).
+ *
+ * A copy of this is in glibc/sysdeps/akaros/syscall.c.  Keep them in sync. */
+bool register_evq(struct syscall *sysc, struct event_queue *ev_q)
+{
+       int old_flags;
+       sysc->ev_q = ev_q;
+       wrmb(); /* don't let that write pass any future reads (flags) */
+       /* Try and set the SC_UEVENT flag (so the kernel knows to look at ev_q) */
+       do {
+               /* no cmb() needed, the atomic_read will reread flags */
+               old_flags = atomic_read(&sysc->flags);
+               /* Spin if the kernel is mucking with syscall flags */
+               while (old_flags & SC_K_LOCK)
+                       old_flags = atomic_read(&sysc->flags);
+               /* If the kernel finishes while we are trying to sign up for an event,
+                * we need to bail out */
+               if (old_flags & (SC_DONE | SC_PROGRESS)) {
+                       sysc->ev_q = 0;         /* not necessary, but might help with bugs */
+                       return FALSE;
+               }
+       } while (!atomic_cas(&sysc->flags, old_flags, old_flags | SC_UEVENT));
+       return TRUE;
+}
+
+/* De-registers a syscall, so that the kernel will not send an event when it is
+ * done.  The call could already be SC_DONE, or could even finish while we try
+ * to unset SC_UEVENT.
+ *
+ * There is a chance the kernel sent an event if you didn't do this in time, but
+ * once this returns, the kernel won't send a message.
+ *
+ * If the kernel is trying to send a message right now, this will spin (on
+ * SC_K_LOCK).  We need to make sure we deregistered, and that if a message
+ * is coming, that it already was sent (and possibly overflowed), before
+ * returning. */
+void deregister_evq(struct syscall *sysc)
+{
+       int old_flags;
+       sysc->ev_q = 0;
+       wrmb(); /* don't let that write pass any future reads (flags) */
+       /* Try and unset the SC_UEVENT flag */
+       do {
+               /* no cmb() needed, the atomic_read will reread flags */
+               old_flags = atomic_read(&sysc->flags);
+               /* Spin if the kernel is mucking with syscall flags */
+               while (old_flags & SC_K_LOCK)
+                       old_flags = atomic_read(&sysc->flags);
+               /* Note we don't care if the SC_DONE flag is getting set.  We just need
+                * to avoid clobbering flags */
+       } while (!atomic_cas(&sysc->flags, old_flags, old_flags & ~SC_UEVENT));
+}
+
 /* Actual Event Handling */
 
 /* List of handler lists, process-wide.  They all must return (don't context
index 71db0b7..a90b485 100644 (file)
@@ -34,6 +34,8 @@ struct event_queue *disable_kevent(unsigned int ev_type);
 
 /********* Event Handling / Reception ***********/
 unsigned int get_event_type(struct event_mbox *ev_mbox);
+bool register_evq(struct syscall *sysc, struct event_queue *ev_q);
+void deregister_evq(struct syscall *sysc);
 
 typedef void (*handle_event_t)(struct event_msg *ev_msg, unsigned int ev_type,
                                void *data);
index d60273f..0669ff3 100644 (file)
@@ -88,9 +88,6 @@ bool __check_preempt_pending(uint32_t vcoreid);       /* careful: check the code */
 void uth_disable_notifs(void);
 void uth_enable_notifs(void);
 
-bool register_evq(struct syscall *sysc, struct event_queue *ev_q);
-void deregister_evq(struct syscall *sysc);
-
 /* Helpers, which sched_entry() can call */
 void highjack_current_uthread(struct uthread *uthread);
 void run_current_uthread(void);
index 7bb8c62..3967fa3 100644 (file)
@@ -1047,62 +1047,6 @@ static void handle_vc_indir(struct event_msg *ev_msg, unsigned int ev_type,
        handle_indirs(rem_vcoreid);
 }
 
-/* Attempts to register ev_q with sysc, so long as sysc is not done/progress.
- * Returns true if it succeeded, and false otherwise.  False means that the
- * syscall is done, and does not need an event set (and should be handled
- * accordingly).
- * 
- * A copy of this is in glibc/sysdeps/ros/syscall.c.  Keep them in sync. */
-bool register_evq(struct syscall *sysc, struct event_queue *ev_q)
-{
-       int old_flags;
-       sysc->ev_q = ev_q;
-       wrmb(); /* don't let that write pass any future reads (flags) */
-       /* Try and set the SC_UEVENT flag (so the kernel knows to look at ev_q) */
-       do {
-               /* no cmb() needed, the atomic_read will reread flags */
-               old_flags = atomic_read(&sysc->flags);
-               /* Spin if the kernel is mucking with syscall flags */
-               while (old_flags & SC_K_LOCK)
-                       old_flags = atomic_read(&sysc->flags);
-               /* If the kernel finishes while we are trying to sign up for an event,
-                * we need to bail out */
-               if (old_flags & (SC_DONE | SC_PROGRESS)) {
-                       sysc->ev_q = 0;         /* not necessary, but might help with bugs */
-                       return FALSE;
-               }
-       } while (!atomic_cas(&sysc->flags, old_flags, old_flags | SC_UEVENT));
-       return TRUE;
-}
-
-/* De-registers a syscall, so that the kernel will not send an event when it is
- * done.  The call could already be SC_DONE, or could even finish while we try
- * to unset SC_UEVENT.
- *
- * There is a chance the kernel sent an event if you didn't do this in time, but
- * once this returns, the kernel won't send a message.
- *
- * If the kernel is trying to send a message right now, this will spin (on
- * SC_K_LOCK).  We need to make sure we deregistered, and that if a message
- * is coming, that it already was sent (and possibly overflowed), before
- * returning. */
-void deregister_evq(struct syscall *sysc)
-{
-       int old_flags;
-       sysc->ev_q = 0;
-       wrmb(); /* don't let that write pass any future reads (flags) */
-       /* Try and unset the SC_UEVENT flag */
-       do {
-               /* no cmb() needed, the atomic_read will reread flags */
-               old_flags = atomic_read(&sysc->flags);
-               /* Spin if the kernel is mucking with syscall flags */
-               while (old_flags & SC_K_LOCK)
-                       old_flags = atomic_read(&sysc->flags);
-               /* Note we don't care if the SC_DONE flag is getting set.  We just need
-                * to avoid clobbering flags */
-       } while (!atomic_cas(&sysc->flags, old_flags, old_flags & ~SC_UEVENT));
-}
-
 static inline bool __uthread_has_tls(struct uthread *uthread)
 {
        return uthread->tls_desc != UTH_TLSDESC_NOTLS;