Coverage Report

Created: 2026-05-30 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/timeval.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at:
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include <config.h>
18
#include "timeval.h"
19
#include <errno.h>
20
#include <poll.h>
21
#include <pthread.h>
22
#include <signal.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <sys/time.h>
26
#include <sys/resource.h>
27
#include <unistd.h>
28
#include "coverage.h"
29
#include "dummy.h"
30
#include "openvswitch/dynamic-string.h"
31
#include "fatal-signal.h"
32
#include "hash.h"
33
#include "openvswitch/hmap.h"
34
#include "ovs-rcu.h"
35
#include "ovs-thread.h"
36
#include "signals.h"
37
#include "seq.h"
38
#include "unixctl.h"
39
#include "util.h"
40
#include "openvswitch/vlog.h"
41
42
VLOG_DEFINE_THIS_MODULE(timeval);
43
44
COVERAGE_DEFINE(long_poll_interval);
45
46
#if !defined(HAVE_CLOCK_GETTIME)
47
typedef unsigned int clockid_t;
48
static int clock_gettime(clock_t id, struct timespec *ts);
49
50
#ifndef CLOCK_MONOTONIC
51
#define CLOCK_MONOTONIC 1
52
#endif
53
54
#ifndef CLOCK_REALTIME
55
#define CLOCK_REALTIME 2
56
#endif
57
#endif /* !defined(HAVE_CLOCK_GETTIME) */
58
59
/* Structure set by unixctl time/warp command. */
60
struct large_warp {
61
    struct unixctl_conn *conn; /* Connection waiting for warp response. */
62
    long long int total_warp; /* Total offset to be added to monotonic time. */
63
    long long int warp;      /* 'total_warp' offset done in steps of 'warp'. */
64
    unsigned int main_thread_id; /* Identification for the main thread. */
65
};
66
67
struct clock {
68
    clockid_t id;               /* CLOCK_MONOTONIC or CLOCK_REALTIME. */
69
70
    /* Features for use by unit tests.  Protected by 'mutex'. */
71
    atomic_bool slow_path;             /* True if warped or stopped. */
72
    bool stopped OVS_GUARDED;          /* Disable real-time updates if true. */
73
    struct ovs_mutex mutex;
74
    struct timespec warp OVS_GUARDED;  /* Offset added for unit tests. */
75
    struct timespec cache OVS_GUARDED; /* Last time read from kernel. */
76
    struct large_warp large_warp OVS_GUARDED; /* Connection information waiting
77
                                                 for warp response. */
78
};
79
80
/* Our clocks. */
81
static struct clock monotonic_clock; /* CLOCK_MONOTONIC, if available. */
82
static struct clock wall_clock;      /* CLOCK_REALTIME. */
83
84
/* The monotonic time at which the time module was initialized. */
85
static long long int boot_time;
86
87
/* True only when timeval_dummy_register() is called. */
88
static bool timewarp_enabled;
89
/* Reference to the seq struct.  Threads other than main thread can
90
 * wait on timewarp_seq and be waken up when time is warped. */
91
static struct seq *timewarp_seq;
92
/* Last value of 'timewarp_seq'. */
93
DEFINE_STATIC_PER_THREAD_DATA(uint64_t, last_seq, 0);
94
95
/* Monotonic time in milliseconds at which to die with SIGALRM (if not
96
 * LLONG_MAX). */
97
static long long int deadline = LLONG_MAX;
98
99
/* Monotonic time, in milliseconds, at which the last call to time_poll() woke
100
 * up. */
101
DEFINE_STATIC_PER_THREAD_DATA(long long int, last_wakeup, 0);
102
103
static void log_poll_interval(long long int last_wakeup);
104
static struct rusage *get_recent_rusage(void);
105
static int getrusage_thread(struct rusage *);
106
static void refresh_rusage(void);
107
static void timespec_add(struct timespec *sum,
108
                         const struct timespec *a, const struct timespec *b);
109
110
static void
111
init_clock(struct clock *c, clockid_t id)
112
    OVS_NO_THREAD_SAFETY_ANALYSIS
113
0
{
114
0
    memset(c, 0, sizeof *c);
115
0
    c->id = id;
116
0
    ovs_mutex_init(&c->mutex);
117
0
    atomic_init(&c->slow_path, false);
118
0
    xclock_gettime(c->id, &c->cache);
119
0
}
120
121
static void
122
do_init_time(void)
123
    OVS_NO_THREAD_SAFETY_ANALYSIS
