Skip to content

Commit b5f8936

Browse files
committed
update tests on windows
1 parent 7afa749 commit b5f8936

3 files changed

Lines changed: 101 additions & 5 deletions

File tree

src/prim/windows/prim.c

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,96 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
746746
}
747747

748748

749-
#if defined(MI_SHARED_LIB)
749+
#if 1 /* we use a combination of _pRawDllMain and TLS init/fini for both static and dynamic linkage */
750+
#define MI_PRIM_HAS_PROCESS_ATTACH 1
751+
// nothing to do since `_mi_thread_done` is handled through the DLL_THREAD_DETACH event.
752+
void _mi_prim_thread_init_auto_done(void) {}
753+
void _mi_prim_thread_done_auto_done(void) {}
754+
void _mi_prim_thread_associate_default_theap(mi_theap_t* theap) {
755+
MI_UNUSED(theap);
756+
}
757+
758+
// If linked into a DLL module, this raw entry is called before the CRT attach and
759+
// after the CRT detach through the CRT _pRawDllMain pointer.
760+
static BOOL NTAPI mi_dll_main_raw(PVOID module, DWORD reason, LPVOID reserved) {
761+
//if (reason == DLL_PROCESS_ATTACH) { mi_debug_out("dll process attach\n"); }
762+
//else if (reason == DLL_PROCESS_DETACH) { mi_debug_out("dll process detach\n"); }
763+
//else if (reason == DLL_THREAD_ATTACH) { mi_debug_out("dll thread attach\n"); }
764+
//else if (reason == DLL_THREAD_DETACH) { mi_debug_out("dll thread detach\n"); }
765+
mi_win_main(module, reason, reserved);
766+
return TRUE;
767+
}
768+
769+
// Set the value of the CRT _pRawDllMain pointer
770+
#if defined(__cplusplus)
771+
extern "C"
772+
#endif
773+
PVOID _pRawDllMain = &mi_dll_main_raw;
774+
775+
// We also hook into the Windows loader TLS initialization and finalization.
776+
// If we are linked into an EXE module we rely on these as `mi_dll_main_raw`
777+
// is not called (and otherwise we ignore the TLS callbacks by checking if we are in a DLL).
778+
static bool mi_module_is_dll(PVOID mod) {
779+
if (mod==NULL) return false;
780+
PIMAGE_DOS_HEADER imageDosHeader = (PIMAGE_DOS_HEADER)mod;
781+
PIMAGE_NT_HEADERS imageNtHeaders = (PIMAGE_NT_HEADERS)((unsigned char*)imageDosHeader + imageDosHeader->e_lfanew);
782+
return ((imageNtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL);
783+
}
784+
785+
static void NTAPI mi_tls_attach(PVOID module, DWORD reason, LPVOID reserved) {
786+
if (reason == DLL_PROCESS_ATTACH || reason == DLL_THREAD_ATTACH) {
787+
if (!mi_module_is_dll(module)) {
788+
// mi_debug_out(reason==DLL_PROCESS_ATTACH ? "exe process attach\n" : "exe thread attach\n");
789+
mi_win_main(module, reason, reserved);
790+
}
791+
}
792+
}
793+
static void NTAPI mi_tls_detach(PVOID module, DWORD reason, LPVOID reserved) {
794+
if (reason == DLL_PROCESS_DETACH || reason == DLL_THREAD_DETACH) {
795+
if (!mi_module_is_dll(module)) {
796+
// mi_debug_out(reason==DLL_PROCESS_DETACH ? "exe process detach\n" : "exe thread detach\n");
797+
mi_win_main(module, reason, reserved);
798+
}
799+
}
800+
}
801+
802+
// Set up TLS callbacks in a statically linked library by using special data sections.
803+
// See <https://stackoverflow.com/questions/14538159/tls-callback-in-windows>
804+
// We use 2 entries to ensure we call attach events before constructors
805+
// are called, and detach events after destructors are called.
806+
#if defined(__cplusplus)
807+
extern "C" {
808+
#endif
809+
810+
#if defined(_WIN64)
811+
#pragma comment(linker, "/INCLUDE:_tls_used")
812+
#pragma comment(linker, "/INCLUDE:_mi_tls_callback_pre")
813+
#pragma comment(linker, "/INCLUDE:_mi_tls_callback_post")
814+
#pragma const_seg(".CRT$XLB")
815+
extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[];
816+
const PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[] = { &mi_tls_attach };
817+
#pragma const_seg()
818+
#pragma const_seg(".CRT$XLY")
819+
extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_post[];
820+
const PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_tls_detach };
821+
#pragma const_seg()
822+
#else
823+
#pragma comment(linker, "/INCLUDE:__tls_used")
824+
#pragma comment(linker, "/INCLUDE:__mi_tls_callback_pre")
825+
#pragma comment(linker, "/INCLUDE:__mi_tls_callback_post")
826+
#pragma data_seg(".CRT$XLB")
827+
PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[] = { &mi_tls_attach };
828+
#pragma data_seg()
829+
#pragma data_seg(".CRT$XIY")
830+
PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_tls_detach };
831+
#pragma data_seg()
832+
#endif
833+
834+
#if defined(__cplusplus)
835+
}
836+
#endif
837+
838+
#elif defined(MI_SHARED_LIB)
750839
#define MI_PRIM_HAS_PROCESS_ATTACH 1
751840

