+static void
+msec_to_timespec(long long int ms, struct timespec *ts)
+{
+ ts->tv_sec = ms / 1000;
+ ts->tv_nsec = (ms % 1000) * 1000 * 1000;
+}
+
+static void
+timewarp_work(void)
+{
+ struct clock *c = &monotonic_clock;
+ struct timespec warp;
+
+ ovs_mutex_lock(&c->mutex);
+ if (!c->large_warp.conn) {
+ ovs_mutex_unlock(&c->mutex);
+ return;
+ }
+
+ if (c->large_warp.total_warp >= c->large_warp.warp) {
+ msec_to_timespec(c->large_warp.warp, &warp);
+ timespec_add(&c->warp, &c->warp, &warp);
+ c->large_warp.total_warp -= c->large_warp.warp;
+ } else if (c->large_warp.total_warp) {
+ msec_to_timespec(c->large_warp.total_warp, &warp);
+ timespec_add(&c->warp, &c->warp, &warp);
+ c->large_warp.total_warp = 0;
+ } else {
+ /* c->large_warp.total_warp is 0. */
+ msec_to_timespec(c->large_warp.warp, &warp);
+ timespec_add(&c->warp, &c->warp, &warp);
+ }
+
+ if (!c->large_warp.total_warp) {
+ unixctl_command_reply(c->large_warp.conn, "warped");
+ c->large_warp.conn = NULL;
+ }
+
+ ovs_mutex_unlock(&c->mutex);
+ seq_change(timewarp_seq);
+
+ /* give threads (eg. monitor) some chances to run */
+#ifndef _WIN32
+ poll(NULL, 0, 10);
+#else
+ Sleep(10);
+#endif
+}
+
+/* Perform work needed for "timewarp_seq"'s producer and consumers. */