124
0
{
125
0
    struct timespec ts;
126
127
0
    coverage_init();
128
129
0
    timewarp_seq = seq_create();
130
0
    init_clock(&monotonic_clock, (!clock_gettime(CLOCK_MONOTONIC, &ts)
131
0
                                  ? CLOCK_MONOTONIC
132
0
                                  : CLOCK_REALTIME));
133
0
    init_clock(&wall_clock, CLOCK_REALTIME);
134
0
    boot_time = timespec_to_msec(&monotonic_clock.cache);
135
0
}
136
137
/* Initializes the timetracking module, if not already initialized. */
138
static void
139
time_init(void)
140
0
{
141
0
    static pthread_once_t once = PTHREAD_ONCE_INIT;
142
0
    pthread_once(&once, do_init_time);
143
0
}
144
145
static void
146
time_timespec__(struct clock *c, struct timespec *ts)
147
0
{
148
0
    bool slow_path;
149
150
0
    time_init();
151
152
0
    atomic_read_relaxed(&c->slow_path, &slow_path);
153
0
    if (!slow_path) {
154
0
        xclock_gettime(c->id, ts);
155
0
    } else {
156
0
        struct timespec warp;
157
0
        struct timespec cache;
158
0
        bool stopped;
159
160
0
        ovs_mutex_lock(&c->mutex);
161
0
        stopped = c->stopped;
162
0
        warp = c->warp;
163
0
        cache = c->cache;
164
0
        ovs_mutex_unlock(&c->mutex);
165
166
0
        if (!stopped) {
167
0
            xclock_gettime(c->id, &cache);
168
0
        }
169
0
        timespec_add(ts, &cache, &warp);
170
0
    }
171
0
}
172
173
/* Stores a monotonic timer into '*ts'. */
174
void
175
time_timespec(struct timespec *ts)
176
0
{
177
0
    time_timespec__(&monotonic_clock, ts);
178
0
}
179
180
/* Stores the current time into '*ts'. */
181
void
182
time_wall_timespec(struct timespec *ts)
183
0
{
184
0
    time_timespec__(&wall_clock, ts);
185
0
}
186
187
static time_t
188
time_sec__(struct clock *c)
189
0
{
190
0
    struct timespec ts;
191
192
0
    time_timespec__(c, &ts);
193
0
    return ts.tv_sec;
194
0
}
195
196
/* Returns a monotonic timer, in seconds. */
197
time_t
198
time_now(void)
199
0
{
200
0
    return time_sec__(&monotonic_clock);
201
0
}
202
203
/* Returns the current time, in seconds. */
204
time_t
205
time_wall(void)
206
0
{
207
0
    return time_sec__(&wall_clock);
208
0
}
209
210
static long long int
211
time_msec__(struct clock *c)
212
0
{
213
0
    struct timespec ts;
214
215
0
    time_timespec__(c, &ts);
216
0
    return timespec_to_msec(&ts);
217
0
}
218
219
/* Returns a monotonic timer, in ms. */
220
long long int
221
time_msec(void)
222
0
{
223
0
    return time_msec__(&monotonic_clock);
224
0
}
225
226
/* Returns the current time, in ms. */
227
long long int
228
time_wall_msec(void)
229
0
{
230
0
    return time_msec__(&wall_clock);
231
0
}
232
233
static long long int
234
time_usec__(struct clock *c)
235
0
{
236
0
    struct timespec ts;
237
238
0
    time_timespec__(c, &ts);
239
0
    return timespec_to_usec(&ts);
240
0
}
241
242
/* Returns a monotonic timer, in microseconds. */
243
long long int
244
time_usec(void)
245
0
{
246
0
    return time_usec__(&monotonic_clock);
247
0
}
248
249
/* Returns the current time, in microseconds. */
250
long long int
251
time_wall_usec(void)
252
0
{
253
0
    return time_usec__(&wall_clock);
254
0
}
255
256
/* Configures the program to die with SIGALRM 'secs' seconds from now, if
257
 * 'secs' is nonzero, or disables the feature if 'secs' is zero. */
