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 <sys/param.h>
-#include <sys/types.h>
+#include <sys/auxv.h>
+#include <sys/elf.h>
 #include <sys/signalvar.h>
 #include <sys/syscall.h>
 #include <signal.h>
@@ -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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to