projects
/
userspace-rcu.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fix: join worker thread in call_rcu_data_free
[userspace-rcu.git]
/
src
/
urcu-call-rcu-impl.h
diff --git
a/src/urcu-call-rcu-impl.h
b/src/urcu-call-rcu-impl.h
index 9f85d55b403c5fa1f882947af021c6cae460d712..cb010687829959f1750242dadb6ecfa99b9cd912 100644
(file)
--- 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;
};
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.
/*
* 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 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
/*
* If the sched_getcpu() and sysconf(_SC_NPROCESSORS_CONF) calls are
@@
-766,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.
*/
* 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;
{
if (crdp == NULL || crdp == default_call_rcu_data) {
return;
@@
-795,9
+799,21
@@
void call_rcu_data_free(struct call_rcu_data *crdp)
cds_list_del(&crdp->list);
call_rcu_unlock(&call_rcu_mutex);
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);
}
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.
*/
/*
* Clean up all the per-CPU call_rcu threads.
*/
@@
-1022,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);
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)
{
}
}
void urcu_register_rculfhash_atfork(struct urcu_atfork *atfork)
{
+ if (CMM_LOAD_SHARED(registered_rculfhash_atfork))
+ return;
call_rcu_lock(&call_rcu_mutex);
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);
}
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)))
{
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);
}
}
This page took
0.025003 seconds
and
4
git commands to generate.