X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Ftimeval.c;h=8097ce806b413f21e429ebbca4fcef01555c6a94;hb=dd1ba5b3f4425c8eba008d1a93b044da63466812;hp=bc7411fb9074f2ffc52d21f8aa1b1fd13a3c44a0;hpb=cee03df4f53a9629f1f18b6c9948362f55a3ae27;p=openvswitch diff --git a/lib/timeval.c b/lib/timeval.c index bc7411fb..8097ce80 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +20,16 @@ #include #include #include +#include #include #include #include #include #include "coverage.h" +#include "dummy.h" #include "fatal-signal.h" #include "signals.h" +#include "unixctl.h" #include "util.h" #include "vlog.h" @@ -48,6 +51,12 @@ static volatile sig_atomic_t monotonic_tick = true; static struct timespec wall_time; static struct timespec monotonic_time; +/* The monotonic time at which the time module was initialized. */ +static long long int boot_time; + +/* Fixed monotonic time offset, for use by unit tests. */ +static struct timespec warp_offset; + /* Time at which to die with SIGALRM (if not TIME_MIN). */ static time_t deadline = TIME_MIN; @@ -62,11 +71,10 @@ static void unblock_sigalrm(const sigset_t *); static void log_poll_interval(long long int last_wakeup); static struct rusage *get_recent_rusage(void); static void refresh_rusage(void); +static void timespec_add(struct timespec *sum, + const struct timespec *a, const struct timespec *b); -/* Initializes the timetracking module. - * - * It is not necessary to call this function directly, because other time - * functions will call it automatically, but it doesn't hurt. */ +/* Initializes the timetracking module, if not already initialized. */ static void time_init(void) { @@ -87,6 +95,7 @@ time_init(void) set_up_signal(SA_RESTART); set_up_timer(); + boot_time = time_msec(); } static void @@ -180,6 +189,7 @@ refresh_monotonic(void) refresh_wall_if_ticked(); monotonic_time = wall_time; } + timespec_add(&monotonic_time, &monotonic_time, &warp_offset); monotonic_tick = false; } @@ -393,6 +403,15 @@ timeval_to_msec(const struct timeval *tv) return (long long int) tv->tv_sec * 1000 + tv->tv_usec / 1000; } +/* Returns the monotonic time at which the "time" module was initialized, in + * milliseconds(). */ +long long int +time_boot_msec(void) +{ + time_init(); + return boot_time; +} + void xgettimeofday(struct timeval *tv) { @@ -407,6 +426,23 @@ timeval_diff_msec(const struct timeval *a, const struct timeval *b) return timeval_to_msec(a) - timeval_to_msec(b); } +static void +timespec_add(struct timespec *sum, + const struct timespec *a, + const struct timespec *b) +{ + struct timespec tmp; + + tmp.tv_sec = a->tv_sec + b->tv_sec; + tmp.tv_nsec = a->tv_nsec + b->tv_nsec; + if (tmp.tv_nsec >= 1000 * 1000 * 1000) { + tmp.tv_nsec -= 1000 * 1000 * 1000; + tmp.tv_sec++; + } + + *sum = tmp; +} + static void log_poll_interval(long long int last_wakeup) { @@ -522,3 +558,31 @@ get_cpu_usage(void) { return cpu_usage; } + +/* Unixctl interface. */ + +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(conn, 501, "invalid MSECS"); + return; + } + + ts.tv_sec = msecs / 1000; + ts.tv_nsec = (msecs % 1000) * 1000 * 1000; + timespec_add(&warp_offset, &warp_offset, &ts); + unixctl_command_reply(conn, 200, "warped"); +} + +void +timeval_dummy_register(void) +{ + unixctl_command_register("time/warp", "MSECS", 1, 1, + timeval_warp_cb, NULL); +}