1 // compat_time addresses following compatibility issue:
2 // topic: high-resolution timestamps
3 // issue: <sys/time.h> is not available on Windows systems
4 // solution: provide a compatible version for Windows systems
5 
6 #include "compat_time.h"
7 
8 #ifdef _WIN32
9 
10 #include <stdbool.h>
11 #include <stddef.h>
12 
13 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
14 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
15 #else
16 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
17 #endif
18 
gettimeofday(struct timeval * tv,void * tz)19 int gettimeofday(struct timeval *tv, void *tz)
20 {
21     if (tz)
22         return -1; // we don't support TZ
23 
24     FILETIME ft;
25     unsigned __int64 t64;
26     GetSystemTimeAsFileTime(&ft);
27     t64 = (((unsigned __int64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
28     t64 /= 10; // convert to microseconds
29     t64 -= DELTA_EPOCH_IN_MICROSECS; // convert file time to unix epoch
30     tv->tv_sec = (long)(t64 / 1000000UL);
31     tv->tv_usec = (long)(t64 % 1000000UL);
32 
33     return 0;
34 }
35 
36 #endif // _WIN32
37 
timeval_subtract(struct timeval * result,struct timeval * x,struct timeval * y)38 int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
39 {
40     // Perform the carry for the later subtraction by updating y
41     if (x->tv_usec < y->tv_usec) {
42         int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
43         y->tv_usec -= 1000000 * nsec;
44         y->tv_sec += nsec;
45     }
46     if (x->tv_usec - y->tv_usec > 1000000) {
47         int nsec = (x->tv_usec - y->tv_usec) / 1000000;
48         y->tv_usec += 1000000 * nsec;
49         y->tv_sec -= nsec;
50     }
51 
52     // Compute the time difference, tv_usec is certainly positive
53     result->tv_sec  = x->tv_sec - y->tv_sec;
54     result->tv_usec = x->tv_usec - y->tv_usec;
55 
56     // Return 1 if result is negative
57     return x->tv_sec < y->tv_sec;
58 }
59