+ return t;
+}
+
+static struct rusage *
+get_recent_rusage(void)
+{
+ return &get_cpu_tracker()->recent_rusage;
+}
+
+static int
+getrusage_thread(struct rusage *rusage OVS_UNUSED)
+{
+#ifdef RUSAGE_THREAD
+ return getrusage(RUSAGE_THREAD, rusage);
+#else
+ errno = EINVAL;
+ return -1;
+#endif
+}
+
+static void
+refresh_rusage(void)
+{
+ struct cpu_tracker *t = get_cpu_tracker();
+ struct rusage *recent_rusage = &t->recent_rusage;
+
+ if (!getrusage_thread(recent_rusage)) {
+ long long int now = time_msec();
+ if (now >= t->newer.when + 3 * 1000) {
+ t->older = t->newer;
+ t->newer.when = now;
+ t->newer.cpu = (timeval_to_msec(&recent_rusage->ru_utime) +
+ timeval_to_msec(&recent_rusage->ru_stime));
+
+ if (t->older.when != LLONG_MIN && t->newer.cpu > t->older.cpu) {
+ unsigned int dividend = t->newer.cpu - t->older.cpu;
+ unsigned int divisor = (t->newer.when - t->older.when) / 100;
+ t->cpu_usage = divisor > 0 ? dividend / divisor : -1;
+ } else {
+ t->cpu_usage = -1;
+ }
+ }
+ }
+}
+
+/* Returns an estimate of this process's CPU usage, as a percentage, over the
+ * past few seconds of wall-clock time. Returns -1 if no estimate is available
+ * (which will happen if the process has not been running long enough to have
+ * an estimate, and can happen for other reasons as well). */
+int
+get_cpu_usage(void)
+{
+ 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(&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.
+ *
+ * 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)
+{
+ struct timespec ts;
+ int msecs;
+
+ msecs = atoi(argv[1]);
+ if (msecs <= 0) {
+ unixctl_command_reply_error(conn, "invalid MSECS");
+ return;
+ }
+
+ ts.tv_sec = msecs / 1000;
+ ts.tv_nsec = (msecs % 1000) * 1000 * 1000;
+
+ ovs_mutex_lock(&monotonic_clock.mutex);
+ atomic_store(&monotonic_clock.slow_path, true);
+ timespec_add(&monotonic_clock.warp, &monotonic_clock.warp, &ts);
+ ovs_mutex_unlock(&monotonic_clock.mutex);
+ seq_change(timewarp_seq);
+ /* give threads (eg. monitor) some chances to run */
+#ifndef _WIN32
+ poll(NULL, 0, 10);
+#else
+ Sleep(10);
+#endif
+ unixctl_command_reply(conn, "warped");
+}
+
+void
+timeval_dummy_register(void)
+{
+ timewarp_enabled = true;
+ unixctl_command_register("time/stop", "", 0, 0, timeval_stop_cb, NULL);
+ unixctl_command_register("time/warp", "MSECS", 1, 1,
+ 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;
+
+ n = strftime(s, max, format, &tm->tm);
+ 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;