Add level of indirection for signal funcs in 2LS
authorKevin Klues <klueska@cs.berkeley.edu>
Sat, 6 Jun 2015 00:31:50 +0000 (17:31 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 12 Jun 2015 16:03:19 +0000 (12:03 -0400)
Some signal functions (like sigprocmask()) are 2LS specific and need to
be implemented as such. We use a level of indirection similar to the
sched_ops for this.

user/parlib/include/parlib.h
user/parlib/signal.c
user/pthread/pthread.c

index 03599c0..efd4449 100644 (file)
@@ -65,6 +65,12 @@ struct sigdata {
        struct siginfo info;
        void *stack;
 };
+/* This is the set of global function pointers that a 2LS using signals needs
+ * to implement.  Subject to grow over time. */
+struct signal_ops {
+       int (*sigprocmask)(int, __const sigset_t *__restrict, sigset_t *__restrict);
+};
+extern struct signal_ops *signal_ops;
 void init_posix_signals(void);
 struct sigdata *alloc_sigdata();
 void free_sigdata(struct sigdata *sigdata);
index abf515a..cc726d0 100644 (file)
 /* This is list of sigactions associated with each posix signal. */
 static struct sigaction sigactions[_NSIG];
 
+/* Forward declare some functions. */
+static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
+                         sigset_t *__restrict __oset);
+
+/* The default definition of signal_ops (similar to sched_ops in uthread.c) */
+struct signal_ops default_signal_ops = {
+       .sigprocmask = __sigprocmask,
+};
+struct signal_ops *signal_ops __attribute__((weak)) = &default_signal_ops;
+
 /* This is a wait-free-list used to hold the data necessary to execute signal
  * handlers inside a 2LS. We are able to store them in a wfl because all
  * sigdata structs are created equal, and reuse is encouraged as uthreads
@@ -252,17 +262,20 @@ int sigismember(__const sigset_t *__set, int __signo)
        return 0;
 }
 
-/* Would need a layer/interposition to ignore blocked signals when they come in,
- * and then to manually play them when they are unblocked, like how x86 does
- * with the IRR and the ISR for interrupt delivery. */
-int sigprocmask(int __how, __const sigset_t *__restrict __set,
-                sigset_t *__restrict __oset)
+static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
+                         sigset_t *__restrict __oset)
 {
        printf("Function not supported generically! "
            "Use 2LS specific function e.g. pthread_sigmask\n");
        return 0;
 }
 
+int sigprocmask(int __how, __const sigset_t *__restrict __set,
+                sigset_t *__restrict __oset)
+{
+       return signal_ops->sigprocmask(__how, __set, __oset);
+}
+
 /* Could do this with a loop on delivery of the signal, sleeping and getting
  * woken up by the kernel on any event, like we do with async syscalls. */
 int sigsuspend(__const sigset_t *__set)
index 1787d95..53ea81c 100644 (file)
@@ -67,9 +67,13 @@ struct schedule_ops pthread_sched_ops = {
        0, /* pth_preempt_pending, */
        0, /* pth_spawn_thread, */
 };
+struct signal_ops pthread_signal_ops = {
+       .sigprocmask = pthread_sigmask,
+};
 
-/* Publish our sched_ops, overriding the weak defaults */
+/* Publish our sched_ops and signal_ops, overriding the weak defaults */
 struct schedule_ops *sched_ops = &pthread_sched_ops;
+struct signal_ops *signal_ops = &pthread_signal_ops;
 
 /* Static helpers */
 static void __pthread_free_stack(struct pthread_tcb *pt);