Remove need for externally alloced sigdata struct
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 10 Nov 2015 21:52:31 +0000 (13:52 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 16 Nov 2015 23:15:03 +0000 (15:15 -0800)
We now use space on the stack for storing the original user context and
and any signal specific state when triggering a posix signal on a
pthread.

As a side effect, we should now be able to safely longjmp out of a
signal handler because there is no longer any external state
to clean up when the signal handler completes.

Signed-off-by: Kevin Klues <klueska@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/parlib/include/signal.h
user/parlib/signal.c
user/pthread/pthread.c

index 6d6ce99..4e30496 100644 (file)
@@ -17,7 +17,6 @@ struct sigdata {
        struct user_context u_ctx;
        struct ancillary_state as;
        struct siginfo info;
-       void *stack;
 };
 
 /* A set of functions related to handling posix signals on akaros. The
@@ -44,6 +43,4 @@ extern struct signal_ops *signal_ops;
 
 /* External API for initializing and generating posix signals inside a 2LS. */
 void init_posix_signals(void);
-struct sigdata *alloc_sigdata();
-void free_sigdata(struct sigdata *sigdata);
 void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux);
index 9817135..3c41b94 100644 (file)
@@ -71,39 +71,6 @@ struct signal_ops default_signal_ops = {
        .sigwaitinfo = __sigwaitinfo
 };
 
-/* 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
- * ask for them on demand. */
-static struct wfl sigdata_list;
-#define SIGNAL_STACK_SIZE (2*PGSIZE + sizeof(struct sigdata))
-
-/* This function allocates a sigdata struct for use when running signal
- * handlers inside a 2LS. The sigdata struct returned is pre-initialized with
- * the 'stack' field pointing to a valid stack.  Space is allocated for both
- * the sigdata struct and the stack in a single mmap call.  The sigdata struct
- * just sits at the bottom of the stack, and its 'stack' field points just
- * above it.  */
-struct sigdata *alloc_sigdata()
-{
-       struct sigdata *data = wfl_remove(&sigdata_list);
-       if (data == NULL) {
-               void *stack = mmap(0, SIGNAL_STACK_SIZE,
-                                  PROT_READ|PROT_WRITE|PROT_EXEC,
-                                  MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
-               assert(stack != MAP_FAILED);
-               data = stack + SIGNAL_STACK_SIZE - sizeof(struct sigdata);
-               data->stack = data;
-       }
-       return data;
-}
-
-/* This function frees a previously allocated sigdata struct. */
-void free_sigdata(struct sigdata *sigdata)
-{
-       wfl_insert(&sigdata_list, sigdata);
-}
-
 /* This is the catch all akaros event->posix signal handler.  All posix signals
  * are received in a single akaros event type.  They are then dispatched from
  * this function to their proper posix signal handler */
@@ -131,7 +98,6 @@ void init_posix_signals(void)
        posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
                                   EVENT_WAKEUP;
        register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
-       wfl_init(&sigdata_list);
 }
 
 /* This is managed by vcore / 2LS code */
index 0eeb5d1..7ed8ffc 100644 (file)
@@ -84,16 +84,13 @@ static void __pthread_prep_sighandler(struct pthread_tcb *pthread,
                                       void (*entry)(void),
                                       struct siginfo *info)
 {
+       uintptr_t stack;
        struct user_context *ctx;
 
-       pthread->sigdata = alloc_sigdata();
-       if (info != NULL)
-               pthread->sigdata->info = *info;
-       init_user_ctx(&pthread->sigdata->u_ctx,
-                     (uintptr_t)entry,
-                     (uintptr_t)pthread->sigdata->stack);
        if (pthread->uthread.flags & UTHREAD_SAVED) {
                ctx = &pthread->uthread.u_ctx;
+               stack = get_user_ctx_stack(ctx) - sizeof(struct sigdata);
+               pthread->sigdata = (struct sigdata*)stack;
                if (pthread->uthread.flags & UTHREAD_FPSAVED) {
                        pthread->sigdata->as = pthread->uthread.as;
                        pthread->uthread.flags &= ~UTHREAD_FPSAVED;
@@ -101,8 +98,14 @@ static void __pthread_prep_sighandler(struct pthread_tcb *pthread,
        } else {
                assert(current_uthread == &pthread->uthread);
                ctx = &vcpd_of(vcore_id())->uthread_ctx;
+               stack = get_user_ctx_stack(ctx) - sizeof(struct sigdata);
+               pthread->sigdata = (struct sigdata*)stack;
                save_fp_state(&pthread->sigdata->as);
        }
+       if (info != NULL)
+               pthread->sigdata->info = *info;
+
+       init_user_ctx(&pthread->sigdata->u_ctx, (uintptr_t)entry, stack);
        swap_user_contexts(ctx, &pthread->sigdata->u_ctx);
 }
 
@@ -116,7 +119,6 @@ static void __pthread_restore_after_sighandler(struct pthread_tcb *pthread)
                pthread->uthread.as = pthread->sigdata->as;
                pthread->uthread.flags |= UTHREAD_FPSAVED;
        }
-       free_sigdata(pthread->sigdata);
        pthread->sigdata = NULL;
 }