diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-11-01 23:15:51 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-11-01 23:15:51 +0000 |
commit | 9bc8642e1f366a35c305b9abe9e01bf934b584b9 (patch) | |
tree | 9c24ba1ebabff472b9caddbff07ef957dbf2c24c /boehm-gc/win32_threads.c | |
parent | 79eaf784f16b0e8079d9dca062a0fc959d289d18 (diff) | |
download | gcc-9bc8642e1f366a35c305b9abe9e01bf934b584b9.tar.gz |
Merged GC 5.0alpha4 with local changes, plus:
* Makefile.in: Rebuilt.
* Makefile.am (gctest_LDADD): Added THREADLIB.
(TESTS): New macro.
* configure: Rebuilt.
* configure.in (INCLUDES): New subst.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30332 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'boehm-gc/win32_threads.c')
-rw-r--r-- | boehm-gc/win32_threads.c | 61 |
1 files changed, 51 insertions, 10 deletions
diff --git a/boehm-gc/win32_threads.c b/boehm-gc/win32_threads.c index eb485bdc064..f6f74bd1111 100644 --- a/boehm-gc/win32_threads.c +++ b/boehm-gc/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() @@ -78,6 +91,12 @@ void GC_push_all_stacks() if (thread_table[i].context.Esp >= (DWORD)thread_table[i].stack || thread_table[i].context.Esp < (DWORD)bottom) ABORT("Thread stack pointer out of range"); + GC_push_one ((word) thread_table[i].context.Edi); + GC_push_one ((word) thread_table[i].context.Esi); + GC_push_one ((word) thread_table[i].context.Ebx); + GC_push_one ((word) thread_table[i].context.Edx); + GC_push_one ((word) thread_table[i].context.Ecx); + GC_push_one ((word) thread_table[i].context.Eax); GC_push_all_stack(thread_table[i].context.Esp, thread_table[i].stack); } } @@ -117,20 +136,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 +176,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 +189,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(); |