Date: Tue, 21 Sep 2010 06:47:05 +0000 (UTC) From: David Xu <davidxu@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r212952 - head/lib/libthr/thread Message-ID: <201009210647.o8L6l55H082194@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: davidxu Date: Tue Sep 21 06:47:04 2010 New Revision: 212952 URL: http://svn.freebsd.org/changeset/base/212952 Log: If we are at cancellation point, always work as deferred mode despite whether asynchronous mode is turned on or not, this always gives us a chance to decide whether thread should be canceled or not in cancellation points. Modified: head/lib/libthr/thread/thr_sig.c Modified: head/lib/libthr/thread/thr_sig.c ============================================================================== --- head/lib/libthr/thread/thr_sig.c Tue Sep 21 05:58:45 2010 (r212951) +++ head/lib/libthr/thread/thr_sig.c Tue Sep 21 06:47:04 2010 (r212952) @@ -270,46 +270,44 @@ static void check_cancel(struct pthread *curthread, ucontext_t *ucp) { - if (__predict_true(!curthread->cancel_pending || !curthread->cancel_enable || - curthread->no_cancel)) + if (__predict_true(!curthread->cancel_pending || + !curthread->cancel_enable || curthread->no_cancel)) return; - if (curthread->cancel_async) { + /* + * Otherwise, we are in defer mode, and we are at + * cancel point, tell kernel to not block the current + * thread on next cancelable system call. + * + * There are three cases we should call thr_wake() to + * turn on TDP_WAKEUP or send SIGCANCEL in kernel: + * 1) we are going to call a cancelable system call, + * non-zero cancel_point means we are already in + * cancelable state, next system call is cancelable. + * 2) because _thr_ast() may be called by + * THR_CRITICAL_LEAVE() which is used by rtld rwlock + * and any libthr internal locks, when rtld rwlock + * is used, it is mostly caused my an unresolved PLT. + * those routines may clear the TDP_WAKEUP flag by + * invoking some system calls, in those cases, we + * also should reenable the flag. + * 3) thread is in sigsuspend(), and the syscall insists + * on getting a signal before it agrees to return. + */ + if (curthread->cancel_point) { + if (curthread->in_sigsuspend && ucp) { + SIGADDSET(ucp->uc_sigmask, SIGCANCEL); + curthread->unblock_sigcancel = 1; + _thr_send_sig(curthread, SIGCANCEL); + } else + thr_wake(curthread->tid); + } else if (curthread->cancel_async) { /* - * asynchronous cancellation mode, act upon + * asynchronous cancellation mode, act upon * immediately. - */ + */ _pthread_exit_mask(PTHREAD_CANCELED, ucp? &ucp->uc_sigmask : NULL); - } else { - /* - * Otherwise, we are in defer mode, and we are at - * cancel point, tell kernel to not block the current - * thread on next cancelable system call. - * - * There are three cases we should call thr_wake() to - * turn on TDP_WAKEUP or send SIGCANCEL in kernel: - * 1) we are going to call a cancelable system call, - * non-zero cancel_point means we are already in - * cancelable state, next system call is cancelable. - * 2) because _thr_ast() may be called by - * THR_CRITICAL_LEAVE() which is used by rtld rwlock - * and any libthr internal locks, when rtld rwlock - * is used, it is mostly caused my an unresolved PLT. - * those routines may clear the TDP_WAKEUP flag by - * invoking some system calls, in those cases, we - * also should reenable the flag. - * 3) thread is in sigsuspend(), and the syscall insists - * on getting a signal before it agrees to return. - */ - if (curthread->cancel_point) { - if (curthread->in_sigsuspend && ucp) { - SIGADDSET(ucp->uc_sigmask, SIGCANCEL); - curthread->unblock_sigcancel = 1; - _thr_send_sig(curthread, SIGCANCEL); - } else - thr_wake(curthread->tid); - } } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009210647.o8L6l55H082194>