1module time
2
3#include <mach/mach_time.h>
4
5const (
6	// start_time is needed on Darwin and Windows because of potential overflows
7	start_time = C.mach_absolute_time()
8	time_base = init_time_base()
9)
10
11[typedef]
12struct C.mach_timebase_info_data_t {
13	numer u32
14	denom u32
15}
16
17fn C.mach_absolute_time() u64
18fn C.mach_timebase_info(&C.mach_timebase_info_data_t)
19fn C.clock_gettime_nsec_np(int) u64
20
21struct InternalTimeBase {
22	numer u32 = 1
23	denom u32 = 1
24}
25
26pub struct C.timeval {
27	tv_sec  u64
28	tv_usec u64
29}
30
31fn init_time_base() InternalTimeBase {
32	tb := C.mach_timebase_info_data_t{}
33	C.mach_timebase_info(&tb)
34	return InternalTimeBase{numer:tb.numer, denom:tb.denom}
35}
36
37fn sys_mono_now_darwin() u64 {
38	tm := C.mach_absolute_time()
39	if time_base.denom == 0 {
40		C.mach_timebase_info(&time_base)
41	}
42	return (tm - start_time) * time_base.numer / time_base.denom
43}
44
45// NB: vpc_now_darwin is used by `v -profile` .
46// It should NOT call *any other v function*, just C functions and casts.
47[inline]
48fn vpc_now_darwin() u64 {
49	tm := C.mach_absolute_time()
50	if time_base.denom == 0 {
51		C.mach_timebase_info(&time_base)
52	}
53	return (tm - start_time) * time_base.numer / time_base.denom
54}
55
56// darwin_now returns a better precision current time for Darwin based operating system
57// this should be implemented with native system calls eventually
58// but for now a bit tweaky. It uses the deprecated  gettimeofday clock to get
59// the microseconds seconds part and converts to local time
60[inline]
61fn darwin_now() Time {
62
63	// get the high precision time as UTC clock
64	tv := C.timeval{}
65	C.gettimeofday(&tv, 0)
66
67	loc_tm := C.tm{}
68	C.localtime_r(&tv.tv_sec, &loc_tm)
69
70	return convert_ctime(loc_tm, int(tv.tv_usec))
71}
72
73// darwin_utc returns a better precision current time for Darwin based operating system
74// this should be implemented with native system calls eventually
75// but for now a bit tweaky. It uses the deprecated  gettimeofday clock to get
76// the microseconds seconds part and normal local time to get correct local time
77[inline]
78fn darwin_utc() Time {
79
80	// get the high precision time as UTC clock
81	tv := C.timeval{}
82	C.gettimeofday(&tv, 0)
83
84	return unix2(int(tv.tv_sec), int(tv.tv_usec))
85}
86