diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2011-07-26 15:20:24 +0400 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-26 15:20:24 +0400 |
commit | c521d2cf164f9d7e1fa8be9c0b21d223e265fa64 (patch) | |
tree | 82fbd7e60e6be39fbabd946717cf065a698cd038 /win32_threads.c | |
parent | 7d3768dbd2a1cd4d5c14f773f23aec43bc0651a5 (diff) | |
download | bdwgc-c521d2cf164f9d7e1fa8be9c0b21d223e265fa64.tar.gz |
gc4.13 tarball importgc4_13
Diffstat (limited to 'win32_threads.c')
-rwxr-xr-x | win32_threads.c | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/win32_threads.c b/win32_threads.c index eb485bdc..2b01c5c6 100755 --- a/win32_threads.c +++ b/win32_threads.c @@ -8,22 +8,32 @@ #define MAX_THREADS 64 struct thread_entry { + LONG in_use; DWORD id; HANDLE handle; - void *stack; /* The cold end of the stack. */ + void *stack; /* The cold end of the stack. */ + /* 0 ==> entry not valid. */ + /* !in_use ==> stack == 0 */ CONTEXT context; + GC_bool suspended; }; -struct thread_entry thread_table[MAX_THREADS]; +volatile GC_bool GC_please_stop = FALSE; + +volatile struct thread_entry thread_table[MAX_THREADS]; void GC_stop_world() { DWORD thread_id = GetCurrentThreadId(); int i; + + GC_please_stop = TRUE; for (i = 0; i < MAX_THREADS; i++) - if (thread_table[i].stack != 0 && thread_table[i].id != thread_id) { + if (thread_table[i].stack != 0 + && thread_table[i].id != thread_id) { if (SuspendThread(thread_table[i].handle) == (DWORD)-1) ABORT("SuspendThread failed"); + thread_table[i].suspended = TRUE; } } @@ -32,10 +42,13 @@ void GC_start_world() DWORD thread_id = GetCurrentThreadId(); int i; for (i = 0; i < MAX_THREADS; i++) - if (thread_table[i].stack != 0 && thread_table[i].id != thread_id) { + if (thread_table[i].stack != 0 && thread_table[i].suspended + && thread_table[i].id != thread_id) { if (ResumeThread(thread_table[i].handle) == (DWORD)-1) ABORT("ResumeThread failed"); + thread_table[i].suspended = FALSE; } + GC_please_stop = FALSE; } ptr_t GC_current_stackbottom() @@ -117,20 +130,34 @@ BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) switch (reason) { case DLL_PROCESS_ATTACH: InitializeCriticalSection(&GC_allocate_ml); + GC_init(); /* Force initialization before thread attach. */ /* fall through */ case DLL_THREAD_ATTACH: { int i; - LOCK(); + /* It appears to be unsafe to acquire a lock here, since this */ + /* code is apparently not preeemptible on some systems. */ + /* (This is based on complaints, not on Microsoft's official */ + /* documentation, which says this should perform "only simple */ + /* inititalization tasks".) */ + /* Hence we make do with nonblocking synchronization. */ + /* The following should be a noop according to the win32 */ /* documentation. There is empirical evidence that it */ /* isn't. - HB */ - if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler); - for (i = 0; thread_table[i].stack != 0; i++) { +# ifndef SMALL_CONFIG + if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler); +# endif + + for (i = 0; InterlockedExchange(&thread_table[i].in_use,1) != 0; i++) { + /* Compare-and-swap would make this cleaner, but that's not */ + /* supported before Windows 98 and NT 4.0. In Windows 2000, */ + /* InterlockedExchange is supposed to be replaced by */ + /* InterlockedExchangePointer, but that's not really what I */ + /* want here. */ if (i == MAX_THREADS - 1) ABORT("too many threads"); } - thread_table[i].stack = GC_get_stack_base(); thread_table[i].id = GetCurrentThreadId(); if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), @@ -143,7 +170,11 @@ BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) GC_printf1("Last error code: %lx\n", last_error); ABORT("DuplicateHandle failed"); } - UNLOCK(); + thread_table[i].stack = GC_get_stack_base(); + /* If this thread is being created while we are trying to stop */ + /* the world, wait here. Hopefully this can't happen on any */ + /* systems that don't allow us to block here. */ + while (GC_please_stop) Sleep(20); } break; case DLL_PROCESS_DETACH: @@ -152,10 +183,14 @@ BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) int i; DWORD thread_id = GetCurrentThreadId(); LOCK(); - for (i = 0; thread_table[i].stack == 0 || thread_table[i].id != thread_id; i++) + for (i = 0; + thread_table[i].stack == 0 || thread_table[i].id != thread_id; + i++) { if (i == MAX_THREADS - 1) ABORT("thread not found on detach"); + } thread_table[i].stack = 0; + thread_table[i].in_use = FALSE; CloseHandle(thread_table[i].handle); BZERO(&thread_table[i].context, sizeof(CONTEXT)); UNLOCK(); |