diff --git a/mcfgthread/clock.c b/mcfgthread/clock.c index 735d32790..9e830880f 100644 --- a/mcfgthread/clock.c +++ b/mcfgthread/clock.c @@ -42,10 +42,10 @@ __MCF_DLLEXPORT double _MCF_hires_utc_now(void) { - if(__MCF_LAZY_P(GetSystemTimePreciseAsFileTime)) { + if(__MCF_G_HAS_LAZY(GetSystemTimePreciseAsFileTime)) { /* This is available since Windows 8. */ ULONGLONG ull; - __MCF_LAZY_REF(GetSystemTimePreciseAsFileTime) ((FILETIME*) &ull); + __MCF_G_LAZY(GetSystemTimePreciseAsFileTime) ((FILETIME*) &ull); return (double) ((int64_t) ull - 116444736000000000) * 0.0001; } @@ -62,10 +62,10 @@ __MCF_DLLEXPORT int64_t _MCF_tick_count(void) { - if(__MCF_LAZY_P(QueryInterruptTime)) { + if(__MCF_G_HAS_LAZY(QueryInterruptTime)) { /* This is available since Windows 10. */ ULONGLONG ull; - __MCF_LAZY_REF(QueryInterruptTime) (&ull); + __MCF_G_LAZY(QueryInterruptTime) (&ull); return (int64_t) do_divide_by_10000(ull); } diff --git a/mcfgthread/xglobals.c b/mcfgthread/xglobals.c index 359e4ec0a..e283a0b5b 100644 --- a/mcfgthread/xglobals.c +++ b/mcfgthread/xglobals.c @@ -177,8 +177,8 @@ __MCF_gthread_initialize_globals(void) __MCF_CHECK(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"KERNELBASE.DLL", &__MCF_crt_kernelbase)); __MCF_CHECK(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"NTDLL.DLL", &__MCF_crt_ntdll)); - FARPROC dllfn = GetProcAddress(__MCF_crt_kernelbase, "TlsGetValue2"); - __MCF_crt_TlsGetValue = dllfn ? __MCF_CAST_PTR(decltype_TlsGetValue, dllfn) : TlsGetValue; + __MCF_crt_TlsGetValue = TlsGetValue; + __MCF_LAZY_LOAD(&__MCF_crt_TlsGetValue, __MCF_crt_kernelbase, TlsGetValue2); /* Generate the unique name for this process. */ static WCHAR gnbuffer[] = L"Local\\__MCF_crt_xglobals_*?pid???_#?cookie????????"; @@ -226,8 +226,8 @@ __MCF_gthread_initialize_globals(void) __MCF_CHECK(__MCF_g->__tls_index != UINT32_MAX); /* Perform lazy binding for newer functions. */ - __MCF_G_INITIALIZE_LAZY(__MCF_crt_kernelbase, GetSystemTimePreciseAsFileTime); /* win8 */ - __MCF_G_INITIALIZE_LAZY(__MCF_crt_kernelbase, QueryInterruptTime); /* win10 */ + __MCF_G_SET_LAZY(__MCF_crt_kernelbase, GetSystemTimePreciseAsFileTime); /* win8 */ + __MCF_G_SET_LAZY(__MCF_crt_kernelbase, QueryInterruptTime); /* win10 */ /* Attach the main thread. The structure should be all zeroes so no * initialization is necessary. */ @@ -368,7 +368,7 @@ double __MCF_crt_pf_recip = 1; SYSTEM_INFO __MCF_crt_sysinfo = { .dwPageSize = 1 }; HMODULE __MCF_crt_kernelbase = __MCF_BAD_PTR; HMODULE __MCF_crt_ntdll = __MCF_BAD_PTR; -decltype_TlsGetValue* __MCF_crt_TlsGetValue = __MCF_BAD_PTR; +decltype_TlsGetValue2* __MCF_crt_TlsGetValue = __MCF_BAD_PTR; /* This is a pointer to global data. If this library is linked statically, * all instances of this pointer in the same process should point to the diff --git a/mcfgthread/xglobals.h b/mcfgthread/xglobals.h index 443f29a4e..57800c9bf 100644 --- a/mcfgthread/xglobals.h +++ b/mcfgthread/xglobals.h @@ -80,13 +80,20 @@ NTSYSAPI ULONG NTAPI RtlNtStatusToDosErrorNoTeb(NTSTATUS status) __MCF_FN_CONST; .Buffer = (void*) ((s) + __MCF_STATIC_ASSERT_0( \ !__builtin_types_compatible_p(__typeof__(1+&*(s)), __typeof__(s)))) } -/* Define macros and types for lazy binding. - * If a symbol cannot be found during startup, it is set to a null pointer. */ -#define __MCF_G_LAZY_FIELD(name) decltype_##name* __f_##name - +/* Define macros and types for lazy binding. If a symbol cannot be found + * during process startup, it shall be initialized to a null pointer. */ typedef void __stdcall decltype_GetSystemTimePreciseAsFileTime(FILETIME*); typedef void __stdcall decltype_QueryInterruptTime(ULONGLONG*); -typedef LPVOID __stdcall decltype_TlsGetValue(ULONG); +typedef LPVOID __stdcall decltype_TlsGetValue2(ULONG); + +#define __MCF_LAZY_D_(name) decltype_##name* __f_##name +#define __MCF_LAZY_P_(name) __f_##name + +#define __MCF_LAZY_LOAD(out, dll, name) \ + ({ decltype_##name* __temp1 = __MCF_nullptr; \ + if(dll) __temp1 = __MCF_CAST_PTR(decltype_##name, GetProcAddress(dll, #name)); \ + if(__temp1) *(out) = __temp1; \ + __temp1; }) /* Declare helper functions here. */ typedef struct __MCF_seh_i386_node __MCF_seh_i386_node; @@ -301,8 +308,8 @@ struct __MCF_crt_xglobals _MCF_cond __interrupt_cond[1]; /* WARNING: Fields hereinafter must be accessed via `__MCF_G_FIELD_OPT`! */ - __MCF_G_LAZY_FIELD(GetSystemTimePreciseAsFileTime); - __MCF_G_LAZY_FIELD(QueryInterruptTime); + __MCF_LAZY_D_(GetSystemTimePreciseAsFileTime); + __MCF_LAZY_D_(QueryInterruptTime); _MCF_mutex __thread_oom_mtx[1]; _MCF_thread __thread_oom_self_st; }; @@ -313,7 +320,7 @@ extern HANDLE __MCF_XGLOBALS_READONLY __MCF_crt_heap; extern double __MCF_XGLOBALS_READONLY __MCF_crt_pf_recip; extern HMODULE __MCF_XGLOBALS_READONLY __MCF_crt_kernelbase; extern HMODULE __MCF_XGLOBALS_READONLY __MCF_crt_ntdll; -extern decltype_TlsGetValue* __MCF_XGLOBALS_READONLY __MCF_crt_TlsGetValue; +extern decltype_TlsGetValue2* __MCF_XGLOBALS_READONLY __MCF_crt_TlsGetValue; /* This is a pointer to the process-specific data. * As mcfgthread may be linked statically by user DLLs, we must ensure that, in @@ -326,21 +333,14 @@ extern __MCF_crt_xglobals* __MCF_XGLOBALS_READONLY restrict __MCF_g; /* As `__MCF_crt_xglobals` is shared between all static and shared instances of * this library within a single process, we have to involve sort of versioning. */ -#define __MCF_G_SIZE \ - ((uint32_t) __builtin_expect((long) __MCF_g->__self_size, sizeof(__MCF_crt_xglobals))) - #define __MCF_G_FIELD_OPT(field) \ - ((__MCF_G_SIZE >= offsetof(__MCF_crt_xglobals, field) + sizeof(__MCF_g->field)) \ + ((__MCF_g->__self_size >= offsetof(__MCF_crt_xglobals, field) + sizeof(__MCF_g->field)) \ ? &(__MCF_g->field) \ : __MCF_nullptr) -#define __MCF_G_INITIALIZE_LAZY(dll, name) \ - (__MCF_g->__f_##name = \ - (dll) ? __MCF_CAST_PTR(decltype_##name, GetProcAddress(dll, #name)) \ - : __MCF_nullptr) - -#define __MCF_LAZY_P(name) (__MCF_G_FIELD_OPT(__f_##name) && __MCF_g->__f_##name) -#define __MCF_LAZY_REF(name) (*(__MCF_g->__f_##name)) +#define __MCF_G_HAS_LAZY(name) (__MCF_G_FIELD_OPT(__MCF_LAZY_P_(name)) && __MCF_g->__MCF_LAZY_P_(name)) +#define __MCF_G_LAZY(name) (*(__MCF_g->__MCF_LAZY_P_(name))) +#define __MCF_G_SET_LAZY(dll, name) __MCF_LAZY_LOAD(&(__MCF_g->__MCF_LAZY_P_(name)), dll, name) /* Define inline functions after all declarations. * We would like to keep them away from declarations for conciseness, which also