11//
22// Copyright (c) Microsoft. All rights reserved.
3- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
44//
55
66/* ++
@@ -75,8 +75,8 @@ time. The system time is expressed in Coordinated Universal Time
7575
7676Parameters
7777
78- lpSystemTime
79- [out] Pointer to a SYSTEMTIME structure to receive the current system date and time.
78+ lpSystemTime
79+ [out] Pointer to a SYSTEMTIME structure to receive the current system date and time.
8080
8181Return Values
8282
@@ -101,10 +101,10 @@ GetSystemTime(
101101
102102 tt = time (NULL );
103103
104- /* We can't get millisecond resolution from time(), so we get it from
104+ /* We can't get millisecond resolution from time(), so we get it from
105105 gettimeofday() */
106106 timeofday_retval = gettimeofday (&timeval,NULL );
107-
107+
108108#if HAVE_GMTIME_R
109109 utPtr = &ut;
110110 if (gmtime_r (&tt, utPtr) == NULL )
@@ -134,20 +134,20 @@ GetSystemTime(
134134 {
135135 int old_seconds;
136136 int new_seconds;
137-
137+
138138 lpSystemTime->wMilliseconds = timeval.tv_usec /tccMillieSecondsToMicroSeconds;
139-
139+
140140 old_seconds = utPtr->tm_sec ;
141141 new_seconds = timeval.tv_sec %60 ;
142-
143- /* just in case we reached the next second in the interval between
142+
143+ /* just in case we reached the next second in the interval between
144144 time() and gettimeofday() */
145145 if ( old_seconds!=new_seconds )
146146 {
147147 TRACE (" crossed seconds boundary; setting milliseconds to 999\n " );
148148 lpSystemTime->wMilliseconds = 999 ;
149- }
150- }
149+ }
150+ }
151151EXIT:
152152 LOGEXIT (" GetSystemTime returns void\n " );
153153 PERF_EXIT (GetSystemTime);
@@ -164,7 +164,7 @@ use the GetSystemTimeAdjustment function.
164164
165165Parameters
166166
167- This function has no parameters.
167+ This function has no parameters.
168168
169169Return Values
170170
@@ -212,7 +212,7 @@ QueryPerformanceCounter(
212212 retval = FALSE ;
213213 break ;
214214 }
215- lpPerformanceCount->QuadPart =
215+ lpPerformanceCount->QuadPart =
216216 (LONGLONG)ts.tv_sec * (LONGLONG)tccSecondsToNanoSeconds + (LONGLONG)ts.tv_nsec ;
217217 }
218218#elif HAVE_MACH_ABSOLUTE_TIME
@@ -233,22 +233,22 @@ QueryPerformanceCounter(
233233 retval = FALSE ;
234234 break ;
235235 }
236- lpPerformanceCount->QuadPart =
236+ lpPerformanceCount->QuadPart =
237237 (LONGLONG)tb.tb_high * (LONGLONG)tccSecondsToNanoSeconds + (LONGLONG)tb.tb_low ;
238238 }
239239#else
240240 {
241- struct timeval tv;
241+ struct timeval tv;
242242 if (gettimeofday (&tv, NULL ) == -1 )
243243 {
244244 ASSERT (" gettimeofday() failed; errno is %d (%s)\n " , errno, strerror (errno));
245245 retval = FALSE ;
246246 break ;
247247 }
248- lpPerformanceCount->QuadPart =
249- (LONGLONG)tv.tv_sec * (LONGLONG)tccSecondsToMicroSeconds + (LONGLONG)tv.tv_usec ;
248+ lpPerformanceCount->QuadPart =
249+ (LONGLONG)tv.tv_sec * (LONGLONG)tccSecondsToMicroSeconds + (LONGLONG)tv.tv_usec ;
250250 }
251- #endif // HAVE_CLOCK_MONOTONIC
251+ #endif // HAVE_CLOCK_MONOTONIC
252252 while (false );
253253
254254 LOGEXIT (" QueryPerformanceCounter\n " );
@@ -280,7 +280,7 @@ QueryPerformanceFrequency(
280280 }
281281#else
282282 lpFrequency->QuadPart = (LONGLONG)tccSecondsToMicroSeconds;
283- #endif // HAVE_GETHRTIME || HAVE_READ_REAL_TIME || HAVE_CLOCK_MONOTONIC
283+ #endif // HAVE_GETHRTIME || HAVE_READ_REAL_TIME || HAVE_CLOCK_MONOTONIC
284284 LOGEXIT (" QueryPerformanceFrequency\n " );
285285 PERF_EXIT (QueryPerformanceFrequency);
286286 return retval;
@@ -324,24 +324,52 @@ QueryThreadCycleTime(
324324 return retval;
325325}
326326
327- /* ++
328- Function:
329- GetTickCount64
327+ #if defined(_X86_) || defined(__AMD64__)
328+ inline size_t rdtsc ()
329+ {
330+ uint32_t H, L;
331+ __asm volatile (" rdtsc" :" =a" (L), " =d" (H));
332+ #ifdef _X86_
333+ return L;
334+ #else
335+ return ((size_t )H << 32 ) | L;
336+ #endif
337+ }
330338
331- Returns a 64-bit tick count with a millisecond resolution. It tries its best
332- to return monotonically increasing counts and avoid being affected by changes
333- to the system clock (either due to drift or due to explicit changes to system
334- time).
335- --*/
336- PALAPI
337- ULONGLONG
338- GetTickCount64 ()
339+ static double CPUFreq ()
340+ {
341+ struct timeval tstart, tend;
342+ size_t start, end;
343+
344+ struct timezone tzone;
345+ memset (&tzone, 0 , sizeof (tzone));
346+
347+ start = rdtsc ();
348+ gettimeofday (&tstart, &tzone);
349+
350+ usleep (1000 ); // 1ms
351+
352+ end = rdtsc ();
353+ gettimeofday (&tend, &tzone);
354+
355+ size_t usec = ((tend.tv_sec - tstart.tv_sec )*1e6 )
356+ + (tend.tv_usec - tstart.tv_usec );
357+
358+ if (!usec) return 0 ;
359+ return (end - start) / usec;
360+ }
361+
362+ static uint32_t cpu_speed = CPUFreq() * 1e3 ; // 1000 + 1e6 => ns to ms
363+ #endif
364+
365+ static ULONGLONG
366+ GetTickCount64Fallback ()
339367{
340368 ULONGLONG retval = 0 ;
341369
342370#if HAVE_CLOCK_MONOTONIC_COARSE || HAVE_CLOCK_MONOTONIC
343371 {
344- clockid_t clockType =
372+ clockid_t clockType =
345373#if HAVE_CLOCK_MONOTONIC_COARSE
346374 CLOCK_MONOTONIC_COARSE; // good enough resolution, fastest speed
347375#else
@@ -382,16 +410,34 @@ GetTickCount64()
382410 }
383411#else
384412 {
385- struct timeval tv;
413+ struct timeval tv;
386414 if (gettimeofday (&tv, NULL ) == -1 )
387415 {
388416 ASSERT (" gettimeofday() failed; errno is %d (%s)\n " , errno, strerror (errno));
389417 goto EXIT;
390418 }
391419 retval = (tv.tv_sec * tccSecondsToMillieSeconds) + (tv.tv_usec / tccMillieSecondsToMicroSeconds);
392420 }
393- #endif // HAVE_CLOCK_MONOTONIC
394- EXIT:
421+ #endif // HAVE_CLOCK_MONOTONIC
422+ EXIT:
395423 return retval;
396424}
425+ /* ++
426+ Function:
427+ GetTickCount64
397428
429+ Returns a 64-bit tick count with a millisecond resolution. It tries its best
430+ to return monotonically increasing counts and avoid being affected by changes
431+ to the system clock (either due to drift or due to explicit changes to system
432+ time).
433+ --*/
434+ PALAPI
435+ ULONGLONG
436+ GetTickCount64 ()
437+ {
438+ #if defined(_X86_) || defined(__AMD64__)
439+ return cpu_speed ? (rdtsc () / cpu_speed) : GetTickCount64Fallback ();
440+ #else
441+ return GetTickCount64Fallback ();
442+ #endif
443+ }
0 commit comments