static struct guarded_list flushed_cbsets;
static struct seq *flushed_cbsets_seq;
-static void ovsrcu_init(void);
+static void ovsrcu_init_module(void);
static void ovsrcu_flush_cbset(struct ovsrcu_perthread *);
static void ovsrcu_unregister__(struct ovsrcu_perthread *);
static bool ovsrcu_call_postponed(void);
static void *ovsrcu_postpone_thread(void *arg OVS_UNUSED);
-static void ovsrcu_synchronize(void);
static struct ovsrcu_perthread *
ovsrcu_perthread_get(void)
{
struct ovsrcu_perthread *perthread;
- ovsrcu_init();
+ ovsrcu_init_module();
perthread = pthread_getspecific(perthread_key);
if (!perthread) {
{
struct ovsrcu_perthread *perthread;
- ovsrcu_init();
+ ovsrcu_init_module();
perthread = pthread_getspecific(perthread_key);
if (perthread) {
pthread_setspecific(perthread_key, NULL);
}
/* Indicates a momentary quiescent state. See "Details" near the top of
- * ovs-rcu.h. */
+ * ovs-rcu.h.
+ *
+ * Provides a full memory barrier via seq_change().
+ */
void
ovsrcu_quiesce(void)
{
- ovsrcu_init();
- ovsrcu_perthread_get()->seqno = seq_read(global_seqno);
+ struct ovsrcu_perthread *perthread;
+
+ perthread = ovsrcu_perthread_get();
+ perthread->seqno = seq_read(global_seqno);
+ if (perthread->cbset) {
+ ovsrcu_flush_cbset(perthread);
+ }
seq_change(global_seqno);
ovsrcu_quiesced();
bool
ovsrcu_is_quiescent(void)
{
- ovsrcu_init();
+ ovsrcu_init_module();
return pthread_getspecific(perthread_key) == NULL;
}
-static void
+void
ovsrcu_synchronize(void)
{
unsigned int warning_threshold = 1000;
}
static void
-ovsrcu_init(void)
+ovsrcu_init_module(void)
{
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
if (ovsthread_once_start(&once)) {