about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2022-11-15 19:33:38 +0000
committerEric Wong <e@80x24.org>2022-11-16 09:25:11 +0000
commitf2521869d0a411a8d3a79c3961895a40eafa2b06 (patch)
tree641f14d492ca4f87aa30292b21f6d4adf878608b
parentdfd859ad96e8d6da4943c770f307d56558588fe7 (diff)
downloadmwrap-f2521869d0a411a8d3a79c3961895a40eafa2b06.tar.gz
rculfhash, call_rcu, and urcu-bp will spawn background
threads.  Ensure we spawn all of these threads while signals
are blocked since the underlying codebase may block signals
and rely on signalfd.
-rw-r--r--Mwrap.xs127
1 files changed, 74 insertions, 53 deletions
diff --git a/Mwrap.xs b/Mwrap.xs
index e87fe30..f441ca8 100644
--- a/Mwrap.xs
+++ b/Mwrap.xs
@@ -21,6 +21,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <pthread.h>
+#include <signal.h>
 #include <urcu-bp.h>
 #include <urcu/rculfhash.h>
 #include <urcu/rculist.h>
@@ -101,60 +102,9 @@ static pthread_mutex_t *mutex_assign(void)
         return &mutexes[uatomic_add_return(&mutex_i, 1) & MUTEX_MASK].mtx;
 }
 
-static struct cds_lfht *
-lfht_new(void)
+static struct cds_lfht *lfht_new(void)
 {
-        return cds_lfht_new(16384, 1, 0, CDS_LFHT_AUTO_RESIZE, 0);
-}
-
-__attribute__((constructor)) static void resolve_malloc(void)
-{
-        int err;
-
-        ++locating;
-
-        /*
-         * PTHREAD_MUTEX_INITIALIZER on FreeBSD means lazy initialization,
-         * which happens at pthread_mutex_lock, and that calls calloc
-         */
-        if (!STATIC_MTX_INIT_OK) {
-                size_t i;
-
-                for (i = 0; i < MUTEX_NR; i++) {
-                        err = pthread_mutex_init(&mutexes[i].mtx, 0);
-                        if (err) {
-                                fprintf(stderr, "error: %s\n", strerror(err));
-                                _exit(1);
-                        }
-                }
-                /* initialize mutexes used by urcu-bp */
-                rcu_read_lock();
-                rcu_read_unlock();
-#ifndef __FreeBSD__
-        } else {
-                if (!real_malloc) {
-                        resolving_malloc = 1;
-                        real_malloc = dlsym(RTLD_NEXT, "malloc");
-                }
-                real_free = dlsym(RTLD_NEXT, "free");
-                if (!real_malloc || !real_free) {
-                        fprintf(stderr, "missing malloc/aligned_alloc/free\n"
-                                "\t%p %p\n", real_malloc, real_free);
-                        _exit(1);
-                }
-#endif /* !__FreeBSD__ */
-        }
-        CMM_STORE_SHARED(totals, lfht_new());
-        if (!CMM_LOAD_SHARED(totals))
-                fprintf(stderr, "failed to allocate totals table\n");
-
-        err = pthread_atfork(call_rcu_before_fork,
-                                call_rcu_after_fork_parent,
-                                call_rcu_after_fork_child);
-        if (err)
-                fprintf(stderr, "pthread_atfork failed: %s\n", strerror(err));
-        page_size = sysconf(_SC_PAGESIZE);
-        --locating;
+        return cds_lfht_new(8192, 1, 0, CDS_LFHT_AUTO_RESIZE, 0);
 }
 
 #ifdef NDEBUG
@@ -807,6 +757,77 @@ out:
         --locating;
 }
 
+__attribute__((constructor)) static void mwrap_ctor(void)
+{
+        sigset_t set, old;
+        struct alloc_hdr *h;
+        int err;
+
+        ++locating;
+
+        /* block signals */
+        err = sigfillset(&set);
+        assert(err == 0);
+        err = pthread_sigmask(SIG_SETMASK, &set, &old);
+        assert(err == 0);
+
+        page_size = sysconf(_SC_PAGESIZE);
+        /*
+         * PTHREAD_MUTEX_INITIALIZER on FreeBSD means lazy initialization,
+         * which happens at pthread_mutex_lock, and that calls calloc
+         */
+        if (!STATIC_MTX_INIT_OK) {
+                size_t i;
+
+                for (i = 0; i < MUTEX_NR; i++) {
+                        err = pthread_mutex_init(&mutexes[i].mtx, 0);
+                        if (err) {
+                                fprintf(stderr, "error: %s\n", strerror(err));
+                                _exit(1);
+                        }
+                }
+                /* initialize mutexes used by urcu-bp */
+                rcu_read_lock();
+                rcu_read_unlock();
+#ifndef __FreeBSD__
+        } else {
+                if (!real_malloc) {
+                        resolving_malloc = 1;
+                        real_malloc = dlsym(RTLD_NEXT, "malloc");
+                }
+                real_free = dlsym(RTLD_NEXT, "free");
+                if (!real_malloc || !real_free) {
+                        fprintf(stderr, "missing malloc/aligned_alloc/free\n"
+                                "\t%p %p\n", real_malloc, real_free);
+                        _exit(1);
+                }
+#endif /* !__FreeBSD__ */
+        }
+        CMM_STORE_SHARED(totals, lfht_new());
+        if (!CMM_LOAD_SHARED(totals)) {
+                fprintf(stderr, "failed to allocate `totals' table\n");
+                abort();
+        }
+        h = real_malloc(sizeof(struct alloc_hdr));
+        if (h) { /* force call_rcu to start background thread */
+                h->real = h;
+                call_rcu(&h->as.dead, free_hdr_rcu);
+        } else
+                fprintf(stderr, "malloc failed: %s\n", strerror(errno));
+
+        /* start more background threads before unblocking signals */
+        cds_lfht_resize(CMM_LOAD_SHARED(totals), 16384);
+        err = pthread_sigmask(SIG_SETMASK, &old, NULL);
+        assert(err == 0);
+        err = pthread_atfork(call_rcu_before_fork,
+                                call_rcu_after_fork_parent,
+                                call_rcu_after_fork_child);
+        if (err)
+                fprintf(stderr, "pthread_atfork failed: %s\n", strerror(err));
+
+        --locating;
+}
+
 MODULE = Devel::Mwrap        PACKAGE = Devel::Mwrap        PREFIX = mwrap_
 
 BOOT: