11/* SPDX-License-Identifier: GPL-3.0-or-later
2- * Copyright © 2016-2020 The TokTok team.
2+ * Copyright © 2016-2023 The TokTok team.
33 * Copyright © 2014 Tox project.
44 */
55#ifndef _XOPEN_SOURCE
4040struct Mono_Time {
4141 uint64_t cur_time ;
4242 uint64_t base_time ;
43- #ifdef OS_WIN32
44- /* protect `last_clock_update` and `last_clock_mono` from concurrent access */
45- pthread_mutex_t last_clock_lock ;
46- uint32_t last_clock_mono ;
47- bool last_clock_update ;
48- #endif
4943
5044#ifndef ESP_PLATFORM
5145 /* protect `time` from concurrent access */
@@ -56,42 +50,33 @@ struct Mono_Time {
5650 void * user_data ;
5751};
5852
53+ static uint64_t timespec_to_u64 (struct timespec clock_mono )
54+ {
55+ return UINT64_C (1000 ) * clock_mono .tv_sec + (clock_mono .tv_nsec / UINT64_C (1000000 ));
56+ }
57+
5958#ifdef OS_WIN32
6059non_null ()
6160static uint64_t current_time_monotonic_default (void * user_data )
6261{
63- Mono_Time * const mono_time = (Mono_Time * )user_data ;
64-
65- /* Must hold mono_time->last_clock_lock here */
66-
67- /* GetTickCount provides only a 32 bit counter, but we can't use
68- * GetTickCount64 for backwards compatibility, so we handle wraparound
69- * ourselves.
70- */
71- const uint32_t ticks = GetTickCount ();
72-
73- /* the higher 32 bits count the number of wrap arounds */
74- uint64_t old_ovf = mono_time -> cur_time & ~((uint64_t )UINT32_MAX );
75-
76- /* Check if time has decreased because of 32 bit wrap from GetTickCount() */
77- if (ticks < mono_time -> last_clock_mono ) {
78- /* account for overflow */
79- old_ovf += UINT32_MAX + UINT64_C (1 );
62+ LARGE_INTEGER freq ;
63+ LARGE_INTEGER count ;
64+ if (!QueryPerformanceFrequency (& freq )) {
65+ return 0 ;
8066 }
81-
82- if (mono_time -> last_clock_update ) {
83- mono_time -> last_clock_mono = ticks ;
84- mono_time -> last_clock_update = false;
67+ if (!QueryPerformanceCounter (& count )) {
68+ return 0 ;
8569 }
86-
87- /* splice the low and high bits back together */
88- return old_ovf + ticks ;
89- }
90- #else // !OS_WIN32
91- static uint64_t timespec_to_u64 ( struct timespec clock_mono )
92- {
93- return 1000ULL * clock_mono . tv_sec + ( clock_mono . tv_nsec / 1000000ULL );
70+ struct timespec sp = { 0 };
71+ sp . tv_sec = count . QuadPart / freq . QuadPart ;
72+ if ( freq . QuadPart < 1000000000 ) {
73+ sp . tv_nsec = ( count . QuadPart % freq . QuadPart ) * 1000000000 / freq . QuadPart ;
74+ } else {
75+ sp . tv_nsec = ( long )(( count . QuadPart % freq . QuadPart ) * ( 1000000000.0 / freq . QuadPart ));
76+ }
77+ return timespec_to_u64 ( sp );
9478}
79+ #else
9580#ifdef __APPLE__
9681non_null ()
9782static uint64_t current_time_monotonic_default (void * user_data )
@@ -150,27 +135,14 @@ Mono_Time *mono_time_new(const Memory *mem, mono_time_current_time_cb *current_t
150135
151136 mono_time_set_current_time_callback (mono_time , current_time_callback , user_data );
152137
153- #ifdef OS_WIN32
154-
155- mono_time -> last_clock_mono = 0 ;
156- mono_time -> last_clock_update = false;
157-
158- if (pthread_mutex_init (& mono_time -> last_clock_lock , nullptr ) < 0 ) {
159- mem_delete (mem , mono_time -> time_update_lock );
160- mem_delete (mem , mono_time );
161- return nullptr ;
162- }
163-
164- #endif
165-
166138 mono_time -> cur_time = 0 ;
167139#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
168140 // Maximum reproducibility. Never return time = 0.
169141 mono_time -> base_time = 1 ;
170142#else
171143 // Never return time = 0 in case time() returns 0 (e.g. on microcontrollers
172144 // without battery-powered RTC or ones where NTP didn't initialise it yet).
173- mono_time -> base_time = max_u64 (1 , (uint64_t )time (nullptr )) * 1000ULL - current_time_monotonic (mono_time );
145+ mono_time -> base_time = max_u64 (1 , (uint64_t )time (nullptr )) * UINT64_C ( 1000 ) - current_time_monotonic (mono_time );
174146#endif
175147
176148 mono_time_update (mono_time );
@@ -183,9 +155,6 @@ void mono_time_free(const Memory *mem, Mono_Time *mono_time)
183155 if (mono_time == nullptr ) {
184156 return ;
185157 }
186- #ifdef OS_WIN32
187- pthread_mutex_destroy (& mono_time -> last_clock_lock );
188- #endif
189158#ifndef ESP_PLATFORM
190159 pthread_rwlock_destroy (mono_time -> time_update_lock );
191160 mem_delete (mem , mono_time -> time_update_lock );
@@ -195,16 +164,8 @@ void mono_time_free(const Memory *mem, Mono_Time *mono_time)
195164
196165void mono_time_update (Mono_Time * mono_time )
197166{
198- #ifdef OS_WIN32
199- /* we actually want to update the overflow state of mono_time here */
200- pthread_mutex_lock (& mono_time -> last_clock_lock );
201- mono_time -> last_clock_update = true;
202- #endif
203167 const uint64_t cur_time =
204168 mono_time -> base_time + mono_time -> current_time_callback (mono_time -> user_data );
205- #ifdef OS_WIN32
206- pthread_mutex_unlock (& mono_time -> last_clock_lock );
207- #endif
208169
209170#ifndef ESP_PLATFORM
210171 pthread_rwlock_wrlock (mono_time -> time_update_lock );
@@ -230,7 +191,7 @@ uint64_t mono_time_get_ms(const Mono_Time *mono_time)
230191
231192uint64_t mono_time_get (const Mono_Time * mono_time )
232193{
233- return mono_time_get_ms (mono_time ) / 1000ULL ;
194+ return mono_time_get_ms (mono_time ) / UINT64_C ( 1000 ) ;
234195}
235196
236197bool mono_time_is_timeout (const Mono_Time * mono_time , uint64_t timestamp , uint64_t timeout )
@@ -257,15 +218,5 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,
257218 */
258219uint64_t current_time_monotonic (Mono_Time * mono_time )
259220{
260- /* For WIN32 we don't want to change overflow state of mono_time here */
261- #ifdef OS_WIN32
262- /* We don't want to update the overflow state of mono_time here,
263- * but must protect against other threads */
264- pthread_mutex_lock (& mono_time -> last_clock_lock );
265- #endif
266- const uint64_t cur_time = mono_time -> current_time_callback (mono_time -> user_data );
267- #ifdef OS_WIN32
268- pthread_mutex_unlock (& mono_time -> last_clock_lock );
269- #endif
270- return cur_time ;
221+ return mono_time -> current_time_callback (mono_time -> user_data );
271222}
0 commit comments