Skip to content

Commit 485fa08

Browse files
committed
Time::HiRes Win32, unwrap jump stubs from GetSystemTimeAsFileTime()
-if possible, wont work < NT6.0, but if we get the kernelbase fn ptr on a sys with kernelbase, then we were successful at removing 2 stubs inside kernel32.dll and going straight to real impl inside kernelbase.dll. On older OSes they use their real impl inside k32.dll like before,
1 parent 80a5909 commit 485fa08

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

dist/Time-HiRes/HiRes.xs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,14 @@ typedef struct {
321321
} my_cxt_t;
322322

323323
typedef BOOL (WINAPI *pfnQueryPerformanceCounter_T)(LARGE_INTEGER*);
324+
typedef VOID (WINAPI *pfnGetSystemTimeAsFileTime_T) (PFILETIME);
324325

325326
static unsigned __int64 tick_frequency = 0;
326327
static NV tick_frequency_nv = 0;
327328
static unsigned __int64 qpc_res_ns = 0;
328329
static unsigned __int64 qpc_res_ns_realtime = 0;
329330
static pfnQueryPerformanceCounter_T pfnQueryPerformanceCounter = NULL;
331+
static pfnGetSystemTimeAsFileTime_T pfnGetSystemTimeAsFileTime = NULL;
330332

331333
#define S_InterlockedExchange64(_d,_s) \
332334
InterlockedExchange64((LONG64 volatile *)(_d),(LONG64)(_s))
@@ -335,6 +337,8 @@ static pfnQueryPerformanceCounter_T pfnQueryPerformanceCounter = NULL;
335337

336338
#undef QueryPerformanceCounter
337339
#define QueryPerformanceCounter pfnQueryPerformanceCounter
340+
#undef GetSystemTimeAsFileTime
341+
#define GetSystemTimeAsFileTime pfnGetSystemTimeAsFileTime
338342

339343
/* Visual C++ 2013 and older don't have the timespec structure.
340344
* Neither do mingw.org compilers with MinGW runtimes older than 3.22. */
@@ -1311,6 +1315,24 @@ BOOT:
13111315
S_InterlockedExchangePointer(&pfnQueryPerformanceCounter, QPCfn);
13121316
}
13131317
}
1318+
{/* Remove 2 jump stub funcs between kernel32->kernelbase for perf reasons.
1319+
kernelbase.dll is somewhat new to the Win32/NT OS, so keep the fallback. */
1320+
pfnGetSystemTimeAsFileTime_T GSTAFTfn = pfnGetSystemTimeAsFileTime;
1321+
if (!GSTAFTfn) {
1322+
HMODULE hmod = GetModuleHandleW(L"KERNELBASE.DLL");
1323+
if (hmod) {
1324+
GSTAFTfn = (pfnGetSystemTimeAsFileTime_T)GetProcAddress(hmod,"GetSystemTimeAsFileTime");
1325+
if (GSTAFTfn)
1326+
goto GSTAFT_done;
1327+
}
1328+
#undef GetSystemTimeAsFileTime
1329+
GSTAFTfn = GetSystemTimeAsFileTime; /* Get the public API fallback sym. */
1330+
#undef GetSystemTimeAsFileTime
1331+
#GetSystemTimeAsFileTime pfnGetSystemTimeAsFileTime
1332+
GSTAFT_done:
1333+
S_InterlockedExchangePointer(&pfnGetSystemTimeAsFileTime, GSTAFTfn);
1334+
}
1335+
}
13141336
}
13151337
#endif
13161338
#ifdef HAS_GETTIMEOFDAY

0 commit comments

Comments
 (0)