At present the timeval timewarp functionality is tightly coupled
with the unixctl interface for external operation by test suite.

It is however desirable to make use of the timewarp functionality
directly in unit tests.

Split unixctl callback interface and the actual timewarp
functionality into separate functions.

This will be used in a patch that implements unit tests for the
cooperative multitasking module.

Signed-off-by: Frode Nordahl <frode.nord...@canonical.com>
---
 lib/timeval.c | 56 ++++++++++++++++++++++++++++++++++++++++-----------
 lib/timeval.h |  4 ++++
 2 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/lib/timeval.c b/lib/timeval.c
index 193c7bab1..4d4951c42 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -533,6 +533,10 @@ nsec_to_timespec(long long int nsec, struct timespec *ts)
     ts->tv_nsec = nsec;
 }
 
+#define MONOTONIC_CLOCK_HAS_WARP_CONN(c) \
+    ( (struct clock *) c)->large_warp.conn && \
+    (uintptr_t) ( (struct clock *) c)->large_warp.conn != UINTPTR_MAX
+
 static void
 timewarp_work(void)
 {
@@ -540,6 +544,8 @@ timewarp_work(void)
     struct timespec warp;
 
     ovs_mutex_lock(&c->mutex);
+    /* note that we do not use MONOTONIC_CLOCK_HAS_WARP_CONN here as we want
+     * to perform work in case of an internal caller has requested warp. */
     if (!c->large_warp.conn) {
         ovs_mutex_unlock(&c->mutex);
         return;
@@ -560,7 +566,9 @@ timewarp_work(void)
     }
 
     if (!c->large_warp.total_warp) {
-        unixctl_command_reply(c->large_warp.conn, "warped");
+        if (MONOTONIC_CLOCK_HAS_WARP_CONN(c)) {
+            unixctl_command_reply(c->large_warp.conn, "warped");
+        }
         c->large_warp.conn = NULL;
     }
 
@@ -763,17 +771,22 @@ get_cpu_usage(void)
 
 /* "time/stop" stops the monotonic time returned by e.g. time_msec() from
  * advancing, except due to later calls to "time/warp". */
-static void
-timeval_stop_cb(struct unixctl_conn *conn,
-                 int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
-                 void *aux OVS_UNUSED)
+void
+timeval_stop(void)
 {
     ovs_mutex_lock(&monotonic_clock.mutex);
     atomic_store_relaxed(&monotonic_clock.slow_path, true);
     monotonic_clock.stopped = true;
     xclock_gettime(monotonic_clock.id, &monotonic_clock.cache);
     ovs_mutex_unlock(&monotonic_clock.mutex);
+}
 
+static void
+timeval_stop_cb(struct unixctl_conn *conn,
+                 int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
+                 void *aux OVS_UNUSED)
+{
+    timeval_stop();
     unixctl_command_reply(conn, NULL);
 }
 
@@ -787,6 +800,25 @@ timeval_stop_cb(struct unixctl_conn *conn,
  * time to run after the clock has been advanced by MSECS.
  *
  * Does not affect wall clock readings. */
+void
+timeval_warp(long long int total_warp, long long int msecs)
+{
+    ovs_mutex_lock(&monotonic_clock.mutex);
+    if (!MONOTONIC_CLOCK_HAS_WARP_CONN(&monotonic_clock)) {
+        /* we do not have a unixctl connection for internal callers, but the
+         * pointer needs to be set for timewarp_work() to know when to
+         * perform work. */
+        monotonic_clock.large_warp.conn = (struct unixctl_conn *) UINTPTR_MAX;
+    }
+    atomic_store_relaxed(&monotonic_clock.slow_path, true);
+    monotonic_clock.large_warp.total_warp = total_warp;
+    monotonic_clock.large_warp.warp = msecs;
+    monotonic_clock.large_warp.main_thread_id = ovsthread_id_self();
+    ovs_mutex_unlock(&monotonic_clock.mutex);
+
+    timewarp_work();
+}
+
 static void
 timeval_warp_cb(struct unixctl_conn *conn,
                 int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
@@ -799,25 +831,25 @@ timeval_warp_cb(struct unixctl_conn *conn,
     }
 
     ovs_mutex_lock(&monotonic_clock.mutex);
-    if (monotonic_clock.large_warp.conn) {
+    if (MONOTONIC_CLOCK_HAS_WARP_CONN(&monotonic_clock)) {
         ovs_mutex_unlock(&monotonic_clock.mutex);
         unixctl_command_reply_error(conn, "A previous warp in progress");
         return;
     }
-    atomic_store_relaxed(&monotonic_clock.slow_path, true);
     monotonic_clock.large_warp.conn = conn;
-    monotonic_clock.large_warp.total_warp = total_warp;
-    monotonic_clock.large_warp.warp = msecs;
-    monotonic_clock.large_warp.main_thread_id = ovsthread_id_self();
     ovs_mutex_unlock(&monotonic_clock.mutex);
 
-    timewarp_work();
+    timeval_warp(total_warp, msecs);
 }
 
+void
+timeval_timewarp_enable(void) {
+    timewarp_enabled = true;
+}
 void
 timeval_dummy_register(void)
 {
-    timewarp_enabled = true;
+    timeval_timewarp_enable();
     unixctl_command_register("time/stop", "", 0, 0, timeval_stop_cb, NULL);
     unixctl_command_register("time/warp", "[large_msecs] msecs", 1, 2,
                              timeval_warp_cb, NULL);
diff --git a/lib/timeval.h b/lib/timeval.h
index 502f703d4..ea7977e0c 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -81,6 +81,10 @@ long long int time_boot_msec(void);
 
 void timewarp_run(void);
 
+void timeval_timewarp_enable(void);
+void timeval_stop(void);
+void timeval_warp(long long int, long long int);
+
 #ifdef  __cplusplus
 }
 #endif
-- 
2.34.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to