752841
// Windows DLL: easy to hook into process_init and thread_done
@@ -775,7 +864,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
775864
mi_win_main(module, reason, reserved);
776865
}
777866
}
778-
867+
779868
// Set up TLS callbacks in a statically linked library by using special data sections.
780869
// See <https://stackoverflow.com/questions/14538159/tls-callback-in-windows>
781870
// We use 2 entries to ensure we call attach events before constructors
@@ -795,15 +884,15 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
795884
#pragma const_seg(".CRT$XLY")
796885
extern const PIMAGE_TLS_CALLBACK _mi_tls_callback_post[];
797886
const PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_win_main_detach };
798-
#pragma const_seg()
887+
#pragma const_seg()
799888
#else
800889
#pragma comment(linker, "/INCLUDE:__tls_used")
801890
#pragma comment(linker, "/INCLUDE:__mi_tls_callback_pre")
802891
#pragma comment(linker, "/INCLUDE:__mi_tls_callback_post")
803892
#pragma data_seg(".CRT$XLB")
804893
PIMAGE_TLS_CALLBACK _mi_tls_callback_pre[] = { &mi_win_main_attach };
805894
#pragma data_seg()
806-
#pragma data_seg(".CRT$XLY")
895+
#pragma data_seg(".CRT$XIY")
807896
PIMAGE_TLS_CALLBACK _mi_tls_callback_post[] = { &mi_win_main_detach };
808897
#pragma data_seg()
809898
#endif
@@ -903,6 +992,7 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
903992
mi_redirected = false;
904993
}
905994
else if (reason == DLL_THREAD_DETACH) {
995+
// mi_debug_out("redirect thread detach\n");
906996
_mi_thread_done(NULL);
907997
}
908998
}

test/main-override-static.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ static void test_manage_os_memory(void) {
287287

288288
#if _WIN32
289289

290-
static void test_dep(void) {
290+
static void call_library(void) {
291291
HMODULE dll = LoadLibraryA("mimalloc-test-static-dep.dll");
292292
if (dll != NULL) {
293293
TestFun fun = (TestFun)GetProcAddress(dll, "Test");
@@ -297,6 +297,11 @@ static void test_dep(void) {
297297
bool ok = FreeLibrary(dll);
298298
}
299299
}
300+
301+
static void test_dep(void) {
302+
call_library();
303+
call_library();
304+
}
300305
#endif
301306

302307
// Experiment with huge OS pages

test/main-static-dep.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID reserved) {
3939
printf("static-dep: dll attach\n");
4040
}
4141
else if (reason==DLL_PROCESS_DETACH) {
42+
mi_option_enable(mi_option_destroy_on_exit);
4243
printf("static-dep: dll detach\n");
4344
}
4445
return TRUE;

0 commit comments

Comments
 (0)