From: Ben Pfaff <blp@nicira.com>
Date: Sat, 26 Apr 2014 01:25:06 +0000 (-0700)
Subject: timeval: Preserve quiescence across time_poll().
X-Git-Tag: sliver-openvswitch-2.2.90-1~3^2~65
X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=3308c696220bbfff36bf29b3e1b168449d57b3d7;p=sliver-openvswitch.git

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 <alexw@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Alex Wang <alexw@nicira.com>
---

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();
         }