1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
7 #include "cycletimer.h"
13 bool CycleTimer::GetThreadCyclesS(unsigned __int64* cycles)
16 res = QueryThreadCycleTime(GetCurrentThread(), cycles);
20 static const int SampleLoopSize = 1000000;
23 double CycleTimer::CyclesPerSecond()
25 // Windows does not provide a way of converting cycles to time -- reasonably enough,
26 // since the frequency of a machine may vary, due, e.g., to power management.
27 // Windows *does* allow you to translate QueryPerformanceCounter counts into time,
28 // however. So we'll assume that the clock speed stayed constant, and measure both the
29 // QPC counts and cycles of a short loop, to get a conversion factor.
30 LARGE_INTEGER lpFrequency;
31 if (!QueryPerformanceFrequency(&lpFrequency)) return 0.0;
33 LARGE_INTEGER qpcStart;
34 unsigned __int64 cycleStart;
35 if (!QueryPerformanceCounter(&qpcStart)) return 0.0;
36 if (!GetThreadCyclesS(&cycleStart)) return 0.0;
38 for (int k = 0; k < SampleLoopSize; k++)
43 if (!QueryPerformanceCounter(&qpcEnd)) return 0.0;
44 unsigned __int64 cycleEnd;
45 if (!GetThreadCyclesS(&cycleEnd)) return 0.0;
47 double qpcTicks = ((double)qpcEnd.QuadPart) - ((double)qpcStart.QuadPart);
48 double secs = (qpcTicks / ((double)lpFrequency.QuadPart));
49 double cycles = ((double)cycleEnd) - ((double)cycleStart);
54 unsigned __int64 CycleTimer::QueryOverhead()
56 unsigned __int64 tot = 0;
57 unsigned __int64 startCycles;
58 unsigned __int64 endCycles;
60 bool b = GetThreadCyclesS(&startCycles); assert(b);
61 for (int i = 0; i < N; i++)
63 b = GetThreadCyclesS(&endCycles); assert(b);
64 tot += (endCycles-startCycles);
65 startCycles = endCycles;
71 void CycleTimer::InterlockedAddU64(unsigned __int64* loc, unsigned __int64 amount)
73 volatile __int64* vloc = (volatile __int64*)loc;
74 unsigned __int64 prev = *vloc;
77 unsigned __int64 next = prev + amount;
78 __int64 snext = (__int64)next;
79 __int64 sprev = (__int64)prev;
80 __int64 res = InterlockedCompareExchange64(vloc, snext, sprev);
81 if (res == sprev) return;
82 else prev = (unsigned __int64)res;