From 3308c696220bbfff36bf29b3e1b168449d57b3d7 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 25 Apr 2014 18:25:06 -0700 Subject: [PATCH] timeval: Preserve quiescence across time_poll(). Otherwise ovsrcu_synchronize() busy-waits in its loop because its poll_block() un-quiesces, causing the global_seqno to increase, which is what it waits for. Reported-by: Alex Wang Signed-off-by: Ben Pfaff Acked-by: Alex Wang --- lib/ovs-rcu.c | 7 +++++++ lib/ovs-rcu.h | 1 + lib/timeval.c | 14 +++++++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/ovs-rcu.c b/lib/ovs-rcu.c index 269f51b53..b3c434dbb 100644 --- a/lib/ovs-rcu.c +++ b/lib/ovs-rcu.c @@ -134,6 +134,13 @@ ovsrcu_quiesce(void) ovsrcu_quiesced(); } +bool +ovsrcu_is_quiescent(void) +{ + ovsrcu_init(); + return pthread_getspecific(perthread_key) == NULL; +} + static void ovsrcu_synchronize(void) { diff --git a/lib/ovs-rcu.h b/lib/ovs-rcu.h index 710870a8b..4b451b23b 100644 --- a/lib/ovs-rcu.h +++ b/lib/ovs-rcu.h @@ -178,5 +178,6 @@ void ovsrcu_postpone__(void (*function)(void *aux), void *aux); void ovsrcu_quiesce_start(void); void ovsrcu_quiesce_end(void); void ovsrcu_quiesce(void); +bool ovsrcu_is_quiescent(void); #endif /* ovs-rcu.h */ diff --git a/lib/timeval.c b/lib/timeval.c index ebbdb9843..d2a4380ff 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -263,6 +263,7 @@ time_poll(struct pollfd *pollfds, int n_pollfds, HANDLE *handles OVS_UNUSED, { long long int *last_wakeup = last_wakeup_get(); long long int start; + bool quiescent; int retval = 0; time_init(); @@ -274,6 +275,7 @@ time_poll(struct pollfd *pollfds, int n_pollfds, HANDLE *handles OVS_UNUSED, start = time_msec(); timeout_when = MIN(timeout_when, deadline); + quiescent = ovsrcu_is_quiescent(); for (;;) { long long int now = time_msec(); @@ -287,10 +289,12 @@ time_poll(struct pollfd *pollfds, int n_pollfds, HANDLE *handles OVS_UNUSED, time_left = timeout_when - now; } - if (!time_left) { - ovsrcu_quiesce(); - } else { - ovsrcu_quiesce_start(); + if (!quiescent) { + if (!time_left) { + ovsrcu_quiesce(); + } else { + ovsrcu_quiesce_start(); + } } #ifndef _WIN32 @@ -313,7 +317,7 @@ time_poll(struct pollfd *pollfds, int n_pollfds, HANDLE *handles OVS_UNUSED, } #endif - if (time_left) { + if (!quiescent && time_left) { ovsrcu_quiesce_end(); } -- 2.43.0