Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Unity-Technologies/bdwgc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--win32_threads.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/win32_threads.c b/win32_threads.c
index 650fe815..c04ff765 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -352,8 +352,8 @@ STATIC volatile LONG GC_max_thread_index = 0;
STATIC GC_thread GC_threads[THREAD_TABLE_SZ];
/* It may not be safe to allocate when we register the first thread. */
-/* Thus we allocated one statically. It does not contain any field we */
-/* need to push ("next" and "status" fields are unused). */
+/* Thus we allocated one statically. It does not contain any pointer */
+/* field we need to push ("next" and "status" fields are unused). */
static struct GC_Thread_Rep first_thread;
static GC_bool first_thread_used = FALSE;
@@ -693,6 +693,9 @@ STATIC void GC_delete_gc_thread_no_free(GC_vthread t)
/* see GC_stop_world() for the information. */
t -> stack_base = 0;
t -> id = 0;
+# ifdef RETRY_GET_THREAD_CONTEXT
+ t -> context_sp = NULL;
+# endif
AO_store_release(&t->tm.in_use, FALSE);
} else
# endif
@@ -1509,20 +1512,36 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me)
/* require looping. */
word *regs = thread->context_regs;
- GC_ASSERT(thread->suspended);
- sp = thread->context_sp;
+ if (thread->suspended) {
+ sp = thread->context_sp;
+ } else
# else
- /* For unblocked threads call GetThreadContext(). */
word regs[PUSHED_REGS_COUNT];
- {
+# endif
+
+ /* else */ {
CONTEXT context;
- GC_ASSERT(thread->suspended);
+ /* For unblocked threads call GetThreadContext(). */
context.ContextFlags = GET_THREAD_CONTEXT_FLAGS;
- if (!GetThreadContext(THREAD_HANDLE(thread), &context))
- ABORT("GetThreadContext failed");
- sp = copy_ptr_regs(regs, &context);
+ if (GetThreadContext(THREAD_HANDLE(thread), &context)) {
+ sp = copy_ptr_regs(regs, &context);
+ } else {
+# ifdef RETRY_GET_THREAD_CONTEXT
+ /* At least, try to use the stale context if saved. */
+ sp = thread->context_sp;
+ if (NULL == sp) {
+ /* Skip the current thread, anyway its stack will */
+ /* be pushed when the world is stopped. */
+ return 0;
+ }
+# else
+ ABORT("GetThreadContext failed");
+# endif
+ }
}
+# ifdef THREAD_LOCAL_ALLOC
+ GC_ASSERT(thread->suspended || !GC_world_stopped);
# endif
# ifdef WOW64_THREAD_CONTEXT_WORKAROUND
@@ -1670,6 +1689,8 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me)
return thread->stack_base - sp; /* stack grows down */
}
+/* We hold allocation lock. Should do exactly the right thing if the */
+/* world is stopped. Should not fail if it isn't. */
GC_INNER void GC_push_all_stacks(void)
{
DWORD thread_id = GetCurrentThreadId();