From owner-p4-projects Wed Jul 31 8:48:28 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 48B1537B420; Wed, 31 Jul 2002 08:47:43 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C603E37B41E for ; Wed, 31 Jul 2002 08:47:42 -0700 (PDT) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 982EB43E6E for ; Wed, 31 Jul 2002 08:47:15 -0700 (PDT) (envelope-from mini@freebsd.org) Received: from freefall.freebsd.org (perforce@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.4/8.12.4) with ESMTP id g6VFlBJU087044 for ; Wed, 31 Jul 2002 08:47:11 -0700 (PDT) (envelope-from mini@freebsd.org) Received: (from perforce@localhost) by freefall.freebsd.org (8.12.4/8.12.4/Submit) id g6VFlBv5087041 for perforce@freebsd.org; Wed, 31 Jul 2002 08:47:11 -0700 (PDT) Date: Wed, 31 Jul 2002 08:47:11 -0700 (PDT) Message-Id: <200207311547.g6VFlBv5087041@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: perforce set sender to mini@freebsd.org using -f From: Jonathan Mini Subject: PERFORCE change 15313 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://people.freebsd.org/~peter/p4db/chv.cgi?CH=15313 Change 15313 by mini@mini_stylus on 2002/07/31 08:46:11 Convert uthreads from setjmp()/longjmp() to swapcontext() and friends. Affected files ... .. //depot/projects/kse/lib/libc_r/uthread/Makefile.inc#2 edit .. //depot/projects/kse/lib/libc_r/uthread/pthread_private.h#2 edit .. //depot/projects/kse/lib/libc_r/uthread/uthread_create.c#2 edit .. //depot/projects/kse/lib/libc_r/uthread/uthread_init.c#2 edit .. //depot/projects/kse/lib/libc_r/uthread/uthread_jmp.c#2 delete .. //depot/projects/kse/lib/libc_r/uthread/uthread_kern.c#2 edit .. //depot/projects/kse/lib/libc_r/uthread/uthread_sig.c#2 edit Differences ... ==== //depot/projects/kse/lib/libc_r/uthread/Makefile.inc#2 (text+ko) ==== @@ -69,7 +69,6 @@ uthread_info.c \ uthread_init.c \ uthread_ioctl.c \ - uthread_jmp.c \ uthread_join.c \ uthread_kern.c \ uthread_kevent.c \ ==== //depot/projects/kse/lib/libc_r/uthread/pthread_private.h#2 (text+ko) ==== @@ -49,7 +49,6 @@ /* * Include files. */ -#include #include #include #include @@ -62,47 +61,15 @@ #include /* - * Define machine dependent macros to get and set the stack pointer - * from the supported contexts. Also define a macro to set the return - * address in a jmp_buf context. - * - * XXX - These need to be moved into architecture dependent support files. + * XXX - Grovelling around in the machine-dependant context only serves + * to get our hands dirty. */ #if defined(__i386__) -#define GET_STACK_JB(jb) ((unsigned long)((jb)[0]._jb[2])) -#define GET_STACK_SJB(sjb) ((unsigned long)((sjb)[0]._sjb[2])) -#define GET_STACK_UC(ucp) ((unsigned long)((ucp)->uc_mcontext.mc_esp)) -#define SET_STACK_JB(jb, stk) (jb)[0]._jb[2] = (int)(stk) -#define SET_STACK_SJB(sjb, stk) (sjb)[0]._sjb[2] = (int)(stk) -#define SET_STACK_UC(ucp, stk) (ucp)->uc_mcontext.mc_esp = (int)(stk) -#define FP_SAVE_UC(ucp) do { \ - char *fdata; \ - fdata = (char *) (ucp)->uc_mcontext.mc_fpregs; \ - __asm__("fnsave %0": :"m"(*fdata)); \ -} while (0) -#define FP_RESTORE_UC(ucp) do { \ - char *fdata; \ - fdata = (char *) (ucp)->uc_mcontext.mc_fpregs; \ - __asm__("frstor %0": :"m"(*fdata)); \ -} while (0) -#define SET_RETURN_ADDR_JB(jb, ra) (jb)[0]._jb[0] = (int)(ra) +#define UCP_STACK(ucp) ((unsigned long)((ucp)->uc_mcontext.mc_esp)) #elif defined(__alpha__) -#include -#define GET_STACK_JB(jb) ((unsigned long)((jb)[0]._jb[R_SP + 4])) -#define GET_STACK_SJB(sjb) ((unsigned long)((sjb)[0]._sjb[R_SP + 4])) -#define GET_STACK_UC(ucp) ((ucp)->uc_mcontext.mc_regs[R_SP]) -#define SET_STACK_JB(jb, stk) (jb)[0]._jb[R_SP + 4] = (long)(stk) -#define SET_STACK_SJB(sjb, stk) (sjb)[0]._sjb[R_SP + 4] = (long)(stk) -#define SET_STACK_UC(ucp, stk) (ucp)->uc_mcontext.mc_regs[R_SP] = (unsigned long)(stk) -#define FP_SAVE_UC(ucp) -#define FP_RESTORE_UC(ucp) -#define SET_RETURN_ADDR_JB(jb, ra) do { \ - (jb)[0]._jb[2] = (long)(ra); \ - (jb)[0]._jb[R_RA + 4] = (long)(ra); \ - (jb)[0]._jb[R_T12 + 4] = (long)(ra); \ -} while (0) +#define UCP_STACK(ucp) ((ucp)->uc_mcontext.mc_regs[R_SP]) #else -#error "Don't recognize this architecture!" +#error "Don't recognize this architecture!" #endif /* @@ -595,22 +562,12 @@ * up the thread to run a signal handler. */ struct pthread_signal_frame { - /* - * This stores the threads state before the signal. - */ - struct pthread_state_data saved_state; - - /* - * Threads return context; we use only jmp_buf's for now. - */ - union { - jmp_buf jb; - ucontext_t uc; - } ctx; - int signo; /* signal, arg 1 to sighandler */ - int sig_has_args; /* use signal args if true */ - ucontext_t uc; - siginfo_t siginfo; + struct pthread_state_data saved_state; /* State before the signal. */ + ucontext_t ctx; /* Thread's return context. */ + int signo; /* Signal, arg 1 to sighandler. */ + int sig_has_args; /* Use signal args if true. */ + ucontext_t uc; /* Pre-signal context. */ + siginfo_t siginfo; }; struct pthread_specific_elem { @@ -652,12 +609,9 @@ struct pthread_attr attr; /* - * Threads return context; we use only jmp_buf's for now. + * Machine context. */ - union { - jmp_buf jb; - ucontext_t uc; - } ctx; + ucontext_t ctx; /* * Used for tracking delivery of signal handlers. @@ -1096,9 +1050,9 @@ /* * Declare the kernel scheduler jump buffer and stack: */ -SCLASS jmp_buf _thread_kern_sched_jb; +SCLASS ucontext_t _thread_kern_sched_ctx; -SCLASS void * _thread_kern_sched_stack +SCLASS void * _thread_kern_sched_stack #ifdef GLOBAL_PTHREAD_PRIVATE = NULL #endif @@ -1322,12 +1276,6 @@ ssize_t __sys_write(int, const void *, size_t); #endif -/* #include */ -#ifdef _SETJMP_H_ -extern void __siglongjmp(sigjmp_buf, int) __dead2; -extern void __longjmp(jmp_buf, int) __dead2; -extern void ___longjmp(jmp_buf, int) __dead2; -#endif __END_DECLS #endif /* !_PTHREAD_PRIVATE_H */ ==== //depot/projects/kse/lib/libc_r/uthread/uthread_create.c#2 (text+ko) ==== @@ -128,21 +128,13 @@ /* Initialize the signal frame: */ new_thread->curframe = NULL; - /* Initialise the jump buffer: */ - _setjmp(new_thread->ctx.jb); - - /* - * Set up new stack frame so that it looks like it - * returned from a longjmp() to the beginning of - * _thread_start(). - */ - SET_RETURN_ADDR_JB(new_thread->ctx.jb, _thread_start); + /* Initialise the machine context: */ + getcontext(&new_thread->ctx); + new_thread->ctx.uc_stack.ss_sp = new_thread->stack; + new_thread->ctx.uc_stack.ss_size = + pattr->stacksize_attr; + makecontext(&new_thread->ctx, _thread_start, 1); - /* The stack starts high and builds down: */ - SET_STACK_JB(new_thread->ctx.jb, - (long)new_thread->stack + pattr->stacksize_attr - - sizeof(double)); - /* Copy the thread attributes: */ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); @@ -257,7 +249,7 @@ { struct pthread *curthread = _get_curthread(); - /* We just left the scheduler via longjmp: */ + /* We just left the scheduler via swapcontext: */ _thread_kern_in_sched = 0; /* Run the current thread's start routine with argument: */ ==== //depot/projects/kse/lib/libc_r/uthread/uthread_init.c#2 (text+ko) ==== @@ -312,15 +312,16 @@ /* Set the main thread stack pointer. */ _thread_initial->stack = _usrstack - PTHREAD_STACK_INITIAL; - /* Set the stack attributes: */ + /* Set the stack attributes. */ _thread_initial->attr.stackaddr_attr = _thread_initial->stack; _thread_initial->attr.stacksize_attr = PTHREAD_STACK_INITIAL; /* Setup the context for the scheduler: */ - _setjmp(_thread_kern_sched_jb); - SET_STACK_JB(_thread_kern_sched_jb, _thread_kern_sched_stack + - sched_stack_size - sizeof(double)); - SET_RETURN_ADDR_JB(_thread_kern_sched_jb, _thread_kern_scheduler); + getcontext(&_thread_kern_sched_ctx); + _thread_kern_sched_ctx.uc_stack.ss_sp = + _thread_kern_sched_stack; + _thread_kern_sched_ctx.uc_stack.ss_size = sched_stack_size; + makecontext(&_thread_kern_sched_ctx, _thread_kern_scheduler, 1); /* * Write a magic value to the thread structure @@ -332,6 +333,11 @@ _thread_initial->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED; + /* Setup the context for initial thread. */ + getcontext(&_thread_initial->ctx); + _thread_kern_sched_ctx.uc_stack.ss_sp = _thread_initial->stack; + _thread_kern_sched_ctx.uc_stack.ss_size = PTHREAD_STACK_INITIAL; + /* Default the priority of the initial thread: */ _thread_initial->base_priority = PTHREAD_DEFAULT_PRIORITY; _thread_initial->active_priority = PTHREAD_DEFAULT_PRIORITY; ==== //depot/projects/kse/lib/libc_r/uthread/uthread_kern.c#2 (text+ko) ==== @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -95,7 +94,7 @@ curthread->check_pending = 1; /* Switch to the thread scheduler: */ - ___longjmp(_thread_kern_sched_jb, 1); + swapcontext(&curthread->ctx, &_thread_kern_sched_ctx); } @@ -113,64 +112,56 @@ /* Check if this function was called from the signal handler: */ if (ucp != NULL) { - /* XXX - Save FP registers? */ - FP_SAVE_UC(ucp); called_from_handler = 1; DBG_MSG("Entering scheduler due to signal\n"); } - /* 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; + /* Switch into the scheduler's context. */ + swapcontext(&curthread->ctx, &_thread_kern_sched_ctx); + DBG_MSG("Returned from swapcontext, thread %p\n", 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(); - } + /* + * This point is reached when swapcontext() 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 (ucp == NULL) - return; - else { - /* XXX - Restore FP registers? */ - FP_RESTORE_UC(ucp); - + if (curthread->sig_defer_count == 0) { + if (((curthread->cancelflags & + PTHREAD_AT_CANCEL_POINT) == 0) && + ((curthread->cancelflags & + PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) /* - * Set the process signal mask in the context; it - * could have changed by the handler. + * 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. */ - ucp->uc_sigmask = _process_sigmask; + 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 { + /* + * 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); - } + /* Resume the interrupted thread: */ + __sys_sigreturn(ucp); } - /* Switch to the thread scheduler: */ - ___longjmp(_thread_kern_sched_jb, 1); } void @@ -193,30 +184,31 @@ unsigned int current_tick; int add_to_prioq; - /* If the currently running thread is a user thread, save it: */ - if ((curthread->flags & PTHREAD_FLAGS_PRIVATE) == 0) - _last_user_thread = curthread; - - if (called_from_handler != 0) { - called_from_handler = 0; - - /* - * 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"); - } - /* * Enter a scheduling loop that finds the next thread that is * ready to run. This loop completes when there are no more threads - * in the global list or when a thread has its state restored by - * either a sigreturn (if the state was saved as a sigcontext) or a - * longjmp (if the state was saved by a setjmp). + * in the global list. It is interrupted each time a thread is + * scheduled, but will continue when we return. */ while (!(TAILQ_EMPTY(&_thread_list))) { + + /* If the currently running thread is a user thread, save it: */ + if ((curthread->flags & PTHREAD_FLAGS_PRIVATE) == 0) + _last_user_thread = curthread; + + if (called_from_handler != 0) { + called_from_handler = 0; + + /* + * 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"); + } + /* Get the current time of day: */ GET_CURRENT_TOD(tv); TIMEVAL_TO_TIMESPEC(&tv, &ts); @@ -584,13 +576,7 @@ /* * Continue the thread at its current frame: */ -#if NOT_YET - _setcontext(&curthread->ctx.uc); -#else - ___longjmp(curthread->ctx.jb, 1); -#endif - /* This point should not be reached. */ - PANIC("Thread has returned from sigreturn or longjmp"); + swapcontext(&_thread_kern_sched_ctx, &curthread->ctx); } } ==== //depot/projects/kse/lib/libc_r/uthread/uthread_sig.c#2 (text+ko) ==== @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include "pthread_private.h" @@ -1008,7 +1007,7 @@ /* * Lower the priority before calling the handler in case - * it never returns (longjmps back): + * it never returns (e.g., it switchcontext()s): */ thread->active_priority &= ~PTHREAD_SIGNAL_PRIORITY; @@ -1038,9 +1037,11 @@ { struct pthread_signal_frame *psf = NULL; unsigned long stackp; + size_t stacksize; + char *stackbase; /* Get the top of the threads stack: */ - stackp = GET_STACK_JB(thread->ctx.jb); + stackp = UCP_STACK(&thread->ctx); /* * Leave a little space on the stack and round down to the @@ -1080,9 +1081,13 @@ * Set up the context: */ stackp -= sizeof(double); - _setjmp(thread->ctx.jb); - SET_STACK_JB(thread->ctx.jb, stackp); - SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper); + stackbase = thread->ctx.uc_stack.ss_sp; + stacksize = thread->ctx.uc_stack.ss_size; + getcontext(&thread->ctx); + thread->ctx.uc_stack.ss_sp = stackbase; + thread->ctx.uc_stack.ss_size = stacksize; + makecontext(&thread->ctx, _thread_sig_wrapper, 1); + UCP_STACK(&thread->ctx) = stackp; } void To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message