Signal with different u_ctx if current_uthread set
[akaros.git] / user / pthread / pthread.c
index 2cd0e16..192dfb8 100644 (file)
@@ -48,7 +48,8 @@ void pth_preempt_pending(void);
 void pth_spawn_thread(uintptr_t pc_start, void *data);
 
 /* Event Handlers */
-static void pth_handle_syscall(struct event_msg *ev_msg, unsigned int ev_type);
+static void pth_handle_syscall(struct event_msg *ev_msg, unsigned int ev_type,
+                               void *data);
 
 struct schedule_ops pthread_sched_ops = {
        pth_sched_entry,
@@ -73,13 +74,35 @@ static void __pthread_trigger_posix_signal(pthread_t thread, int signo,
                                            struct siginfo *info)
 {
        int vcoreid = vcore_id();
+       struct user_context *ctx;
+       if (current_uthread) {
+               struct preempt_data *vcpd = vcpd_of(vcoreid);
+        ctx = &vcpd->uthread_ctx;
+       } else {
+               ctx = &thread->uthread.u_ctx;
+       }
+
        void *temp_tls_desc = get_tls_desc(vcoreid);
-       struct uthread *uthread = (struct uthread*)thread;
-       set_tls_desc(uthread->tls_desc, vcore_id());
-       trigger_posix_signal(signo, info, &uthread->u_ctx);
+       set_tls_desc(thread->uthread.tls_desc, vcoreid);
+       trigger_posix_signal(signo, info, ctx);
        set_tls_desc(temp_tls_desc, vcoreid);
 }
 
+static void __pthread_trigger_pending_posix_signals(pthread_t thread)
+{
+       if (thread->sigpending) {
+               sigset_t andset = thread->sigpending & (~thread->sigmask);
+               if (!__sigisemptyset(&andset)) {
+                       for (int i = 1; i < _NSIG; i++) {
+                               if (__sigismember(&andset, i)) {
+                                       __sigdelset(&thread->sigpending, i);
+                                       __pthread_trigger_posix_signal(thread, i, NULL);
+                               }
+                       }
+               }
+       }
+}
+
 /* Called from vcore entry.  Options usually include restarting whoever was
  * running there before or running a new thread.  Events are handled out of
  * event.c (table of function pointers, stuff like that). */
@@ -87,7 +110,10 @@ void __attribute__((noreturn)) pth_sched_entry(void)
 {
        uint32_t vcoreid = vcore_id();
        if (current_uthread) {
+               /* Run any pending posix signal handlers registered via pthread_kill */
+               __pthread_trigger_pending_posix_signals((pthread_t)current_uthread);
                run_current_uthread();
+               /* Run the thread itself */
                assert(0);
        }
        /* no one currently running, so lets get someone from the ready queue */
@@ -124,17 +150,7 @@ void __attribute__((noreturn)) pth_sched_entry(void)
        } while (1);
        assert(new_thread->state == PTH_RUNNABLE);
        /* Run any pending posix signal handlers registered via pthread_kill */
-       if (new_thread->sigpending) {
-               sigset_t andset = new_thread->sigpending & (~new_thread->sigmask);
-               if (!__sigisemptyset(&andset)) {
-                       for (int i = 1; i < _NSIG; i++) {
-                               if (__sigismember(&andset, i)) {
-                                       __sigdelset(&new_thread->sigpending, i);
-                                       __pthread_trigger_posix_signal(new_thread, i, NULL);
-                               }
-                       }
-               }
-       }
+       __pthread_trigger_pending_posix_signals(new_thread);
        /* Run the thread itself */
        run_uthread((struct uthread*)new_thread);
        assert(0);
@@ -226,7 +242,8 @@ static void restart_thread(struct syscall *sysc)
 
 /* This handler is usually run in vcore context, though I can imagine it being
  * called by a uthread in some other threading library. */
-static void pth_handle_syscall(struct event_msg *ev_msg, unsigned int ev_type)
+static void pth_handle_syscall(struct event_msg *ev_msg, unsigned int ev_type,
+                               void *data)
 {
        struct syscall *sysc;
        assert(in_vcore_context());
@@ -443,7 +460,7 @@ void pthread_lib_init(void)
        enable_kevent(EV_USER_IPI, 0, EVENT_IPI | EVENT_VCORE_PRIVATE);
 
        /* Handle syscall events. */
-       ev_handlers[EV_SYSCALL] = pth_handle_syscall;
+       register_ev_handler(EV_SYSCALL, pth_handle_syscall, 0);
        /* Set up the per-vcore structs to track outstanding syscalls */
        sysc_mgmt = malloc(sizeof(struct sysc_mgmt) * max_vcores());
        assert(sysc_mgmt);