From: Ivan Maidanski Date: Thu, 3 Oct 2019 21:38:28 +0000 (+0300) Subject: Do not hold GC_fault_handler_lock when in Sleep (Win32) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47873be17352b194bfd42731531fcf6ee68e64dc;p=gc Do not hold GC_fault_handler_lock when in Sleep (Win32) (fix of commits 0c0e4cd0b, 449eda034) Also, reduce a period between GetExitCodeThread and SuspendThread. * win32_threads.c [DEBUG_THREADS] (GC_suspend): Call GC_log_printf() before UNPROTECT_THREAD(). * win32_threads.c [DEBUG_THREADS && !MSWINCE] (GC_suspend): Call GC_acquire_dirty_lock() before GetExitCodeThread(); call GC_release_dirty_lock() immediately if GetExitCodeThread() failed. * win32_threads.c [MSWINCE || RETRY_GET_THREAD_CONTEXT] (GC_suspend): Wrap Sleep() call with GC_release/acquire_dirty_lock(). --- diff --git a/win32_threads.c b/win32_threads.c index 6ac42a8c..7dfeeb8f 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -1276,11 +1276,17 @@ STATIC void GC_suspend(GC_thread t) # ifdef RETRY_GET_THREAD_CONTEXT int retry_cnt = 0; # define MAX_SUSPEND_THREAD_RETRIES (1000 * 1000) +# endif + +# ifdef DEBUG_THREADS + GC_log_printf("Suspending 0x%x\n", (int)t->id); # endif UNPROTECT_THREAD(t); + GC_acquire_dirty_lock(); # ifndef MSWINCE if (GetExitCodeThread(t -> handle, &exitCode) && exitCode != STILL_ACTIVE) { + GC_release_dirty_lock(); # ifdef GC_PTHREADS t -> stack_base = 0; /* prevent stack from being pushed */ # else @@ -1292,14 +1298,14 @@ STATIC void GC_suspend(GC_thread t) return; } # endif -# ifdef DEBUG_THREADS - GC_log_printf("Suspending 0x%x\n", (int)t->id); -# endif - GC_acquire_dirty_lock(); + # ifdef MSWINCE /* SuspendThread() will fail if thread is running kernel code. */ - while (SuspendThread(THREAD_HANDLE(t)) == (DWORD)-1) + while (SuspendThread(THREAD_HANDLE(t)) == (DWORD)-1) { + GC_release_dirty_lock(); Sleep(10); /* in millis */ + GC_acquire_dirty_lock(); + } # elif defined(RETRY_GET_THREAD_CONTEXT) for (;;) { if (SuspendThread(t->handle) != (DWORD)-1) { @@ -1317,8 +1323,11 @@ STATIC void GC_suspend(GC_thread t) if (ResumeThread(t->handle) == (DWORD)-1) ABORT("ResumeThread failed"); } - if (retry_cnt > 1) + if (retry_cnt > 1) { + GC_release_dirty_lock(); Sleep(0); /* yield */ + GC_acquire_dirty_lock(); + } if (++retry_cnt >= MAX_SUSPEND_THREAD_RETRIES) ABORT("SuspendThread loop failed"); /* something must be wrong */ }