Add callbacks to close() (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 18 Dec 2015 22:59:09 +0000 (17:59 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 14 Jan 2016 21:04:46 +0000 (16:04 -0500)
Akaros has various utilities in userspace that operate on FDs, but those
facilities are in the kernel in other OSs.  These facilities would like to
know when the FD is closed.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/Makefile
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/Versions
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/close.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/close_cb.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sys/close_cb.h [new file with mode: 0644]

index d8f008b..fa44dc5 100644 (file)
@@ -55,8 +55,10 @@ endif
 # User FDs
 ifeq ($(subdir),stdlib)
 sysdep_routines += user_fd
+sysdep_routines += close_cb
 endif
 sysdep_headers += sys/user_fd.h
+sysdep_headers += sys/close_cb.h
 # Epoll: uses User FDs, implemented in iplib
 sysdep_headers += sys/epoll.h bits/epoll.h
 
index d2b3cc3..03a8fa2 100644 (file)
@@ -48,6 +48,8 @@ libc {
     ufd_get_fd;
     ufd_lookup;
 
+    register_close_cb;
+
     _sock_get_listen_fd;
     _sock_lookup_listen_fd;
 
index fc9f0df..916471f 100644 (file)
 #include <stddef.h>
 #include <ros/syscall.h>
 #include <sys/user_fd.h>
+#include <sys/close_cb.h>
 
-/* Write NBYTES of BUF to FD.  Return the number written, or -1.  */
-int
-__close (int fd)
+int __close(int fd)
 {
+       struct close_cb *cb = close_callbacks;
+
+       /* Another thread could be publishing a new callback to the front of the
+        * list concurrently.  We'll miss that callback.  They to handle this,
+        * usually by making sure their CB is registered before using FDs. */
+       while (cb) {
+               cb->func(fd);
+               cb = cb->next;
+       }
        if (fd >= USER_FD_BASE)
                return glibc_close_helper(fd);
        else
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/close_cb.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/close_cb.c
new file mode 100644 (file)
index 0000000..19114b7
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (c) 2015 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * close() callbacks.  See sys/close_cb.h. */
+
+#include <sys/close_cb.h>
+#include <ros/common.h>
+
+struct close_cb *close_callbacks;
+
+void register_close_cb(struct close_cb *cb)
+{
+       struct close_cb *old;
+
+       do {
+               old = ACCESS_ONCE(close_callbacks);
+               cb->next = old;
+       } while (!__sync_bool_compare_and_swap(&close_callbacks, old, cb));
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sys/close_cb.h b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sys/close_cb.h
new file mode 100644 (file)
index 0000000..784a977
--- /dev/null
@@ -0,0 +1,30 @@
+/* Copyright (c) 2015 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * close() callbacks.
+ *
+ * Akaros has various utilities in userspace that operate on FDs, but those
+ * facilities are in the kernel in other OSs.  Examples include epoll and the
+ * Rocks (socket layer).  So far, these are only for compatibility.
+ *
+ * These facilities would like to know when the FD is closed.  In lieu of
+ * encoding the callback info in the FD, close() will call all of the registered
+ * callbacks for every FD that closes.  That's not ideal, so these facilities
+ * should only register their FD if a program actually uses the facility.
+ *
+ * To register a cb, do your own allocation of a close_cb, fill in func, then
+ * call register_close_cb.  You cannot remove your CB.  Concurrent calls to
+ * close() may or may not run your callback.  Do not hand out an FD to a user
+ * until you have registered your CB. */
+
+#pragma once
+
+struct close_cb {
+       struct close_cb                         *next;
+       void (*func)(int fd);
+};
+
+extern struct close_cb *close_callbacks;       /* for use within glibc */
+
+void register_close_cb(struct close_cb *cb);