2 * copyright (c) 2012 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 /* Fake up clock_gettime() on OS X. */
27 # include <sys/time.h>
28 # include <inttypes.h>
29 # include <mach/mach.h>
30 # include <mach/mach_time.h>
32 typedef int clockid_t
;
33 #define CLOCK_REALTIME 0
34 #define CLOCK_MONOTONIC 1
36 static uint64_t mono_first
= 0;
38 int clock_gettime(clockid_t clk_id
, struct timespec
*tp
) {
39 if (clk_id
== CLOCK_REALTIME
) {
41 gettimeofday(&tv
, NULL
);
42 tp
->tv_sec
= tv
.tv_sec
;
43 tp
->tv_nsec
= tv
.tv_usec
* 1000;
46 if (clk_id
== CLOCK_MONOTONIC
) {
47 uint64_t t
= mach_absolute_time();
48 mach_timebase_info_data_t timebase
;
49 mach_timebase_info(&timebase
);
53 uint64_t tdiff
= (t
- mono_first
) * timebase
.numer
/ timebase
.denom
;
54 tp
->tv_sec
= tdiff
/ 1000000000;
55 tp
->tv_nsec
= tdiff
% 1000000000;
62 static struct timespec clock_real
, clock_mono
;
63 static int now_initialized
= 0;
66 assert(now_initialized
);
67 return clock_real
.tv_sec
;
71 assert(now_initialized
);
72 return clock_mono
.tv_sec
;
75 static int before(const struct timespec
*a
, const struct timespec
*b
) {
76 if (a
->tv_sec
< b
->tv_sec
)
78 if (a
->tv_sec
== b
->tv_sec
&& a
->tv_nsec
< b
->tv_nsec
)
83 static void clock_update(const clockid_t clk_id
,
84 struct timespec
*dest
,
88 clock_gettime(clk_id
, &t
);
89 if (now_initialized
&& before(&t
, dest
)) {
90 verbosef("%s clock went backwards from %ld.%09ld to %ld.%09ld",
97 memcpy(dest
, &t
, sizeof(t
));
100 static void all_clocks_update(void) {
101 clock_update(CLOCK_REALTIME
, &clock_real
, "realtime");
102 clock_update(CLOCK_MONOTONIC
, &clock_mono
, "monotonic");
105 void now_init(void) {
106 assert(!now_initialized
);
111 void now_update(void) {
112 assert(now_initialized
);
116 long mono_to_real(const long t
) {
117 assert(now_initialized
);
118 return t
- clock_mono
.tv_sec
+ clock_real
.tv_sec
;
121 long real_to_mono(const long t
) {
122 assert(now_initialized
);
123 return t
- clock_real
.tv_sec
+ clock_mono
.tv_sec
;
126 void timer_start(struct timespec
*t
) {
127 clock_gettime(CLOCK_MONOTONIC
, t
);
130 static int64_t ts_diff(const struct timespec
* const a
,
131 const struct timespec
* const b
) {
132 return (int64_t)(a
->tv_sec
- b
->tv_sec
) * 1000000000 +
133 a
->tv_nsec
- b
->tv_nsec
;
136 void timer_stop(const struct timespec
* const t
,
138 const char *warning
) {
142 clock_gettime(CLOCK_MONOTONIC
, &t2
);
143 diff
= ts_diff(&t2
, t
);
146 warnx("%s (took %lld nsec, over threshold of %lld nsec)",
152 /* vim:set ts=3 sw=3 tw=80 et: */