258
void
259
time_alarm(unsigned int secs)
260
0
{
261
0
    long long int now;
262
0
    long long int msecs;
263
264
0
    assert_single_threaded();
265
0
    time_init();
266
267
0
    now = time_msec();
268
0
    msecs = secs * 1000LL;
269
0
    deadline = now < LLONG_MAX - msecs ? now + msecs : LLONG_MAX;
270
0
}
271
272
/* Like poll(), except:
273
 *
274
 *      - The timeout is specified as an absolute time, as defined by
275
 *        time_msec(), instead of a duration.
276
 *
277
 *      - On error, returns a negative error code (instead of setting errno).
278
 *
279
 *      - If interrupted by a signal, retries automatically until the original
280
 *        timeout is reached.  (Because of this property, this function will
281
 *        never return -EINTR.)
282
 *
283
 * Stores the number of milliseconds elapsed during poll in '*elapsed'. */
284
int
285
time_poll(struct pollfd *pollfds, int n_pollfds,
286
          long long int timeout_when, int *elapsed)
287
0
{
288
0
    long long int *last_wakeup = last_wakeup_get();
289
0
    long long int start;
290
0
    bool quiescent;
291
0
    int retval = 0;
292
293
0
    time_init();
294
0
    coverage_clear();
295
0
    coverage_run();
296
0
    if (*last_wakeup && !thread_is_pmd()) {
297
0
        log_poll_interval(*last_wakeup);
298
0
    }
299
0
    start = time_msec();
300
301
0
    timeout_when = MIN(timeout_when, deadline);
302
0
    quiescent = ovsrcu_is_quiescent();
303
304
0
    for (;;) {
305
0
        long long int now = time_msec();
306
0
        int time_left;
307
308
0
        if (now >= timeout_when) {
309
0
            time_left = 0;
310
0
        } else if ((unsigned long long int) timeout_when - now > INT_MAX) {
311
0
            time_left = INT_MAX;
312
0
        } else {
313
0
            time_left = timeout_when - now;
314
0
        }
315
316
0
        if (!quiescent) {
317
0
            if (!time_left) {
318
0
                ovsrcu_quiesce();
319
0
            } else {
320
0
                ovsrcu_quiesce_start();
321
0
            }
322
0
        }
323
324
0
        retval = poll(pollfds, n_pollfds, time_left);
325
0
        if (retval < 0) {
326
0
            retval = -errno;
327
0
        }
328
329
0
        if (!quiescent && time_left) {
330
0
            ovsrcu_quiesce_end();
331
0
        }
332
333
0
        if (deadline <= time_msec()) {
334
0
            fatal_signal_handler(SIGALRM);
335
0
            if (retval < 0) {
336
0
                retval = 0;
337
0
            }
338
0
            break;
339
0
        }
340
341
0
        if (retval != -EINTR) {
342
0
            break;
343
0
        }
344
0
    }
345
0
    *last_wakeup = time_msec();
346
0
    refresh_rusage();
347
0
    *elapsed = *last_wakeup - start;
348
0
    return retval;
349
0
}
350
351
long long int
352
timespec_to_msec(const struct timespec *ts)
353
0
{
354
0
    return (long long int) ts->tv_sec * 1000 + ts->tv_nsec / (1000 * 1000);
355
0
}
356
357
long long int
358
timeval_to_msec(const struct timeval *tv)
359
0
{
360
0
    return (long long int) tv->tv_sec * 1000 + tv->tv_usec / 1000;
361
0
}
362
363
long long int
364
timespec_to_usec(const struct timespec *ts)
365
0
{
366
0
    return (long long int) ts->tv_sec * 1000 * 1000 + ts->tv_nsec / 1000;
367
0
}
368
369
long long int
370
timeval_to_usec(const struct timeval *tv)
371
0
{
372
0
    return (long long int) tv->tv_sec * 1000 * 1000 + tv->tv_usec;
373
0
}
374
375
/* Returns the monotonic time at which the "time" module was initialized, in
376
 * milliseconds. */
