diff options
author | deischen <deischen@FreeBSD.org> | 2002-02-09 19:58:41 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2002-02-09 19:58:41 +0000 |
commit | 4ed9f7fd062cd8c757f7325cad3bc2ea2c340e84 (patch) | |
tree | dc39d813fe8f056c1b1cfa1a5216fba9998c6103 /lib/libpthread/thread/thr_kern.c | |
parent | 04de78234927ede2f34f9b1286fb8344dafa63fc (diff) | |
download | FreeBSD-src-4ed9f7fd062cd8c757f7325cad3bc2ea2c340e84.zip FreeBSD-src-4ed9f7fd062cd8c757f7325cad3bc2ea2c340e84.tar.gz |
This has been sitting in my local tree long enough. Remove the use
of an alternate signal stack for handling signals. Let the kernel
send signals on the stack of the current thread and teach the threads
signal handler how to deliver signals to the current thread if it
needs to. Also, always store a threads context as a jmp_buf. Eventually
this will change to be a ucontext_t or mcontext_t.
Other small nits. Use struct pthread * instead of pthread_t in internal
library routines. The threads code wants struct pthread *, and pthread_t
doesn't necessarily have to be the same.
Reviewed by: jasone
Diffstat (limited to 'lib/libpthread/thread/thr_kern.c')
-rw-r--r-- | lib/libpthread/thread/thr_kern.c | 138 |
1 files changed, 55 insertions, 83 deletions
diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c index ec4c233..a4cc3c3 100644 --- a/lib/libpthread/thread/thr_kern.c +++ b/lib/libpthread/thread/thr_kern.c @@ -100,7 +100,7 @@ _thread_kern_sched_frame(struct pthread_signal_frame *psf) void -_thread_kern_sched(ucontext_t *scp) +_thread_kern_sched(ucontext_t *ucp) { struct pthread *curthread = _get_curthread(); @@ -112,50 +112,61 @@ _thread_kern_sched(ucontext_t *scp) _thread_kern_in_sched = 1; /* Check if this function was called from the signal handler: */ - if (scp != NULL) { + if (ucp != NULL) { + /* XXX - Save FP registers? */ + FP_SAVE_UC(ucp); called_from_handler = 1; DBG_MSG("Entering scheduler due to signal\n"); - } else { - /* Save the state of the current thread: */ - if (_setjmp(curthread->ctx.jb) == 0) { - /* Flag the jump buffer was the last state saved: */ - curthread->ctxtype = CTX_JB_NOSIG; - curthread->longjmp_val = 1; - } else { - DBG_MSG("Returned from ___longjmp, thread %p\n", - curthread); - /* - * This point is reached when a longjmp() is called - * to restore the state of a thread. - * - * This is the normal way out of the scheduler. - */ - _thread_kern_in_sched = 0; + } - if (curthread->sig_defer_count == 0) { - if (((curthread->cancelflags & - PTHREAD_AT_CANCEL_POINT) == 0) && - ((curthread->cancelflags & - PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) - /* - * Cancellations override signals. - * - * Stick a cancellation point at the - * start of each async-cancellable - * thread's resumption. - * - * We allow threads woken at cancel - * points to do their own checks. - */ - pthread_testcancel(); - } + /* Save the state of the current thread: */ + if (_setjmp(curthread->ctx.jb) != 0) { + DBG_MSG("Returned from ___longjmp, thread %p\n", + curthread); + /* + * This point is reached when a longjmp() is called + * to restore the state of a thread. + * + * This is the normal way out of the scheduler. + */ + _thread_kern_in_sched = 0; - if (_sched_switch_hook != NULL) { - /* Run the installed switch hook: */ - thread_run_switch_hook(_last_user_thread, - curthread); - } + if (curthread->sig_defer_count == 0) { + if (((curthread->cancelflags & + PTHREAD_AT_CANCEL_POINT) == 0) && + ((curthread->cancelflags & + PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) + /* + * Cancellations override signals. + * + * Stick a cancellation point at the + * start of each async-cancellable + * thread's resumption. + * + * We allow threads woken at cancel + * points to do their own checks. + */ + pthread_testcancel(); + } + + if (_sched_switch_hook != NULL) { + /* Run the installed switch hook: */ + thread_run_switch_hook(_last_user_thread, curthread); + } + if (ucp == NULL) return; + else { + /* XXX - Restore FP registers? */ + FP_RESTORE_UC(ucp); + + /* + * Set the process signal mask in the context; it + * could have changed by the handler. + */ + ucp->uc_sigmask = _process_sigmask; + + /* Resume the interrupted thread: */ + __sys_sigreturn(ucp); } } /* Switch to the thread scheduler: */ @@ -190,20 +201,12 @@ _thread_kern_scheduler(void) called_from_handler = 0; /* - * The signal handler should have saved the state of - * the current thread. Restore the process signal - * mask. + * We were called from a signal handler; restore the process + * signal mask. */ if (__sys_sigprocmask(SIG_SETMASK, &_process_sigmask, NULL) != 0) PANIC("Unable to restore process mask after signal"); - - /* - * Since the signal handler didn't return normally, we - * have to tell the kernel to reuse the signal stack. - */ - if (__sys_sigaltstack(&_thread_sigstack, NULL) != 0) - PANIC("Unable to restore alternate signal stack"); } /* @@ -581,42 +584,11 @@ _thread_kern_scheduler(void) /* * Continue the thread at its current frame: */ - switch(curthread->ctxtype) { - case CTX_JB_NOSIG: - ___longjmp(curthread->ctx.jb, - curthread->longjmp_val); - break; - case CTX_JB: - __longjmp(curthread->ctx.jb, - curthread->longjmp_val); - break; - case CTX_SJB: - __siglongjmp(curthread->ctx.sigjb, - curthread->longjmp_val); - break; - case CTX_UC: - /* XXX - Restore FP regsisters? */ - FP_RESTORE_UC(&curthread->ctx.uc); - - /* - * Do a sigreturn to restart the thread that - * was interrupted by a signal: - */ - _thread_kern_in_sched = 0; - #if NOT_YET - _setcontext(&curthread->ctx.uc); + _setcontext(&curthread->ctx.uc); #else - /* - * Ensure the process signal mask is set - * correctly: - */ - curthread->ctx.uc.uc_sigmask = - _process_sigmask; - __sys_sigreturn(&curthread->ctx.uc); + ___longjmp(curthread->ctx.jb, 1); #endif - break; - } /* This point should not be reached. */ PANIC("Thread has returned from sigreturn or longjmp"); } |