summaryrefslogtreecommitdiff
path: root/win32_threads.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2012-02-21 18:12:47 +0100
committerIvan Maidanski <ivmai@mail.ru>2012-02-21 18:35:53 +0100
commit6b6db24da3a71f26e4efc6c5b7a9b2efe129c43c (patch)
treec5ee07b2ca9e7642675b29b67d21e7bee19cf7bd /win32_threads.c
parent68756f05b1e4a22f79f68a62eec27fb2b395718c (diff)
Fix Win32 GC_unregister_my_thread to ensure no ongoing incremental GC
* win32_threads.c (GC_wait_for_gc_completion): Add function (similar implementation as in pthread_support.c). * win32_threads.c (GC_unregister_my_thread, GC_thread_exit_proc): Call GC_wait_for_gc_completion to prevent collecting from unregistered thread; remove FIXME.
Diffstat (limited to 'win32_threads.c')
-rw-r--r--win32_threads.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/win32_threads.c b/win32_threads.c
index ca9976e..e6a2002 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -744,6 +744,30 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
}
}
+/* Similar to that in pthread_support.c (wait_for_all is always FALSE). */
+STATIC void GC_wait_for_gc_completion(void)
+{
+ GC_ASSERT(I_HOLD_LOCK());
+ if (GC_incremental && GC_collection_in_progress()) {
+ word old_gc_no = GC_gc_no;
+
+ /* Make sure that no part of our stack is still on the mark stack, */
+ /* since it's about to be unmapped. */
+ do {
+ ENTER_GC();
+ GC_in_thread_creation = TRUE;
+ GC_collect_a_little_inner(1);
+ GC_in_thread_creation = FALSE;
+ EXIT_GC();
+
+ UNLOCK();
+ Sleep(0); /* yield */
+ LOCK();
+ } while (GC_incremental && GC_collection_in_progress()
+ && old_gc_no == GC_gc_no);
+ }
+}
+
GC_API int GC_CALL GC_unregister_my_thread(void)
{
DCL_LOCK_STATE;
@@ -752,7 +776,6 @@ GC_API int GC_CALL GC_unregister_my_thread(void)
GC_log_printf("Unregistering thread 0x%lx\n", (long)GetCurrentThreadId());
# endif
- /* FIXME: is GC_wait_for_gc_completion(FALSE) needed here? */
if (GC_win32_dll_threads) {
# if defined(THREAD_LOCAL_ALLOC)
/* Can't happen: see GC_use_threads_discovery(). */
@@ -771,6 +794,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void)
DWORD thread_id = GetCurrentThreadId();
LOCK();
+ GC_wait_for_gc_completion();
# if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS)
me = GC_lookup_thread_inner(thread_id);
CHECK_LOOKUP_MY_THREAD(me);
@@ -2512,6 +2536,7 @@ GC_INNER void GC_thr_init(void)
# endif
LOCK();
+ GC_wait_for_gc_completion();
# if defined(THREAD_LOCAL_ALLOC)
GC_destroy_thread_local(&(me->tlfs));
# endif