+ return get_cpu_tracker()->cpu_usage;
+}
+\f
+/* Unixctl interface. */
+
+/* "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)
+{
+ 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);
+
+ unixctl_command_reply(conn, NULL);
+}
+
+/* "time/warp MSECS" advances the current monotonic time by the specified
+ * number of milliseconds. Unless "time/stop" has also been executed, the
+ * monotonic clock continues to tick forward at the normal rate afterward.
+ *
+ * "time/warp LARGE_MSECS MSECS" is a variation of the above command. It
+ * advances the current monotonic time by LARGE_MSECS. This is done MSECS
+ * at a time in each run of the main thread. This gives other threads
+ * time to run after the clock has been advanced by MSECS.
+ *
+ * Does not affect wall clock readings. */
+static void
+timeval_warp_cb(struct unixctl_conn *conn,
+ int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
+{
+ long long int total_warp = argc > 2 ? atoll(argv[1]) : 0;
+ long long int msecs = argc > 2 ? atoll(argv[2]) : atoll(argv[1]);
+ if (msecs <= 0 || total_warp < 0) {
+ unixctl_command_reply_error(conn, "invalid MSECS");
+ return;
+ }
+
+ ovs_mutex_lock(&monotonic_clock.mutex);
+ if (monotonic_clock.large_warp.conn) {
+ 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();
+}
+
+void
+timeval_dummy_register(void)
+{
+ timewarp_enabled = true;
+ 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);
+}
+
+
+
+/* strftime() with an extension for high-resolution timestamps. Any '#'s in
+ * 'format' will be replaced by subseconds, e.g. use "%S.###" to obtain results
+ * like "01.123". */
+size_t
+strftime_msec(char *s, size_t max, const char *format,
+ const struct tm_msec *tm)
+{
+ size_t n;
+
+ /* Visual Studio 2013's behavior is to crash when 0 is passed as second
+ * argument to strftime. */
+ n = max ? strftime(s, max, format, &tm->tm) : 0;
+ if (n) {
+ char decimals[4];
+ char *p;
+
+ sprintf(decimals, "%03d", tm->msec);
+ for (p = strchr(s, '#'); p; p = strchr(p, '#')) {
+ char *d = decimals;
+ while (*p == '#') {
+ *p++ = *d ? *d++ : '0';
+ }
+ }
+ }
+
+ return n;
+}
+
+struct tm_msec *
+localtime_msec(long long int now, struct tm_msec *result)
+{
+ time_t now_sec = now / 1000;
+ localtime_r(&now_sec, &result->tm);
+ result->msec = now % 1000;
+ return result;
+}
+
+struct tm_msec *
+gmtime_msec(long long int now, struct tm_msec *result)
+{
+ time_t now_sec = now / 1000;
+ gmtime_r(&now_sec, &result->tm);
+ result->msec = now % 1000;
+ return result;