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,14 @@ QueryThreadCycleTime(
324324 return retval;
325325}
326326
327- /* ++
328- Function:
329- GetTickCount64
330-
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 ()
327+ static ULONGLONG
328+ GetTickCount64Fallback ()
339329{
340330 ULONGLONG retval = 0 ;
341331
342332#if HAVE_CLOCK_MONOTONIC_COARSE || HAVE_CLOCK_MONOTONIC
343333 {
344- clockid_t clockType =
334+ clockid_t clockType =
345335#if HAVE_CLOCK_MONOTONIC_COARSE
346336 CLOCK_MONOTONIC_COARSE; // good enough resolution, fastest speed
347337#else
@@ -382,16 +372,79 @@ GetTickCount64()
382372 }
383373#else
384374 {
385- struct timeval tv;
375+ struct timeval tv;
386376 if (gettimeofday (&tv, NULL ) == -1 )
387377 {
388378 ASSERT (" gettimeofday() failed; errno is %d (%s)\n " , errno, strerror (errno));
389379 goto EXIT;
390380 }
391381 retval = (tv.tv_sec * tccSecondsToMillieSeconds) + (tv.tv_usec / tccMillieSecondsToMicroSeconds);
392382 }
393- #endif // HAVE_CLOCK_MONOTONIC
394- EXIT:
383+ #endif // HAVE_CLOCK_MONOTONIC
384+ EXIT:
395385 return retval;
396386}
397387
388+ #if defined(_X86_) || defined(__AMD64__) || defined(__x86_64__)
389+ inline ULONGLONG rdtsc ()
390+ {
391+ ULONGLONG H, L;
392+ __asm volatile (" rdtsc" :" =a" (L), " =d" (H));
393+ #ifdef _X86_
394+ return L;
395+ #else
396+ return (H << 32 ) | L;
397+ #endif
398+ }
399+
400+ static double CPUFreq ()
401+ {
402+ struct timeval tstart, tend;
403+ ULONGLONG start, end;
404+
405+ struct timezone tzone;
406+ memset (&tzone, 0 , sizeof (tzone));
407+
408+ start = rdtsc ();
409+ gettimeofday (&tstart, &tzone);
410+
411+ usleep (1000 ); // 1ms
412+
413+ end = rdtsc ();
414+ gettimeofday (&tend, &tzone);
415+
416+ ULONGLONG usec = ((tend.tv_sec - tstart.tv_sec )*1e6 )
417+ + (tend.tv_usec - tstart.tv_usec );
418+
419+ if (!usec) return 0 ;
420+ return (end - start) / usec;
421+ }
422+
423+ static ULONGLONG cpu_speed = CPUFreq() * 1e3 ; // 1000 * 1e6 => ns to ms
424+ typedef ULONGLONG (*GetTickCount64FallbackCB)(void );
425+ inline ULONGLONG FastTickCount ()
426+ {
427+ return rdtsc () / cpu_speed;
428+ }
429+ static GetTickCount64FallbackCB getTickCount64FallbackCB = cpu_speed ? FastTickCount : GetTickCount64Fallback;
430+ #endif
431+
432+ /* ++
433+ Function:
434+ GetTickCount64
435+
436+ Returns a 64-bit tick count with a millisecond resolution. It tries its best
437+ to return monotonically increasing counts and avoid being affected by changes
438+ to the system clock (either due to drift or due to explicit changes to system
439+ time).
440+ --*/
441+ PALAPI
442+ ULONGLONG
443+ GetTickCount64 ()
444+ {
445+ #if defined(_X86_) || defined(__AMD64__) || defined(__x86_64__)
446+ return getTickCount64FallbackCB ();
447+ #else
448+ return GetTickCount64Fallback ();
449+ #endif
450+ }
0 commit comments