X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Furcu-call-rcu-impl.h;h=cb010687829959f1750242dadb6ecfa99b9cd912;hb=1cf55ba47342156cdf25335264b9774a16e0bb2d;hp=e9366b42355b8b0db313cca083b121017192852b;hpb=5cfe81b7ddff9543d451746de9965cac58c67182;p=urcu.git diff --git a/src/urcu-call-rcu-impl.h b/src/urcu-call-rcu-impl.h index e9366b4..cb01068 100644 --- a/src/urcu-call-rcu-impl.h +++ b/src/urcu-call-rcu-impl.h @@ -81,6 +81,10 @@ struct call_rcu_completion_work { struct call_rcu_completion *completion; }; +enum crdf_flags { + CRDF_FLAG_JOIN_THREAD = (1 << 0), +}; + /* * List of all call_rcu_data structures to keep valgrind happy. * Protected by call_rcu_mutex. @@ -102,7 +106,6 @@ static pthread_mutex_t call_rcu_mutex = PTHREAD_MUTEX_INITIALIZER; static struct call_rcu_data *default_call_rcu_data; static struct urcu_atfork *registered_rculfhash_atfork; -static unsigned long registered_rculfhash_atfork_refcount; /* * If the sched_getcpu() and sysconf(_SC_NPROCESSORS_CONF) calls are @@ -434,6 +437,7 @@ static void call_rcu_data_init(struct call_rcu_data **crdpp, { struct call_rcu_data *crdp; int ret; + sigset_t newmask, oldmask; crdp = malloc(sizeof(*crdp)); if (crdp == NULL) @@ -448,9 +452,18 @@ static void call_rcu_data_init(struct call_rcu_data **crdpp, crdp->gp_count = 0; cmm_smp_mb(); /* Structure initialized before pointer is planted. */ *crdpp = crdp; + + ret = sigfillset(&newmask); + urcu_posix_assert(!ret); + ret = pthread_sigmask(SIG_BLOCK, &newmask, &oldmask); + urcu_posix_assert(!ret); + ret = pthread_create(&crdp->tid, NULL, call_rcu_thread, crdp); if (ret) urcu_die(ret); + + ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL); + urcu_posix_assert(!ret); } /* @@ -756,7 +769,8 @@ void call_rcu(struct rcu_head *head, * a list corruption bug in the 0.7.x series. The equivalent fix * appeared in 0.6.8 for the stable-0.6 branch. */ -void call_rcu_data_free(struct call_rcu_data *crdp) +static +void _call_rcu_data_free(struct call_rcu_data *crdp, unsigned int flags) { if (crdp == NULL || crdp == default_call_rcu_data) { return; @@ -785,9 +799,21 @@ void call_rcu_data_free(struct call_rcu_data *crdp) cds_list_del(&crdp->list); call_rcu_unlock(&call_rcu_mutex); + if (flags & CRDF_FLAG_JOIN_THREAD) { + int ret; + + ret = pthread_join(get_call_rcu_thread(crdp), NULL); + if (ret) + urcu_die(ret); + } free(crdp); } +void call_rcu_data_free(struct call_rcu_data *crdp) +{ + _call_rcu_data_free(crdp, CRDF_FLAG_JOIN_THREAD); +} + /* * Clean up all the per-CPU call_rcu threads. */ @@ -1012,26 +1038,30 @@ void call_rcu_after_fork_child(void) if (crdp == default_call_rcu_data) continue; uatomic_set(&crdp->flags, URCU_CALL_RCU_STOPPED); - call_rcu_data_free(crdp); + /* + * Do not join the thread because it does not exist in + * the child. + */ + _call_rcu_data_free(crdp, 0); } } void urcu_register_rculfhash_atfork(struct urcu_atfork *atfork) { + if (CMM_LOAD_SHARED(registered_rculfhash_atfork)) + return; call_rcu_lock(&call_rcu_mutex); - if (registered_rculfhash_atfork_refcount++) - goto end; - registered_rculfhash_atfork = atfork; -end: + if (!registered_rculfhash_atfork) + registered_rculfhash_atfork = atfork; call_rcu_unlock(&call_rcu_mutex); } +/* + * This unregistration function is deprecated, meant only for internal + * use by rculfhash. + */ +__attribute__((noreturn)) void urcu_unregister_rculfhash_atfork(struct urcu_atfork *atfork __attribute__((unused))) { - call_rcu_lock(&call_rcu_mutex); - if (--registered_rculfhash_atfork_refcount) - goto end; - registered_rculfhash_atfork = NULL; -end: - call_rcu_unlock(&call_rcu_mutex); + urcu_die(EPERM); }