2 * copyright (c) 2012-2014 Emil Mikulic.
4 * now.c: a cache of the current time.
6 * Permission to use, copy, modify, and distribute this file for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 #if defined(__MACH__) && !defined(__gnu_hurd__)
27 /* Fake up clock_gettime() on OS X. */
28 # include <sys/time.h>
29 # include <inttypes.h>
30 # include <mach/mach.h>
31 # include <mach/mach_time.h>
33 typedef int clockid_t
;
34 # define CLOCK_REALTIME 0
35 # define CLOCK_MONOTONIC 1
37 static uint64_t mono_first
= 0;
39 int clock_gettime(clockid_t clk_id
, struct timespec
*tp
) {
40 if (clk_id
== CLOCK_REALTIME
) {
42 gettimeofday(&tv
, NULL
);
43 tp
->tv_sec
= tv
.tv_sec
;
44 tp
->tv_nsec
= tv
.tv_usec
* 1000;
47 if (clk_id
== CLOCK_MONOTONIC
) {
48 uint64_t t
= mach_absolute_time();
49 mach_timebase_info_data_t timebase
;
50 mach_timebase_info(&timebase
);
54 uint64_t tdiff
= (t
- mono_first
) * timebase
.numer
/ timebase
.denom
;
55 tp
->tv_sec
= tdiff
/ 1000000000;
56 tp
->tv_nsec
= tdiff
% 1000000000;
63 static struct timespec clock_real
, clock_mono
;
64 static int now_initialized
= 0;
66 time_t now_real(void) {
67 assert(now_initialized
);
68 return clock_real
.tv_sec
;
71 time_t now_mono(void) {
72 assert(now_initialized
);
73 return clock_mono
.tv_sec
;
76 static int before(const struct timespec
*a
, const struct timespec
*b
) {
77 if (a
->tv_sec
< b
->tv_sec
)
79 if (a
->tv_sec
== b
->tv_sec
&& a
->tv_nsec
< b
->tv_nsec
)
84 static void warn_backwards(const char *name
,
85 const struct timespec
* const t0
,
86 const struct timespec
* const t1
) {
87 verbosef("%s clock went backwards from %lld.%09lld to %lld.%09lld",
95 static void clock_update(const clockid_t clk_id
,
96 struct timespec
*dest
,
100 clock_gettime(clk_id
, &t
);
101 if (now_initialized
&& before(&t
, dest
)) {
102 warn_backwards(name
, &t
, dest
);
104 memcpy(dest
, &t
, sizeof(t
));
107 static void all_clocks_update(void) {
108 clock_update(CLOCK_REALTIME
, &clock_real
, "realtime");
109 clock_update(CLOCK_MONOTONIC
, &clock_mono
, "monotonic");
112 void now_init(void) {
113 assert(!now_initialized
);
118 void now_update(void) {
119 assert(now_initialized
);
123 time_t mono_to_real(const int64_t t
) {
124 assert(now_initialized
);
125 return (time_t)(t
- (int64_t)clock_mono
.tv_sec
+ (int64_t)clock_real
.tv_sec
);
128 int64_t real_to_mono(const time_t t
) {
129 assert(now_initialized
);
130 return (int64_t)(t
- clock_real
.tv_sec
+ clock_mono
.tv_sec
);
133 void timer_start(struct timespec
*t
) {
134 clock_gettime(CLOCK_MONOTONIC
, t
);
137 static int64_t ts_diff(const struct timespec
* const a
,
138 const struct timespec
* const b
) {
139 return (int64_t)(a
->tv_sec
- b
->tv_sec
) * 1000000000 +
140 a
->tv_nsec
- b
->tv_nsec
;
143 void timer_stop(const struct timespec
* const t0
,
145 const char *warning
) {
149 clock_gettime(CLOCK_MONOTONIC
, &t1
);
150 if (before(&t1
, t0
)) {
151 warn_backwards("monotonic timer", t0
, &t1
);
154 diff
= ts_diff(&t1
, t0
);
156 warnx("%s (took %lld nsec, over threshold of %lld nsec)",
163 /* vim:set ts=3 sw=3 tw=80 et: */