Also send SIGSEGV on EACCES fault
[akaros.git] / user / pthread / pthread.c
index 56cc8ea..924db08 100644 (file)
@@ -74,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). */
@@ -88,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 */
@@ -125,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);
@@ -298,8 +313,8 @@ void pth_thread_refl_fault(struct uthread *uthread, unsigned int trap_nr,
        TAILQ_REMOVE(&active_queue, pthread, next);
        mcs_pdr_unlock(&queue_lock);
 
-       if (trap_nr != 14) {
-               printf("Pthread has unhandled fault\n");
+       if (trap_nr != 14 && trap_nr != 13) {
+               printf("Pthread has unhandled fault: %d\n", trap_nr);
                print_user_context(&uthread->u_ctx);
                exit(-1);
        }
@@ -445,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);