Date: Fri, 31 Dec 2004 14:51:56 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 67973 for review Message-ID: <200412311451.iBVEpuAp008978@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=67973 Change 67973 by davidxu@davidxu_tiger on 2004/12/31 14:51:33 remove unused code. use SIGCANCEL defined in thr_private.h to do asynchronous cancellation. Affected files ... .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_sig.c#4 edit Differences ... ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_sig.c#4 (text+ko) ==== @@ -43,13 +43,6 @@ #include <pthread.h> #include "thr_private.h" -/* Prototypes: */ -static inline void build_siginfo(siginfo_t *info, int signo); -static inline void thr_sigframe_restore(struct pthread *thread, - struct pthread_sigframe *psf); -static inline void thr_sigframe_save(struct pthread *thread, - struct pthread_sigframe *psf); - /* #define DEBUG_SIGNAL */ #ifdef DEBUG_SIGNAL #define DBG_MSG stdout_debug @@ -59,11 +52,11 @@ typedef void (*ohandler)(int sig, int code, struct sigcontext *scp, char *addr, __sighandler_t *catcher); +static void thr_cancel_handler(struct pthread *); void _thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp) { - struct pthread_sigframe psf; __siginfohandler_t *sigfunc; struct pthread *curthread; struct sigaction act; @@ -76,7 +69,7 @@ curthread = _get_curthread(); if (curthread == NULL) PANIC("No current thread.\n"); - if (curthread->flags & THR_FLAGS_EXITING) { + if (curthread->state == PS_DEAD) { errno = err_save; return; } @@ -85,40 +78,27 @@ * If thread is in critical region or if thread is on * the way of state transition, then latch signal into buffer. */ - if (THR_IN_CRITICAL(curthread) || curthread->state != PS_RUNNING || - curthread->lock_switch != 0 || curthread->idle != 0) { + if (THR_IN_CRITICAL(curthread)) { DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig); curthread->siginfo[sig-1] = *info; curthread->check_pending = 1; - curthread->sigseqno++; SIGADDSET(curthread->sigpend, sig); - /* - * If the thread is on the way to idle itself, but - * we have signal ready, we should prevent it - * to sleep, kernel will latch the wakeup request, - * so thr_suspend will return from kernel immediately. - */ - if (curthread->idle) - thr_wake(curthread->tid); errno = err_save; return; } - /* Check if the signal requires a dump of thread information: */ - if (sig == SIGINFO) { - /* Dump thread information to file: */ - _thread_dump_info(); - } - /* Check the threads previous state: */ curthread->critical_count++; if (curthread->sigbackout != NULL) curthread->sigbackout((void *)curthread); curthread->critical_count--; - thr_sigframe_save(curthread, &psf); + + if (sig == SIGCANCEL) + thr_cancel_handler(curthread); THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared."); + /* Reset signal handler if needed */ THR_LOCK_ACQUIRE(curthread, &_thread_signal_lock); sigfunc = _thread_sigact[sig - 1].sa_sigaction; sa_flags = _thread_sigact[sig - 1].sa_flags; @@ -142,25 +122,17 @@ sig, info->si_code, (struct sigcontext *)ucp, info->si_addr, (__sighandler_t *)sigfunc); } - } else if ((__sighandler_t *)sigfunc == SIG_DFL) { - thr_kill(curthread->tid, sig); + } else if (sig != SIGCANCEL && (__sighandler_t *)sigfunc == SIG_DFL) { + thr_kill(curthread->tid, sig); } - thr_sigframe_restore(curthread, &psf); + SIGDELSET(ucp->uc_sigmask, SIGCANCEL); DBG_MSG("<<< _thr_sig_handler(%d)\n", sig); errno = err_save; } -static inline void -build_siginfo(siginfo_t *info, int signo) -{ - bzero(info, sizeof(*info)); - info->si_signo = signo; - info->si_pid = _thr_pid; -} - /* * This is called by a thread when it has pending signals to deliver. * It should only be called from the context of the thread. @@ -169,7 +141,7 @@ _thr_sig_rundown(struct pthread *curthread) { int i, err_save; - sigset_t sigmask; + sigset_t sigmask, oldmask; err_save = errno; @@ -178,7 +150,7 @@ SIGFILLSET(sigmask); /* repost signal to kernel */ if (!SIGISEMPTY(curthread->sigpend)) { - __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask); + __sys_sigprocmask(SIG_SETMASK, &sigmask, &oldmask); for (i = 1; i <= _SIG_MAXSIG; ++i) { if (SIGISMEMBER(curthread->sigpend, i)) { SIGDELSET(curthread->sigpend, i); @@ -188,35 +160,21 @@ thr_kill(curthread->tid, i); } } - __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); + __sys_sigprocmask(SIG_SETMASK, &oldmask, NULL); } DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread); errno = err_save; } /* - * This checks pending signals for the current thread. It should be - * called whenever a thread changes its signal mask. Note that this - * is called from a thread (using its stack). - * - * XXX - We might want to just check to see if there are pending - * signals for the thread here, but enter the UTS scheduler - * to actually install the signal handler(s). + * This checks pending signals for the current thread. */ void _thr_sig_check_pending(struct pthread *curthread) { int errsave; - /* - * If the thread is in critical region, delay processing signals. - * If the thread state is not PS_RUNNING, it might be switching - * into UTS and but a THR_LOCK_RELEASE saw check_pending, and it - * goes here, in the case we delay processing signals, lets UTS - * process complicated things, normally UTS will call _thr_sig_add - * to resume the thread, so we needn't repeat doing it here. - */ - if (THR_IN_CRITICAL(curthread) || curthread->lock_switch) + if (THR_IN_CRITICAL(curthread)) return; errsave = errno; @@ -225,137 +183,51 @@ errno = errsave; } -/* - * Perform thread specific actions in response to a signal. - * This function is only called if there is a handler installed - * for the signal, and if the target thread has the signal - * unmasked. - * - * This must be called with the thread's scheduling lock held. - */ -long -_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info) +static void +thr_cancel_handler(struct pthread *curthread) { - struct pthread *curthread = _get_curthread(); - long tid = -1; - int suppress_handler = 0; - __sighandler_t *sigfunc; - - DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig); - - sigfunc = _thread_sigact[sig - 1].sa_handler; - - if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK || - pthread->state == PS_STATE_MAX) - return (-1); /* return false */ - - if (curthread != pthread) { - PANIC("Please use _thr_send_sig for bound thread"); - return (-1); + if ((curthread->cancelflags & + (THR_CANCEL_AT_POINT | THR_CANCEL_ASYNCHRONOUS))) { + pthread_testcancel(); } + _thr_suspend_check(curthread); +} - if (SIGISMEMBER(pthread->sigmask, sig) || THR_IN_CRITICAL(pthread)) { - /* signal is masked, just add signal to thread. */ - SIGADDSET(pthread->sigpend, sig); - if (info == NULL) - build_siginfo(&pthread->siginfo[sig-1], sig); - else if (info != &pthread->siginfo[sig-1]) - memcpy(&pthread->siginfo[sig-1], info, - sizeof(*info)); - if (!SIGISMEMBER(pthread->sigmask, sig)) - pthread->check_pending = 1; - } else { - /* - * Process according to thread state: - */ - switch (pthread->state) { - case PS_DEAD: - case PS_DEADLOCK: - case PS_STATE_MAX: - return (-1); /* XXX return false */ - case PS_SUSPENDED: - /* - * You can't call a signal handler for threads in these - * states. - */ - suppress_handler = 1; - break; - case PS_RUNNING: - /* Possible not in RUNQ and has curframe ? */ - /* pthread->active_priority |= THR_SIGNAL_PRIORITY; */ - break; - /* - * States which cannot be interrupted but still require the - * signal handler to run: - */ - case PS_MUTEX_WAIT: - break; - case PS_JOIN: - break; - } - - SIGADDSET(pthread->sigpend, sig); - if (info == NULL) - build_siginfo(&pthread->siginfo[sig-1], sig); - else if (info != &pthread->siginfo[sig-1]) - memcpy(&pthread->siginfo[sig-1], info, sizeof(*info)); - pthread->check_pending = 1; - if (suppress_handler == 0) { - if (pthread->state != PS_RUNNING) - tid = _thr_setrunnable_unlocked(pthread); - } - } - return (tid); -} - -/* - * Send a signal to a specific thread (ala pthread_kill): - */ void -_thr_sig_send(struct pthread *pthread, int sig) +_thr_suspend_check(struct pthread *curthread) { - thr_kill(pthread->tid, sig); -} +#if 0 + sigset_t set; + long cycle; -static inline void -thr_sigframe_restore(struct pthread *curthread, struct pthread_sigframe *psf) -{ + /* Async suspend. */ THR_LOCK(curthread); - curthread->cancelflags = (psf->psf_cancelflags | - (curthread->cancelflags & - (THR_CANCEL_NEEDED | THR_CANCELLING))); - curthread->flags = psf->psf_flags; - curthread->interrupted = psf->psf_interrupted; - curthread->timeout = psf->psf_timeout; - curthread->data = psf->psf_wait_data; - curthread->wakeup_time = psf->psf_wakeup_time; - curthread->continuation = psf->psf_continuation; + if ((curthread->flags & (THR_FLAGS_NEED_SUSPEND | THR_FLAGS_SUSPENDED)) + == THR_FLAGS_NEED_SUSPEND) { + curthread->flags |= THR_FLAGS_SUSPENDED; + SIGEMPTYSET(set); + SIGADDSET(set, SIGCANCEL); + __sys_sigprocmask(SIG_UNBLOCK, &set, NULL); + while (curthread->flags & THR_FLAGS_NEED_SUSPEND) { + cycle = curthread->cycle; + THR_UNLOCK(curthread); + umtx_wait((struct umtx *)&curthread->cycle, cycle); + THR_LOCK(curthread); + } + curthread->flags &= ~THR_FLAGS_SUSPENDED; + } THR_UNLOCK(curthread); +#endif } -static inline void -thr_sigframe_save(struct pthread *curthread, struct pthread_sigframe *psf) -{ - THR_LOCK(curthread); - psf->psf_cancelflags = curthread->cancelflags; - /* This has to initialize all members of the sigframe. */ - psf->psf_flags = (curthread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_EXITING)); - psf->psf_interrupted = curthread->interrupted; - psf->psf_timeout = curthread->timeout; - psf->psf_wait_data = curthread->data; - psf->psf_wakeup_time = curthread->wakeup_time; - psf->psf_continuation = curthread->continuation; - THR_UNLOCK(curthread); -} - void _thr_signal_init(void) { struct sigaction act; __siginfohandler_t *sigfunc; + int i; - int i; /* Enter a loop to get the existing signal status: */ for (i = 1; i <= _SIG_MAXSIG; i++) { /* Get the signal handler details: */ @@ -377,16 +249,12 @@ __sys_sigaction(i, &act, NULL); } } - /* - * Install the signal handler for SIGINFO. It isn't - * really needed, but it is nice to have for debugging - * purposes. - */ - _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART; + /* Install cancel handler. */ + _thread_sigact[SIGCANCEL - 1].sa_flags = SA_SIGINFO | SA_RESTART; SIGEMPTYSET(act.sa_mask); act.sa_flags = SA_SIGINFO | SA_RESTART; act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler; - __sys_sigaction(SIGINFO, &act, NULL); + __sys_sigaction(SIGCANCEL, &act, NULL); } void @@ -411,4 +279,3 @@ } } } -
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412311451.iBVEpuAp008978>