On the two systems I've tested (a 32-bit Ubuntu 12.04 server and a 64-bit Ubuntu 13.10 VM), the seconds since the epoch given by time() may differ from gettimeofday()'s.
Specifically, though I call time()
after calling gettimeofday()
, the value returned by time()
is sometimes less than the tv_sec
value returned by gettimeofday()
.
This apparently occurs just after the clock rolls over to a new second.
This caused bugs in some of my code that expected time()'s and gettimeofday()'s seconds to be interchangeable.
Sample code demonstrating this problem:
#include <stdio.h> #include <time.h> #include <sys/time.h> int main() { time_t start = time(NULL); int same = 0; int different = 0; int max_usec = 0; while (1) { time_t t; struct timeval tv; gettimeofday(&tv, NULL); t = time(NULL); if (t < tv.tv_sec) { different++; if (tv.tv_usec > max_usec) { max_usec = tv.tv_usec; } } else { same++; } if (t > start + 5) { break; } } printf("Same: %i\n", same); printf("Different: %i\n", different); printf("Largest difference seen at %i\n", max_usec); }
Note that I'm calling time() second and only complaining if its value is less than gettimeofday()'s.
Sample output:
Same: 33282836 Different: 177076 Largest difference seen at 5844
I.e., the two values were the same 33 million times, they were different 177k times, and they were always different within 5844 microseconds of a new second.
Is this a known issue? What causes this?
The gettimeofday() function retrieves the current Coordinated Universal Time (UTC) and places it in the timeval structure pointed to by tp . If tzp is not NULL, the time zone information is returned in the time zone structure pointed to by tzp .
The gettimeofday() function returns 0 upon success and -1 on failure. The errno variable is set when the function fails.
long int tv_sec. This represents the number of whole seconds of elapsed time. long int tv_usec. This is the rest of the elapsed time (a fraction of a second), represented as the number of microseconds.
Both calls are implemented as kernel syscalls. Both functions end up reading a struct timekeeper
, both refer to the very same instance. But they differ in what they do with it:
uses the get_seconds()
function, which is a shortcut to this:
struct timekeeper *tk = &timekeeper; return tk->xtime_sec;
it just returns xktime_sec
.
gettimeofday()
:gettimeofday()
on the other hand uses do_gettimeofday()
(via getnstimeofday
) which reads both fields xktime_sec
as well as xktime_nsec
(via timekeeping_get_ns
). Here it might happen that xktime_nsec
holds more nanoseconds than a second. This potential extra time is used to increase the tv_sec
field by calling the function timespec_add_ns()
which does this:
a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns); a->tv_nsec = ns;
So, tv_sec
might get bigger than the xktime_sec
field was. And there you have it: a little difference in what time()
gives you and what gettimeofday()
gives you.
I fought against this issue in fluxbox today and until a better solution occurs I live with this:
uint64_t t_usec = gettimeofday_in_usecs(); // calcs usecs since epoch time_t t = static_cast<time_t>(t_usec / 1000000L);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With