377
long long int
378
time_boot_msec(void)
379
0
{
380
0
    time_init();
381
0
    return boot_time;
382
0
}
383
384
#if defined(__MACH__) && !defined(HAVE_CLOCK_GETTIME)
385
#include <mach/clock.h>
386
#include <mach/mach.h>
387
static int
388
clock_gettime(clock_t id, struct timespec *ts)
389
{
390
    mach_timespec_t mts;
391
    clock_serv_t clk;
392
    clock_id_t cid;
393
394
    if (id == CLOCK_MONOTONIC) {
395
        cid = SYSTEM_CLOCK;
396
    } else if (id == CLOCK_REALTIME) {
397
        cid = CALENDAR_CLOCK;
398
    } else {
399
        return -1;
400
    }
401
402
    host_get_clock_service(mach_host_self(), cid, &clk);
403
    clock_get_time(clk, &mts);
404
    mach_port_deallocate(mach_task_self(), clk);
405
    ts->tv_sec = mts.tv_sec;
406
    ts->tv_nsec = mts.tv_nsec;
407
408
    return 0;
409
}
410
#endif
411
412
void
413
xgettimeofday(struct timeval *tv)
414
0
{
415
0
    if (gettimeofday(tv, NULL) == -1) {
416
0
        VLOG_FATAL("gettimeofday failed (%s)", ovs_strerror(errno));
417
0
    }
418
0
}
419
420
void
421
xclock_gettime(clock_t id, struct timespec *ts)
422
0
{
423
0
    if (clock_gettime(id, ts) == -1) {
424
        /* It seems like a bad idea to try to use vlog here because it is
425
         * likely to try to check the current time. */
426
0
        ovs_abort(errno, "xclock_gettime() failed");
427
0
    }
428
0
}
429
430
static void
431
msec_to_timespec(long long int ms, struct timespec *ts)
432
0
{
433
0
    ts->tv_sec = ms / 1000;
434
0
    ts->tv_nsec = (ms % 1000) * 1000 * 1000;
435
0
}
436
437
void
438
nsec_to_timespec(long long int nsec, struct timespec *ts)
439
0
{
440
0
    if (!nsec) {
441
0
        ts->tv_sec = ts->tv_nsec = 0;
442
0
        return;
443
0
    }
444
0
    ts->tv_sec = nsec / (1000 * 1000 * 1000);
445
446
0
    nsec = nsec % (1000 * 1000 * 1000);
447
    /* This is to handle dates before epoch. */
448
0
    if (OVS_UNLIKELY(nsec < 0)) {
449
0
        nsec += 1000 * 1000 * 1000;
450
0
        ts->tv_sec--;
451
0
    }
452
453
0
    ts->tv_nsec = nsec;
454
0
}
455
456
static void
457
timewarp_work(void)
458
0
{
459
0
    struct clock *c = &monotonic_clock;
460
0
    struct timespec warp;
461
462
0
    ovs_mutex_lock(&c->mutex);
463
0
    if (!c->large_warp.conn) {
464
0
        ovs_mutex_unlock(&c->mutex);
465
0
        return;
466
0
    }
467
468
0
    if (c->large_warp.total_warp >= c->large_warp.warp) {
469
0
        msec_to_timespec(c->large_warp.warp, &warp);
470
0
        timespec_add(&c->warp, &c->warp, &warp);
471
0
        c->large_warp.total_warp -= c->large_warp.warp;
472
0
    } else if (c->large_warp.total_warp) {
473
0
        msec_to_timespec(c->large_warp.total_warp, &warp);
474
0
        timespec_add(&c->warp, &c->warp, &warp);
475
0
        c->large_warp.total_warp = 0;
476
0
    } else {
477
        /* c->large_warp.total_warp is 0. */
478
0
        msec_to_timespec(c->large_warp.warp, &warp);
479
0
        timespec_add(&c->warp, &c->warp, &warp);
480
0
    }
481
482
0
    if (!c->large_warp.total_warp) {
483
0
        unixctl_command_reply(c->large_warp.conn, "warped");
484
0
        c->large_warp.conn = NULL;
485
0
    }
486
487
0
    ovs_mutex_unlock(&c->mutex);
488
0
    seq_change(timewarp_seq);
489
490
    /* give threads (eg. monitor) some chances to run */
491
0
    poll(NULL, 0, 10);
492
0
}
493
494
/* Perform work needed for "timewarp_seq"'s producer and consumers. */
495
void
496
timewarp_run(void)
497
0
{
498
    /* The function is a no-op unless timeval_dummy_register() is called. */
499
0
    if (timewarp_enabled) {
500
0
        unsigned int thread_id;
501
0
        ovs_mutex_lock(&monotonic_clock.mutex);
502
0
        thread_id = monotonic_clock.large_warp.main_thread_id;
503
0
        ovs_mutex_unlock(&monotonic_clock.mutex);
504
505
0
        if (thread_id != ovsthread_id_self()) {
506
            /* For threads other than the thread that changes the sequence,
507
             * wait on it. */
508
0
            uint64_t *last_seq = last_seq_get();
509
510
0
            *last_seq = seq_read(timewarp_seq);
511
0
            seq_wait(timewarp_seq, *last_seq);
512
0
        } else {
513
            /* Work on adding the remaining warps. */
514
0
            timewarp_work();
515
0
        }
516
0
    }
517
0
}
518
519
static long long int
520
timeval_diff_msec(const struct timeval *a, const struct timeval *b)
521
0
{
522
0
    return timeval_to_msec(a) - timeval_to_msec(b);
523
0
}
524
525
static void
526
timespec_add(struct timespec *sum,
527
             const struct timespec *a,
528
             const struct timespec *b)
