From owner-svn-src-head@freebsd.org Sun Feb 9 12:27:23 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 6C75C238159; Sun, 9 Feb 2020 12:27:23 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48FpFl2BXnz45pP; Sun, 9 Feb 2020 12:27:23 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4171A62C6; Sun, 9 Feb 2020 12:27:23 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 019CRNn2018323; Sun, 9 Feb 2020 12:27:23 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 019CRMg3018317; Sun, 9 Feb 2020 12:27:22 GMT (envelope-from kib@FreeBSD.org) Message-Id: <202002091227.019CRMg3018317@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Sun, 9 Feb 2020 12:27:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357698 - head/lib/libthr/thread X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: head/lib/libthr/thread X-SVN-Commit-Revision: 357698 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 Feb 2020 12:27:23 -0000 Author: kib Date: Sun Feb 9 12:27:22 2020 New Revision: 357698 URL: https://svnweb.freebsd.org/changeset/base/357698 Log: Use sigfastblock(2) for masking signals in libthr. Ensure proper handshake to transfer sigfastblock(2) blocking word ownership from rtld to libthr. Unfortunately sigfastblock(2) is not enough to stop intercepting signals in libthr, because critical sections must ensure more than just signal blocking. Tested by: pho Disscussed with: cem, emaste, jilles Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D12773 Modified: head/lib/libthr/thread/thr_create.c head/lib/libthr/thread/thr_private.h head/lib/libthr/thread/thr_rtld.c head/lib/libthr/thread/thr_sig.c Modified: head/lib/libthr/thread/thr_create.c ============================================================================== --- head/lib/libthr/thread/thr_create.c Sun Feb 9 12:22:43 2020 (r357697) +++ head/lib/libthr/thread/thr_create.c Sun Feb 9 12:27:22 2020 (r357698) @@ -257,6 +257,7 @@ thread_start(struct pthread *curthread) if (curthread->attr.suspend == THR_CREATE_SUSPENDED) set = curthread->sigmask; + _thr_signal_block_setup(curthread); /* * This is used as a serialization point to allow parent Modified: head/lib/libthr/thread/thr_private.h ============================================================================== --- head/lib/libthr/thread/thr_private.h Sun Feb 9 12:22:43 2020 (r357697) +++ head/lib/libthr/thread/thr_private.h Sun Feb 9 12:27:22 2020 (r357698) @@ -396,6 +396,9 @@ struct pthread { /* Signal blocked counter. */ int sigblock; + /* Fast sigblock var. */ + uint32_t fsigblock; + /* Queue entry for list of all threads. */ TAILQ_ENTRY(pthread) tle; /* link for all threads in process */ @@ -813,6 +816,8 @@ void _thr_cancel_leave(struct pthread *, int) __hidden void _thr_testcancel(struct pthread *) __hidden; void _thr_signal_block(struct pthread *) __hidden; void _thr_signal_unblock(struct pthread *) __hidden; +void _thr_signal_block_check_fast(void) __hidden; +void _thr_signal_block_setup(struct pthread *) __hidden; void _thr_signal_init(int) __hidden; void _thr_signal_deinit(void) __hidden; int _thr_send_sig(struct pthread *, int sig) __hidden; Modified: head/lib/libthr/thread/thr_rtld.c ============================================================================== --- head/lib/libthr/thread/thr_rtld.c Sun Feb 9 12:22:43 2020 (r357697) +++ head/lib/libthr/thread/thr_rtld.c Sun Feb 9 12:27:22 2020 (r357698) @@ -236,6 +236,8 @@ _thr_rtld_init(void) _thr_signal_block(curthread); _rtld_thread_init(&li); _thr_signal_unblock(curthread); + _thr_signal_block_check_fast(); + _thr_signal_block_setup(curthread); uc_len = __getcontextx_size(); uc = alloca(uc_len); Modified: head/lib/libthr/thread/thr_sig.c ============================================================================== --- head/lib/libthr/thread/thr_sig.c Sun Feb 9 12:22:43 2020 (r357697) +++ head/lib/libthr/thread/thr_sig.c Sun Feb 9 12:27:22 2020 (r357698) @@ -31,7 +31,8 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include -#include +#include +#include #include #include #include @@ -92,10 +93,9 @@ static const sigset_t _thr_maskset={{ 0xffffffff, 0xffffffff}}; -void -_thr_signal_block(struct pthread *curthread) +static void +thr_signal_block_slow(struct pthread *curthread) { - if (curthread->sigblock > 0) { curthread->sigblock++; return; @@ -104,11 +104,66 @@ _thr_signal_block(struct pthread *curthread) curthread->sigblock++; } -void -_thr_signal_unblock(struct pthread *curthread) +static void +thr_signal_unblock_slow(struct pthread *curthread) { if (--curthread->sigblock == 0) __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); +} + +static void +thr_signal_block_fast(struct pthread *curthread) +{ + atomic_add_32(&curthread->fsigblock, SIGFASTBLOCK_INC); +} + +static void +thr_signal_unblock_fast(struct pthread *curthread) +{ + uint32_t oldval; + + oldval = atomic_fetchadd_32(&curthread->fsigblock, -SIGFASTBLOCK_INC); + if (oldval == (SIGFASTBLOCK_PEND | SIGFASTBLOCK_INC)) + __sys_sigfastblock(SIGFASTBLOCK_UNBLOCK, NULL); +} + +static bool fast_sigblock; + +void +_thr_signal_block(struct pthread *curthread) +{ + if (fast_sigblock) + thr_signal_block_fast(curthread); + else + thr_signal_block_slow(curthread); +} + +void +_thr_signal_unblock(struct pthread *curthread) +{ + if (fast_sigblock) + thr_signal_unblock_fast(curthread); + else + thr_signal_unblock_slow(curthread); +} + +void +_thr_signal_block_check_fast(void) +{ + int bsdflags, error; + + error = elf_aux_info(AT_BSDFLAGS, &bsdflags, sizeof(bsdflags)); + if (error != 0) + return; + fast_sigblock = (bsdflags & ELF_BSDF_SIGFASTBLK) != 0; +} + +void +_thr_signal_block_setup(struct pthread *curthread) +{ + if (!fast_sigblock) + return; + __sys_sigfastblock(SIGFASTBLOCK_SETPTR, &curthread->fsigblock); } int