From 7eb49a4e623cd6a73c595b077697702e345ce00a Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Sun, 11 Dec 2022 11:16:30 +0300 Subject: Move stack-related fields out of GC_thread to GC_stack_context_t (refactoring) Issue #362 (bdwgc). * darwin_stop_world.c (GC_stack_range_for): Define and crtn local variable; use crtn instead of p to access stack_ptr, topOfStack, stack_end, altstack, altstack_size, normstack, normstack_size, backing_store_end, backing_store_ptr. * pthread_stop_world.c [!NACL] (GC_suspend_handler_inner, GC_push_all_stacks): Likewise. * pthread_support.c [!GC_NO_FINALIZATION] (GC_reset_finalizer_nested, GC_check_finalizer_nested): Likewise. * pthread_support.c [!GC_WIN32_THREADS] (GC_register_altstack): Likewise. * pthread_support.c (do_blocking_enter, do_blocking_leave, GC_set_stackbottom, GC_get_my_stackbottom, GC_call_with_gc_active): Likewise. * win32_threads.c (GC_push_stack_for, GC_get_next_stack): Likewise. * darwin_stop_world.c (GC_push_all_stacks): Use p->crtn instead of p to access traced_stack_sect. * win32_threads.c (GC_suspend, GC_stop_world, GC_start_world): Likewise. * include/private/pthread_support.h (GC_StackContext_Rep): New struct type (move dummy, stack_end, stack_ptr, last_stack_min, initial_stack_base, topOfStack, backing_store_end, backing_store_ptr, altstack, altstack_size, normstack, normstack_size, finalizer_nested, finalizer_skipped, traced_stack_sect from GC_Thread_Rep). * include/private/pthread_support.h [!GC_NO_THREADS_DISCOVERY && GC_WIN32_THREADS] (GC_StackContext_Rep.stack_end): Add volatile. * include/private/pthread_support.h [!GC_NO_FINALIZATION] (GC_StackContext_Rep.fnlz_pad): New field. * include/private/pthread_support.h (GC_stack_context_t): New type. * include/private/pthread_support.h (GC_Thread_Rep.crtn, GC_Thread_Rep.flags_pad): New field. * include/private/pthread_support.h [GC_NO_FINALIZATION] (GC_Thread_Rep.no_fnlz_pad): Remove field. * include/private/pthread_support.h (GC_threads): Move (and refine) comment from GC_Thread_Rep. * include/private/pthread_support.h [GC_WIN32_THREADS] (GC_record_stack_base): Change me argument to crtn. * pthread_stop_world.c [!NACL] (GC_store_stack_ptr): Likewise. * pthread_support.c (GC_record_stack_base): Likewise. * pthread_stop_world.c [NACL] (NACL_STORE_REGS, nacl_pre_syscall_hook, __nacl_suspend_thread_if_needed): Use p->crtn instead of p to access stack_ptr. * pthread_support.c (first_crtn): New static variable. * pthread_support.c (first_thread): Update comment. * pthread_support.c (first_thread_used): Remove variable. * pthread_support.c (GC_push_thread_structures): Push first_thread.crtn symbol * pthread_support.c (GC_push_thread_structures): Push first_crtn.backing_store_end instead of that in first_thread. * pthread_support.c [MPROTECT_VDB && GC_WIN32_THREADS] (GC_win32_unprotect_thread): Call GC_remove_protection() for t->crtn. * pthread_support.c (GC_new_thread): Use first_thread.crtn!=0 instead of first_thread_used; set first_thread.crtn to &first_crtn; allocate GC_StackContext_Rep object using GC_INTERNAL_MALLOC() and store the pointer to result->crtn. * pthread_support.c [CPPCHECK] (GC_new_thread): Call GC_noop1() for first_thread.flags_pad, for first_crtn.dummy instead of result->dummy, and for first_crtn.fnlz_pad instead of result->no_fnlz_pad. * pthread_support.c (GC_delete_thread): Call GC_INTERNAL_FREE(p->crtn) along with that for p. * pthread_support.c [CAN_HANDLE_FORK && (!THREAD_SANITIZER || !CAN_CALL_ATFORK)] (GC_remove_all_threads_but_me): Likewise. * pthread_support.c [GC_PTHREADS] (GC_pthread_join, GC_pthread_detach): Likewise. * pthread_support.c (GC_segment_is_thread_stack, GC_greatest_stack_base_below): Use p->crtn instead of p to access stack_end. * pthread_support.c (GC_call_with_gc_active): Move assertions about me fields to be after LOCK; add assertion that me->crtn==crtn. * win32_threads.c (dll_thread_table): Make it static. * win32_threads.c [!GC_NO_THREADS_DISCOVERY] (dll_crtn_table): New static variable. * win32_threads.c (GC_register_my_thread_inner): Reformat comment; set me->crtn. * win32_threads.c (GC_push_stack_for): Define stack_end local variable; immediately return (zero) if stack_end is NULL. * win32_threads.c (GC_push_all_stacks): Call GC_push_stack_for() (and increment nthreads) even if stack_end is NULL. * win32_threads.c (GC_get_next_stack): Rename s local variable to stack_end. --- pthread_stop_world.c | 70 +++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'pthread_stop_world.c') diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 993db7d9..4099ae95 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -298,7 +298,7 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy, void *context); # define GC_lookup_thread_async GC_lookup_thread #endif -GC_INLINE void GC_store_stack_ptr(GC_thread me) +GC_INLINE void GC_store_stack_ptr(GC_stack_context_t crtn) { /* There is no data race between the suspend handler (storing */ /* stack_ptr) and GC_push_all_stacks (fetching stack_ptr) because */ @@ -308,14 +308,15 @@ GC_INLINE void GC_store_stack_ptr(GC_thread me) /* and fetched (by GC_push_all_stacks) using the atomic primitives to */ /* avoid the related TSan warning. */ # ifdef SPARC - ao_store_async((volatile AO_t *)&(me -> stack_ptr), + ao_store_async((volatile AO_t *)&(crtn -> stack_ptr), (AO_t)GC_save_regs_in_stack()); /* TODO: regs saving already done by GC_with_callee_saves_pushed */ # else # ifdef IA64 - me -> backing_store_ptr = GC_save_regs_in_stack(); + crtn -> backing_store_ptr = GC_save_regs_in_stack(); # endif - ao_store_async((volatile AO_t *)&(me -> stack_ptr), (AO_t)GC_approx_sp()); + ao_store_async((volatile AO_t *)&(crtn -> stack_ptr), + (AO_t)GC_approx_sp()); # endif } @@ -323,6 +324,7 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy, void *context) { pthread_t self; GC_thread me; + GC_stack_context_t crtn; # ifdef E2K ptr_t bs_lo; size_t stack_size; @@ -363,12 +365,13 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy, void *context) RESTORE_CANCEL(cancel_state); return; } - GC_store_stack_ptr(me); + crtn = me -> crtn; + GC_store_stack_ptr(crtn); # ifdef E2K - GC_ASSERT(NULL == me -> backing_store_end); + GC_ASSERT(NULL == crtn -> backing_store_end); GET_PROCEDURE_STACK_LOCAL(&bs_lo, &stack_size); - me -> backing_store_end = bs_lo; - me -> backing_store_ptr = bs_lo + stack_size; + crtn -> backing_store_end = bs_lo; + crtn -> backing_store_ptr = bs_lo + stack_size; # endif # ifdef GC_ENABLE_SUSPEND_THREAD suspend_cnt = (word)ao_load_async(&(me -> ext_suspend_cnt)); @@ -405,10 +408,10 @@ STATIC void GC_suspend_handler_inner(ptr_t dummy, void *context) GC_log_printf("Continuing %p\n", (void *)self); # endif # ifdef E2K - GC_ASSERT(me -> backing_store_end == bs_lo); + GC_ASSERT(crtn -> backing_store_end == bs_lo); FREE_PROCEDURE_STACK_LOCAL(bs_lo, stack_size); - me -> backing_store_ptr = NULL; - me -> backing_store_end = NULL; + crtn -> backing_store_ptr = NULL; + crtn -> backing_store_end = NULL; # endif # ifndef GC_NETBSD_THREADS_WORKAROUND @@ -797,10 +800,11 @@ GC_INNER void GC_push_all_stacks(void) # if defined(E2K) || defined(IA64) GC_bool is_self = FALSE; # endif + GC_stack_context_t crtn = p -> crtn; if (KNOWN_FINISHED(p)) continue; ++nthreads; - traced_stack_sect = p -> traced_stack_sect; + traced_stack_sect = crtn -> traced_stack_sect; if (THREAD_EQUAL(p -> id, self)) { GC_ASSERT((p -> flags & DO_BLOCKING) == 0); # ifdef SPARC @@ -810,7 +814,7 @@ GC_INNER void GC_push_all_stacks(void) # ifdef IA64 bs_hi = GC_save_regs_in_stack(); # elif defined(E2K) - GC_ASSERT(NULL == p -> backing_store_end); + GC_ASSERT(NULL == crtn -> backing_store_end); (void)GC_save_regs_in_stack(); { size_t stack_size; @@ -824,25 +828,25 @@ GC_INNER void GC_push_all_stacks(void) is_self = TRUE; # endif } else { - lo = (ptr_t)AO_load((volatile AO_t *)&(p -> stack_ptr)); + lo = (ptr_t)AO_load((volatile AO_t *)&(crtn -> stack_ptr)); # ifdef IA64 - bs_hi = p -> backing_store_ptr; + bs_hi = crtn -> backing_store_ptr; # elif defined(E2K) - bs_lo = p -> backing_store_end; - bs_hi = p -> backing_store_ptr; + bs_lo = crtn -> backing_store_end; + bs_hi = crtn -> backing_store_ptr; # endif if (traced_stack_sect != NULL - && traced_stack_sect->saved_stack_ptr == lo) { + && traced_stack_sect -> saved_stack_ptr == lo) { /* If the thread has never been stopped since the recent */ /* GC_call_with_gc_active invocation then skip the top */ /* "stack section" as stack_ptr already points to. */ - traced_stack_sect = traced_stack_sect->prev; + traced_stack_sect = traced_stack_sect -> prev; } } if (EXPECT((p -> flags & MAIN_THREAD) == 0, TRUE)) { - hi = p -> stack_end; + hi = crtn -> stack_end; # ifdef IA64 - bs_lo = p -> backing_store_end; + bs_lo = crtn -> backing_store_end; # endif } else { /* The original stack. */ @@ -855,10 +859,10 @@ GC_INNER void GC_push_all_stacks(void) GC_log_printf("Stack for thread %p is [%p,%p)\n", (void *)p->id, (void *)lo, (void *)hi); # endif - if (0 == lo) ABORT("GC_push_all_stacks: sp not set!"); - if (p->altstack != NULL && (word)p->altstack <= (word)lo - && (word)lo <= (word)p->altstack + p->altstack_size) { - hi = p->altstack + p->altstack_size; + if (NULL == lo) ABORT("GC_push_all_stacks: sp not set!"); + if (crtn -> altstack != NULL && (word)(crtn -> altstack) <= (word)lo + && (word)lo <= (word)(crtn -> altstack) + crtn -> altstack_size) { + hi = crtn -> altstack + crtn -> altstack_size; /* FIXME: Need to scan the normal stack too, but how ? */ /* FIXME: Assume stack grows down */ } @@ -1085,8 +1089,8 @@ GC_INNER void GC_stop_world(void) __asm__ __volatile__ ("push %r14"); \ __asm__ __volatile__ ("push %r15"); \ __asm__ __volatile__ ("mov %%esp, %0" \ - : "=m" (GC_nacl_gc_thread_self -> stack_ptr)); \ - BCOPY(GC_nacl_gc_thread_self -> stack_ptr, \ + : "=m" (GC_nacl_gc_thread_self -> crtn -> stack_ptr)); \ + BCOPY(GC_nacl_gc_thread_self -> crtn -> stack_ptr, \ GC_nacl_gc_thread_self -> reg_storage, \ NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \ __asm__ __volatile__ ("naclasp $48, %r15"); \ @@ -1099,8 +1103,8 @@ GC_INNER void GC_stop_world(void) __asm__ __volatile__ ("push %esi"); \ __asm__ __volatile__ ("push %edi"); \ __asm__ __volatile__ ("mov %%esp, %0" \ - : "=m" (GC_nacl_gc_thread_self -> stack_ptr)); \ - BCOPY(GC_nacl_gc_thread_self -> stack_ptr, \ + : "=m" (GC_nacl_gc_thread_self -> crtn -> stack_ptr)); \ + BCOPY(GC_nacl_gc_thread_self -> crtn -> stack_ptr, \ GC_nacl_gc_thread_self -> reg_storage, \ NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\ __asm__ __volatile__ ("add $16, %esp"); \ @@ -1110,10 +1114,10 @@ GC_INNER void GC_stop_world(void) do { \ __asm__ __volatile__ ("push {r4-r8,r10-r12,lr}"); \ __asm__ __volatile__ ("mov r0, %0" \ - : : "r" (&GC_nacl_gc_thread_self -> stack_ptr)); \ + : : "r" (&GC_nacl_gc_thread_self -> crtn -> stack_ptr)); \ __asm__ __volatile__ ("bic r0, r0, #0xc0000000"); \ __asm__ __volatile__ ("str sp, [r0]"); \ - BCOPY(GC_nacl_gc_thread_self -> stack_ptr, \ + BCOPY(GC_nacl_gc_thread_self -> crtn -> stack_ptr, \ GC_nacl_gc_thread_self -> reg_storage, \ NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \ __asm__ __volatile__ ("add sp, sp, #40"); \ @@ -1127,7 +1131,7 @@ GC_INNER void GC_stop_world(void) { if (GC_nacl_thread_idx != -1) { NACL_STORE_REGS(); - GC_nacl_gc_thread_self -> stack_ptr = GC_approx_sp(); + GC_nacl_gc_thread_self -> crtn -> stack_ptr = GC_approx_sp(); GC_nacl_thread_parked[GC_nacl_thread_idx] = 1; } } @@ -1150,7 +1154,7 @@ GC_INNER void GC_stop_world(void) /* so don't bother storing registers again, the GC has a set. */ if (!GC_nacl_thread_parked[GC_nacl_thread_idx]) { NACL_STORE_REGS(); - GC_nacl_gc_thread_self -> stack_ptr = GC_approx_sp(); + GC_nacl_gc_thread_self -> crtn -> stack_ptr = GC_approx_sp(); } GC_nacl_thread_parked[GC_nacl_thread_idx] = 1; while (GC_nacl_park_threads_now) { -- cgit v1.2.1