529
0
{
530
0
    struct timespec tmp;
531
532
0
    tmp.tv_sec = a->tv_sec + b->tv_sec;
533
0
    tmp.tv_nsec = a->tv_nsec + b->tv_nsec;
534
0
    if (tmp.tv_nsec >= 1000 * 1000 * 1000) {
535
0
        tmp.tv_nsec -= 1000 * 1000 * 1000;
536
0
        tmp.tv_sec++;
537
0
    }
538
539
0
    *sum = tmp;
540
0
}
541
542
static bool
543
is_warped(const struct clock *c)
544
0
{
545
0
    bool warped;
546
547
0
    ovs_mutex_lock(&c->mutex);
548
0
    warped = monotonic_clock.warp.tv_sec || monotonic_clock.warp.tv_nsec;
549
0
    ovs_mutex_unlock(&c->mutex);
550
551
0
    return warped;
552
0
}
553
554
static void
555
log_poll_interval(long long int last_wakeup)
556
0
{
557
0
    long long int interval = time_msec() - last_wakeup;
558
559
0
    if (interval >= 1000 && !is_warped(&monotonic_clock)) {
560
0
        const struct rusage *last_rusage = get_recent_rusage();
561
0
        struct rusage rusage;
562
563
0
        COVERAGE_INC(long_poll_interval);
564
565
0
        if (!getrusage_thread(&rusage)) {
566
0
            VLOG_WARN("Unreasonably long %lldms poll interval"
567
0
                      " (%lldms user, %lldms system)",
568
0
                      interval,
569
0
                      timeval_diff_msec(&rusage.ru_utime,
570
0
                                        &last_rusage->ru_utime),
571
0
                      timeval_diff_msec(&rusage.ru_stime,
572
0
                                        &last_rusage->ru_stime));
573
574
0
            if (rusage.ru_minflt > last_rusage->ru_minflt
575
0
                || rusage.ru_majflt > last_rusage->ru_majflt) {
576
0
                VLOG_WARN("faults: %ld minor, %ld major",
577
0
                          rusage.ru_minflt - last_rusage->ru_minflt,
578
0
                          rusage.ru_majflt - last_rusage->ru_majflt);
579
0
            }
580
0
            if (rusage.ru_inblock > last_rusage->ru_inblock
581
0
                || rusage.ru_oublock > last_rusage->ru_oublock) {
582
0
                VLOG_WARN("disk: %ld reads, %ld writes",
583
0
                          rusage.ru_inblock - last_rusage->ru_inblock,
584
0
                          rusage.ru_oublock - last_rusage->ru_oublock);
585
0
            }
586
0
            if (rusage.ru_nvcsw > last_rusage->ru_nvcsw
587
0
                || rusage.ru_nivcsw > last_rusage->ru_nivcsw) {
588
0
                VLOG_WARN("context switches: %ld voluntary, %ld involuntary",
589
0
                          rusage.ru_nvcsw - last_rusage->ru_nvcsw,
590
0
                          rusage.ru_nivcsw - last_rusage->ru_nivcsw);
591
0
            }
592
0
        } else {
593
0
            VLOG_WARN("Unreasonably long %lldms poll interval", interval);
594
0
        }
595
0
        coverage_log();
596
0
    }
597
0
}
598

