[ovs-dev] [PATCH V4 1/2] ofproto-dpif-upcall: Allow main thread to pause all revalidators.

Alex Wang ee07b291 at gmail.com
Sun Aug 30 01:44:44 UTC 2015


This commit adds logic using ovs barrier to allow main thread pause
all revalidators.  This new feature will be used in a later patch.

Signed-off-by: Alex Wang <ee07b291 at gmail.com>
---
V3->V4:
- sync the pause_latch state among all revalidators~ thx Joe for point
  out~!

V3:
- new patch.
---
 ofproto/ofproto-dpif-upcall.c | 53 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 419fd1a..962d980 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -110,7 +110,11 @@ struct udpif {
     /* Revalidation. */
     struct seq *reval_seq;             /* Incremented to force revalidation. */
     bool reval_exit;                   /* Set by leader on 'exit_latch. */
+    bool pause;                        /* Set by leader on 'pause_latch. */
     struct ovs_barrier reval_barrier;  /* Barrier used by revalidators. */
+    struct latch pause_latch;          /* Set to force revalidators pause. */
+    struct ovs_barrier pause_barrier;  /* Barrier used to pause all */
+                                       /* revalidators by main thread. */
     struct dpif_flow_dump *dump;       /* DPIF flow dump state. */
     long long int dump_duration;       /* Duration of the last flow dump. */
     struct seq *dump_seq;              /* Increments each dump iteration. */
@@ -267,10 +271,13 @@ static void handle_upcalls(struct udpif *, struct upcall *, size_t n_upcalls);
 static void udpif_stop_threads(struct udpif *);
 static void udpif_start_threads(struct udpif *, size_t n_handlers,
                                 size_t n_revalidators);
+static void udpif_pause_revalidators(struct udpif *);
+static void udpif_resume_revalidators(struct udpif *);
 static void *udpif_upcall_handler(void *);
 static void *udpif_revalidator(void *);
 static unsigned long udpif_get_n_flows(struct udpif *);
 static void revalidate(struct revalidator *);
+static void revalidator_pause(struct revalidator *);
 static void revalidator_sweep(struct revalidator *);
 static void revalidator_purge(struct revalidator *);
 static void upcall_unixctl_show(struct unixctl_conn *conn, int argc,
@@ -356,6 +363,7 @@ udpif_create(struct dpif_backer *backer, struct dpif *dpif)
     udpif->reval_seq = seq_create();
     udpif->dump_seq = seq_create();
     latch_init(&udpif->exit_latch);
+    latch_init(&udpif->pause_latch);
     list_push_back(&all_udpifs, &udpif->list_node);
     atomic_init(&udpif->enable_ufid, false);
     atomic_init(&udpif->n_flows, 0);
@@ -401,6 +409,7 @@ udpif_destroy(struct udpif *udpif)
 
     list_remove(&udpif->list_node);
     latch_destroy(&udpif->exit_latch);
+    latch_destroy(&udpif->pause_latch);
     seq_destroy(udpif->reval_seq);
     seq_destroy(udpif->dump_seq);
     ovs_mutex_destroy(&udpif->n_flows_mutex);
@@ -440,6 +449,7 @@ udpif_stop_threads(struct udpif *udpif)
         latch_poll(&udpif->exit_latch);
 
         ovs_barrier_destroy(&udpif->reval_barrier);
+        ovs_barrier_destroy(&udpif->pause_barrier);
 
         free(udpif->revalidators);
         udpif->revalidators = NULL;
@@ -479,7 +489,9 @@ udpif_start_threads(struct udpif *udpif, size_t n_handlers,
         dpif_enable_upcall(udpif->dpif);
 
         ovs_barrier_init(&udpif->reval_barrier, udpif->n_revalidators);
+        ovs_barrier_init(&udpif->pause_barrier, udpif->n_revalidators + 1);
         udpif->reval_exit = false;
+        udpif->pause = false;
         udpif->revalidators = xzalloc(udpif->n_revalidators
                                       * sizeof *udpif->revalidators);
         for (i = 0; i < udpif->n_revalidators; i++) {
@@ -492,6 +504,25 @@ udpif_start_threads(struct udpif *udpif, size_t n_handlers,
     }
 }
 
+/* Pauses all revalidators.  Should only be called by the main thread.
+ * When function returns, all revalidators are paused and will proceed
+ * only after udpif_resume_revalidators() is called. */
+static void
+udpif_pause_revalidators(struct udpif *udpif)
+{
+    latch_set(&udpif->pause_latch);
+    ovs_barrier_block(&udpif->pause_barrier);
+}
+
+/* Resumes the pausing of revalidators.  Should only be called by the
+ * main thread. */
+static void
+udpif_resume_revalidators(struct udpif *udpif)
+{
+    latch_poll(&udpif->pause_latch);
+    ovs_barrier_block(&udpif->pause_barrier);
+}
+
 /* Tells 'udpif' how many threads it should use to handle upcalls.
  * 'n_handlers' and 'n_revalidators' can never be zero.  'udpif''s
  * datapath handle must have packet reception enabled before starting
@@ -774,6 +805,12 @@ udpif_revalidator(void *arg)
             udpif->max_n_flows = MAX(n_flows, udpif->max_n_flows);
             udpif->avg_n_flows = (udpif->avg_n_flows + n_flows) / 2;
 
+            /* Only the leader checks the pause latch to prevent a race where
+             * some threads think it's false and proceed to block on
+             * reval_barrier and others think it's true and block indefinitely
+             * on the pause_barrier */
+            udpif->pause = latch_is_set(&udpif->pause_latch);
+
             /* Only the leader checks the exit latch to prevent a race where
              * some threads think it's true and exit and others think it's
              * false and block indefinitely on the reval_barrier */
@@ -790,6 +827,10 @@ udpif_revalidator(void *arg)
 
         /* Wait for the leader to start the flow dump. */
         ovs_barrier_block(&udpif->reval_barrier);
+        if (udpif->pause) {
+            revalidator_pause(revalidator);
+        }
+
         if (udpif->reval_exit) {
             break;
         }
@@ -832,6 +873,7 @@ udpif_revalidator(void *arg)
             poll_timer_wait_until(start_time + MIN(ofproto_max_idle, 500));
             seq_wait(udpif->reval_seq, last_reval_seq);
             latch_wait(&udpif->exit_latch);
+            latch_wait(&udpif->pause_latch);
             poll_block();
         }
     }
@@ -2108,6 +2150,17 @@ revalidate(struct revalidator *revalidator)
     ofpbuf_uninit(&odp_actions);
 }
 
+/* Pauses the 'revalidator', can only proceed after main thread
+ * calls udpif_resume_revalidators(). */
+static void
+revalidator_pause(struct revalidator *revalidator)
+{
+    /* The first block is for sync'ing the pause with main thread. */
+    ovs_barrier_block(&revalidator->udpif->pause_barrier);
+    /* The second block is for pausing until main thread resumes. */
+    ovs_barrier_block(&revalidator->udpif->pause_barrier);
+}
+
 static void
 revalidator_sweep__(struct revalidator *revalidator, bool purge)
 {
-- 
1.9.1




More information about the dev mailing list