diff options
Diffstat (limited to 'toxcore/mono_time.c')
-rw-r--r-- | toxcore/mono_time.c | 97 |
1 files changed, 48 insertions, 49 deletions
diff --git a/toxcore/mono_time.c b/toxcore/mono_time.c index aa272749..6e4bc067 100644 --- a/toxcore/mono_time.c +++ b/toxcore/mono_time.c | |||
@@ -28,12 +28,52 @@ | |||
28 | struct Mono_Time { | 28 | struct Mono_Time { |
29 | uint64_t time; | 29 | uint64_t time; |
30 | uint64_t base_time; | 30 | uint64_t base_time; |
31 | #ifdef OS_WIN32 | ||
32 | uint64_t last_clock_mono; | ||
33 | uint64_t add_clock_mono; | ||
34 | #endif | ||
31 | 35 | ||
32 | mono_time_current_time_cb *current_time_callback; | 36 | mono_time_current_time_cb *current_time_callback; |
33 | void *user_data; | 37 | void *user_data; |
34 | }; | 38 | }; |
35 | 39 | ||
36 | static mono_time_current_time_cb current_time_monotonic_default; | 40 | static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_data) |
41 | { | ||
42 | uint64_t time; | ||
43 | #ifdef OS_WIN32 | ||
44 | uint64_t old_add_clock_mono = mono_time->add_clock_mono; | ||
45 | time = (uint64_t)GetTickCount() + mono_time->add_clock_mono; | ||
46 | |||
47 | /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race | ||
48 | * conditions when multiple threads call this function at once */ | ||
49 | if (time + 0x10000 < mono_time->last_clock_mono) { | ||
50 | uint32_t add = ~0; | ||
51 | /* use old_add_clock_mono rather than simply incrementing add_clock_mono, to handle the case that many threads | ||
52 | * simultaneously detect an overflow */ | ||
53 | mono_time->add_clock_mono = old_add_clock_mono + add; | ||
54 | time += add; | ||
55 | } | ||
56 | |||
57 | mono_time->last_clock_mono = time; | ||
58 | #else | ||
59 | struct timespec clock_mono; | ||
60 | #if defined(__APPLE__) | ||
61 | clock_serv_t muhclock; | ||
62 | mach_timespec_t machtime; | ||
63 | |||
64 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); | ||
65 | clock_get_time(muhclock, &machtime); | ||
66 | mach_port_deallocate(mach_task_self(), muhclock); | ||
67 | |||
68 | clock_mono.tv_sec = machtime.tv_sec; | ||
69 | clock_mono.tv_nsec = machtime.tv_nsec; | ||
70 | #else | ||
71 | clock_gettime(CLOCK_MONOTONIC, &clock_mono); | ||
72 | #endif | ||
73 | time = 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL); | ||
74 | #endif | ||
75 | return time; | ||
76 | } | ||
37 | 77 | ||
38 | Mono_Time *mono_time_new(void) | 78 | Mono_Time *mono_time_new(void) |
39 | { | 79 | { |
@@ -46,6 +86,11 @@ Mono_Time *mono_time_new(void) | |||
46 | mono_time->current_time_callback = current_time_monotonic_default; | 86 | mono_time->current_time_callback = current_time_monotonic_default; |
47 | mono_time->user_data = nullptr; | 87 | mono_time->user_data = nullptr; |
48 | 88 | ||
89 | #ifdef OS_WIN32 | ||
90 | mono_time->last_clock_mono = 0; | ||
91 | mono_time->add_clock_mono = 0; | ||
92 | #endif | ||
93 | |||
49 | mono_time->time = 0; | 94 | mono_time->time = 0; |
50 | mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL); | 95 | mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL); |
51 | 96 | ||
@@ -87,53 +132,7 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time, | |||
87 | } | 132 | } |
88 | 133 | ||
89 | /* return current monotonic time in milliseconds (ms). */ | 134 | /* return current monotonic time in milliseconds (ms). */ |
90 | uint64_t current_time_monotonic(const Mono_Time *mono_time) | 135 | uint64_t current_time_monotonic(Mono_Time *mono_time) |
91 | { | 136 | { |
92 | return mono_time->current_time_callback(mono_time->user_data); | 137 | return mono_time->current_time_callback(mono_time, mono_time->user_data); |
93 | } | ||
94 | |||
95 | //!TOKSTYLE- | ||
96 | // No global mutable state in Tokstyle. | ||
97 | #ifdef OS_WIN32 | ||
98 | static uint64_t last_clock_mono; | ||
99 | static uint64_t add_clock_mono; | ||
100 | #endif | ||
101 | //!TOKSTYLE+ | ||
102 | |||
103 | static uint64_t current_time_monotonic_default(void *user_data) | ||
104 | { | ||
105 | uint64_t time; | ||
106 | #ifdef OS_WIN32 | ||
107 | uint64_t old_add_clock_mono = add_clock_mono; | ||
108 | time = (uint64_t)GetTickCount() + add_clock_mono; | ||
109 | |||
110 | /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race | ||
111 | * conditions when multiple threads call this function at once */ | ||
112 | if (time + 0x10000 < last_clock_mono) { | ||
113 | uint32_t add = ~0; | ||
114 | /* use old_add_clock_mono rather than simply incrementing add_clock_mono, to handle the case that many threads | ||
115 | * simultaneously detect an overflow */ | ||
116 | add_clock_mono = old_add_clock_mono + add; | ||
117 | time += add; | ||
118 | } | ||
119 | |||
120 | last_clock_mono = time; | ||
121 | #else | ||
122 | struct timespec clock_mono; | ||
123 | #if defined(__APPLE__) | ||
124 | clock_serv_t muhclock; | ||
125 | mach_timespec_t machtime; | ||
126 | |||
127 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); | ||
128 | clock_get_time(muhclock, &machtime); | ||
129 | mach_port_deallocate(mach_task_self(), muhclock); | ||
130 | |||
131 | clock_mono.tv_sec = machtime.tv_sec; | ||
132 | clock_mono.tv_nsec = machtime.tv_nsec; | ||
133 | #else | ||
134 | clock_gettime(CLOCK_MONOTONIC, &clock_mono); | ||
135 | #endif | ||
136 | time = 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL); | ||
137 | #endif | ||
138 | return time; | ||
139 | } | 138 | } |