599
/* CPU usage tracking. */
600
601
struct cpu_usage {
602
    long long int when;         /* Time that this sample was taken. */
603
    unsigned long long int cpu; /* Total user+system CPU usage when sampled. */
604
};
605
606
struct cpu_tracker {
607
    struct cpu_usage older;
608
    struct cpu_usage newer;
609
    int cpu_usage;
610
611
    struct rusage recent_rusage;
612
};
613
0
DEFINE_PER_THREAD_MALLOCED_DATA(struct cpu_tracker *, cpu_tracker_var);
614
615
static struct cpu_tracker *
616
get_cpu_tracker(void)
617
0
{
618
0
    struct cpu_tracker *t = cpu_tracker_var_get();
619
0
    if (!t) {
620
0
        t = xzalloc(sizeof *t);
621
0
        t->older.when = LLONG_MIN;
622
0
        t->newer.when = LLONG_MIN;
623
0
        cpu_tracker_var_set_unsafe(t);
624
0
    }
625
0
    return t;
626
0
}
627
628
static struct rusage *
629
get_recent_rusage(void)
630
0
{
631
0
    return &get_cpu_tracker()->recent_rusage;
632
0
}
633
634
static int
635
getrusage_thread(struct rusage *rusage OVS_UNUSED)
636
0
{
637
0
#ifdef RUSAGE_THREAD
638
0
    return getrusage(RUSAGE_THREAD, rusage);
639
#else
640
    errno = EINVAL;
641
    return -1;
642
#endif
643
0
}
644
645
static void
646
refresh_rusage(void)
647
0
{
648
0
    struct cpu_tracker *t = get_cpu_tracker();
649
0
    struct rusage *recent_rusage = &t->recent_rusage;
650
651
0
    if (!getrusage_thread(recent_rusage)) {
652
0
        long long int now = time_msec();
653
0
        if (now >= t->newer.when + 3 * 1000) {
654
0
            t->older = t->newer;
655
0
            t->newer.when = now;
656
0
            t->newer.cpu = (timeval_to_msec(&recent_rusage->ru_utime) +
657
0
                            timeval_to_msec(&recent_rusage->ru_stime));
658
659
0
            if (t->older.when != LLONG_MIN && t->newer.cpu > t->older.cpu) {
660
0
                unsigned int dividend = t->newer.cpu - t->older.cpu;
661
0
                unsigned int divisor = (t->newer.when - t->older.when) / 100;
662
0
                t->cpu_usage = divisor > 0 ? dividend / divisor : -1;
663
0
            } else {
664
0
                t->cpu_usage = -1;
665
0
            }
666
0
        }
667
0
    }
668
0
}
669
670
/* Returns an estimate of this process's CPU usage, as a percentage, over the
671
 * past few seconds of wall-clock time.  Returns -1 if no estimate is available
672
 * (which will happen if the process has not been running long enough to have
673
 * an estimate, and can happen for other reasons as well). */
674
int
675
get_cpu_usage(void)
676
0
{
677
0
    return get_cpu_tracker()->cpu_usage;
678
0
}
679

680
/* Unixctl interface. */
681
682
/* "time/stop" stops the monotonic time returned by e.g. time_msec() from
683
 * advancing, except due to later calls to "time/warp". */
684
void
685
timeval_stop(void)
686
0
{
687
0
    ovs_mutex_lock(&monotonic_clock.mutex);
688
0
    atomic_store_relaxed(&monotonic_clock.slow_path, true);
689
0
    monotonic_clock.stopped = true;
690
0
    xclock_gettime(monotonic_clock.id, &monotonic_clock.cache);
691
0
    ovs_mutex_unlock(&monotonic_clock.mutex);
692
0
}
693
694
static void
695
timeval_stop_cb(struct unixctl_conn *conn,
696
                int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
697
                void *aux OVS_UNUSED)
698
0
{
699
0
    timeval_stop();
700
0
    unixctl_command_reply(conn, NULL);
701
0
}
702
703
/* "time/warp MSECS" advances the current monotonic time by the specified
704
 * number of milliseconds.  Unless "time/stop" has also been executed, the
705
 * monotonic clock continues to tick forward at the normal rate afterward.
706
 *
707
 * "time/warp LARGE_MSECS MSECS" is a variation of the above command. It
708
 * advances the current monotonic time by LARGE_MSECS. This is done MSECS
709
 * at a time in each run of the main thread. This gives other threads
710
 * time to run after the clock has been advanced by MSECS.
711
 *
712
 * Does not affect wall clock readings. */
713
static void
714
timeval_warp_cb(struct unixctl_conn *conn,
715
                int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
716
0
{
717
0
    long long int total_warp = argc > 2 ? atoll(argv[1]) : 0;
718
0
    long long int msecs = argc > 2 ? atoll(argv[2]) : atoll(argv[1]);
719
0
    if (msecs <= 0 || total_warp < 0) {
720
0
        unixctl_command_reply_error(conn, "invalid MSECS");
721
0
        return;
722
0
    }
723
724
0
    ovs_mutex_lock(&monotonic_clock.mutex);
725
0
    if (monotonic_clock.large_warp.conn) {
726
0
        ovs_mutex_unlock(&monotonic_clock.mutex);
727
0
        unixctl_command_reply_error(conn, "A previous warp in progress");
728
0
        return;
729
0
    }
730
0
    atomic_store_relaxed(&monotonic_clock.slow_path, true);
731
0
    monotonic_clock.large_warp.conn = conn;
732
0
    monotonic_clock.large_warp.total_warp = total_warp;
733
0
    monotonic_clock.large_warp.warp = msecs;
734
0
    monotonic_clock.large_warp.main_thread_id = ovsthread_id_self();
735
0
    ovs_mutex_unlock(&monotonic_clock.mutex);
736
737
0
    timewarp_work();
738
0
}
739
740
/* Direct monotonic clock into slow path and advance the current monotonic
741
 * time by 'msecs' milliseconds directly.  This is for use in unit tests. */
742
void
743
timeval_warp(long long int msecs)
744
0
{
745
0
    struct clock *c = &monotonic_clock;
746
0
    struct timespec warp;
747
748
0
    ovs_mutex_lock(&monotonic_clock.mutex);
749
0
    atomic_store_relaxed(&monotonic_clock.slow_path, true);
750
0
    msec_to_timespec(msecs, &warp);
751
0
    timespec_add(&c->warp, &c->warp, &warp);
752
0
    ovs_mutex_unlock(&monotonic_clock.mutex);
753
0
}
754
755
void
756
timeval_dummy_register(void)
757
0
{
758
0
    timewarp_enabled = true;
759
0
    unixctl_command_register("time/stop", "", 0, 0, timeval_stop_cb, NULL);
760
0
    unixctl_command_register("time/warp", "[large_msecs] msecs", 1, 2,
761
0
                             timeval_warp_cb, NULL);
762
0
}
763
764
765
766
/* strftime() with an extension for high-resolution timestamps.  Any '#'s in
767
 * 'format' will be replaced by subseconds, e.g. use "%S.###" to obtain results
768
 * like "01.123".  */
769
size_t
770
strftime_msec(char *s, size_t max, const char *format,
771
              const struct tm_msec *tm)
772
0
{
773
0
    size_t n;
774
775
    /* Visual Studio 2013's behavior is to crash when 0 is passed as second
776
     * argument to strftime. */
777
0
    n = max ? strftime(s, max, format, &tm->tm) : 0;
778
0
    if (n) {
779
0
        char decimals[4];
780
0
        char *p;
781
782
0
        sprintf(decimals, "%03d", tm->msec);
783
0
        for (p = strchr(s, '#'); p; p = strchr(p, '#')) {
784
0
            char *d = decimals;
785
0
            while (*p == '#')  {
786
0
                *p++ = *d ? *d++ : '0';
787
0
            }
788
0
        }
789
0
    }
790
791
0
    return n;
792
0
}
793
794
struct tm_msec *
795
localtime_msec(long long int now, struct tm_msec *result)
796
0
{
797
0
  time_t now_sec = now / 1000;
798
0
  localtime_r(&now_sec, &result->tm);
799
0
  result->msec = now % 1000;
800
0
  return result;
801
0
}
802
803
struct tm_msec *
804
gmtime_msec(long long int now, struct tm_msec *result)
805
0
{
806
0
  time_t now_sec = now / 1000;
807
0
  gmtime_r(&now_sec, &result->tm);
808
0
  result->msec = now % 1000;
809
0
  return result;
810
0
}