diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2022-10-06 08:46:35 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2022-10-06 20:50:37 +0300 |
commit | 6b2980ab6e8f0a1dbd176eb546cdf4aba8172092 (patch) | |
tree | 007a938f0f3586d8f0fd3f08ee22d24ef6f73ff0 /win32_threads.c | |
parent | 394b6e2909a25bb4658248cc1425a8f5b06c8e70 (diff) | |
download | bdwgc-6b2980ab6e8f0a1dbd176eb546cdf4aba8172092.tar.gz |
Define GC_thread type in a single place both for pthreads and Win32
(refactoring)
* include/private/pthread_support.h: Add title comment.
* include/private/pthread_support.h: Replace
GC_PTHREADS&&!GC_WIN32_THREADS condition to THREADS.
* include/private/pthread_support.h [GC_PTHREADS
|| GC_PTHREADS_PARAMARK]: Include pthread.h.
* include/private/pthread_support.h [GC_WIN32_THREADS] (thread_id_t):
Define as DWORD.
* include/private/pthread_support.h [!GC_NO_THREADS_DISCOVERY
&& GC_WIN32_THREADS] (GC_Thread_Rep.tm): Add in_use and long_in_use
union fields (moved from win32_threads.c).
* include/private/pthread_support.h (GC_Thread_Rep.tm.next,
GC_Thread_Rep.stack_end): Update comment.
* include/private/pthread_support.h (GC_Thread_Rep.id): Add comment.
* include/private/pthread_support.h [USE_TKILL_ON_ANDROID]
(GC_Thread_Rep.kernel_id): Move field down (to be after stack_ptr).
* include/private/pthread_support.h [GC_WIN32_THREADS && GC_PTHREADS]
(GC_Thread_Rep.pthread_id): New field (moved from win32_threads.c).
* include/private/pthread_support.h [GC_NO_FINALIZATION]
(GC_Thread_Rep.no_fnlz_pad): Likewise.
* include/private/pthread_support.h [GC_WIN32_THREADS]
(GC_Thread_Rep.last_stack_min): Likewise.
* include/private/pthread_support.h [GC_WIN32_THREADS && I386]
(GC_Thread_Rep.initial_stack_base): Likewise.
* include/private/pthread_support.h [GC_WIN32_THREADS && !MSWINCE]
(GC_Thread_Rep.handle): Likewise.
* include/private/pthread_support.h [RETRY_GET_THREAD_CONTEXT]
(GC_Thread_Rep.context_sp, GC_Thread_Rep.context_regs): Likewise.
* include/private/pthread_support.h (GC_Thread_Rep.flags): Move field
up (to be right after pthread_id one).
* include/private/pthread_support.h (FINISHED, DETACHED, MAIN_THREAD,
DISABLED_GC, DO_BLOCKING, KNOWN_FINISHED): Move macro definition up
to stay close to flags field.
* include/private/pthread_support.h [!GC_PTHREADS] (KNOWN_FINISHED):
Define to FALSE.
* include/private/pthread_support.h (DETACHED): Define only if
GC_PTHREADS.
* include/private/pthread_support.h (GC_Thread_Rep.status): Likewise.
* include/private/pthread_support.h (MAIN_THREAD, DISABLED_GC): Do not
define if GC_WIN32_THREADS.
* include/private/pthread_support.h (GC_Thread_Rep.altstack,
GC_Thread_Rep.altstack_size, GC_Thread_Rep.normstack,
GC_Thread_Rep.normstack_size): Likewise.
* include/private/pthread_support.h [GC_WIN32_THREADS] (IS_SUSPENDED):
Define macro (moved from win32_threads.c).
* include/private/pthread_support.h [MSWINCE || GC_WIN32_THREADS]
(THREAD_HANDLE): Likewise.
* include/private/pthread_support.h [GC_WIN32_THREADS]
(THREAD_TABLE_INDEX): Likewise.
* include/private/gcconfig.h [GC_WIN32_THREADS] (PUSHED_REGS_COUNT):
Likewise.
* include/private/gcconfig.h [GC_PTHREADS && !GC_PTHREADS_PARAMARK
&& !__MINGW32__] (GC_PTHREADS_PARAMARK): Likewise.
* include/private/pthread_support.h [!GC_NO_FINALIZATION]
(GC_Thread_Rep.finalizer_nested, GC_Thread_Rep.finalizer_skipped): Move
field up to be right after flags one.
* include/private/pthread_support.h [SIGNAL_BASED_STOP_WORLD]
(GC_Thread_Rep.last_stop_count, GC_Thread_Rep.ext_suspend_cnt):
Reformat comment.
* include/private/pthread_support.h (GC_Thread_Rep.traced_stack_sect):
Likewise.
* include/private/pthread_support.h (GC_inner_start_routine,
GC_start_rtn_prepare_thread): Do not declare if GC_WIN32_THREADS.
* include/private/pthread_support.h (GC_thread_exit_proc): Declare only
if GC_PTHREADS.
* pthread_start.c: Do not include pthread.h.
* pthread_support.c: Likewise.
* win32_threads.c [GC_PTHREADS || GC_WIN32_PTHREADS
|| GC_PTHREADS_PARAMARK]: Likewise.
* win32_threads.c: Include pthread_support.h instead of gc_priv.h.
* win32_threads.c [THREAD_LOCAL_ALLOC]: Do not include
thread_local_alloc.h directly.
* win32_threads.c [GC_PTHREADS] (GC_thread_exit_proc): Remove static
function declaration.
* win32_threads.c [GC_ASSERTIONS] (GC_thr_initialized, GC_threads,
GC_lookup_thread_inner): Change STATIC to GC_INNER.
* win32_threads.c (thread_id_t, GC_Thread_Rep, THREAD_TABLE_SZ,
THREAD_TABLE_INDEX, PUSHED_REGS_COUNT, GC_PTHREADS_PARAMARK): Do not
define.
* win32_threads.c (GC_lookup_thread_inner): Rename to GC_lookup_thread.
* win32_threads.c [GC_PTHREADS] (GC_lookup_pthread): Rename to
GC_lookup_by_pthread.
* win32_threads.c [GC_PTHREADS] (GC_thread_exit_proc): Change STATIC to
GC_INNER_PTHRSTART.
Diffstat (limited to 'win32_threads.c')
-rw-r--r-- | win32_threads.c | 199 |
1 files changed, 24 insertions, 175 deletions
diff --git a/win32_threads.c b/win32_threads.c index 153dd7b6..3e5cdaf0 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -16,14 +16,10 @@ * modified is included with the above copyright notice. */ -#include "private/gc_priv.h" +#include "private/pthread_support.h" #if defined(GC_WIN32_THREADS) -#ifdef THREAD_LOCAL_ALLOC -# include "private/thread_local_alloc.h" -#endif /* THREAD_LOCAL_ALLOC */ - /* Allocation lock declarations. */ #if !defined(USE_PTHREAD_LOCKS) GC_INNER CRITICAL_SECTION GC_allocate_ml; @@ -56,9 +52,7 @@ # endif STATIC void * GC_pthread_start(void * arg); - STATIC void GC_thread_exit_proc(void *arg); -# include <pthread.h> # ifdef CAN_CALL_ATFORK # include <unistd.h> # endif @@ -69,25 +63,7 @@ #endif /* !GC_PTHREADS && !MSWINCE */ -/* PUSHED_REGS_COUNT is the number of copied registers in copy_ptr_regs. */ static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext); -#if defined(I386) -# ifdef WOW64_THREAD_CONTEXT_WORKAROUND -# define PUSHED_REGS_COUNT 9 -# else -# define PUSHED_REGS_COUNT 7 -# endif -#elif defined(X86_64) || defined(SHx) -# define PUSHED_REGS_COUNT 15 -#elif defined(ARM32) -# define PUSHED_REGS_COUNT 13 -#elif defined(AARCH64) -# define PUSHED_REGS_COUNT 30 -#elif defined(MIPS) || defined(ALPHA) -# define PUSHED_REGS_COUNT 28 -#elif defined(PPC) -# define PUSHED_REGS_COUNT 29 -#endif #ifndef GC_NO_THREADS_DISCOVERY /* This code operates in two distinct modes, depending on */ @@ -146,7 +122,7 @@ static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext); typedef LONG * IE_t; #ifdef GC_ASSERTIONS - STATIC GC_bool GC_thr_initialized = FALSE; + GC_INNER GC_bool GC_thr_initialized = FALSE; #endif #ifndef GC_ALWAYS_MULTITHREADED @@ -175,115 +151,6 @@ GC_API void GC_CALL GC_use_threads_discovery(void) #define ADDR_LIMIT ((ptr_t)GC_WORD_MAX) -typedef DWORD thread_id_t; - -struct GC_Thread_Rep { - union { -# ifndef GC_NO_THREADS_DISCOVERY - volatile AO_t in_use; - /* Updated without lock. */ - /* We assert that unused */ - /* entries have invalid ids of */ - /* zero and zero stack fields. */ - /* Used only with GC_win32_dll_threads. */ - LONG long_in_use; /* The same but of the type that */ - /* matches the first argument of */ - /* InterlockedExchange(); volatile is */ - /* omitted because the ancient version */ - /* of the prototype lacks the qualifier.*/ -# endif - struct GC_Thread_Rep * next; - /* Hash table link without */ - /* GC_win32_dll_threads. */ - /* More recently allocated threads */ - /* with a given pthread id come */ - /* first. (All but the first are */ - /* guaranteed to be dead, but we may */ - /* not yet have registered the join.) */ - } tm; /* table_management */ - - thread_id_t id; - -# ifdef MSWINCE - /* According to MSDN specs for WinCE targets: */ - /* - DuplicateHandle() is not applicable to thread handles; and */ - /* - the value returned by GetCurrentThreadId() could be used as */ - /* a "real" thread handle (for SuspendThread(), ResumeThread() and */ - /* GetThreadContext()). */ -# define THREAD_HANDLE(t) (HANDLE)(word)(t)->id -# else - HANDLE handle; -# define THREAD_HANDLE(t) (t)->handle -# endif - - ptr_t stack_end; /* The cold end of the stack. */ - /* 0 ==> entry not valid. */ - /* !in_use ==> stack_end == 0 */ - - ptr_t last_stack_min; /* Last known minimum (hottest) address */ - /* in stack or ADDR_LIMIT if unset */ -# ifdef IA64 - ptr_t backing_store_end; - ptr_t backing_store_ptr; -# elif defined(I386) - ptr_t initial_stack_base; - /* The cold end of the stack saved by */ - /* GC_record_stack_base (never modified */ - /* by GC_set_stackbottom). */ -# endif - - ptr_t stack_ptr; /* Protected by GC lock. */ - /* Valid only if thread is in */ - /* do-blocking state (and will acquire */ - /* GC lock before doing any pointer */ - /* manipulation). Thus it does not */ - /* need to stop this thread. */ - - struct GC_traced_stack_sect_s *traced_stack_sect; - /* Points to the "stack section" data */ - /* held in stack by the innermost */ - /* GC_call_with_gc_active() of this */ - /* thread. May be NULL. */ - -# ifndef GC_NO_FINALIZATION - unsigned short finalizer_skipped; - unsigned char finalizer_nested; - /* Used by GC_check_finalizer_nested() */ - /* to minimize the level of recursion */ - /* when a client finalizer allocates */ - /* memory (initially both are 0). */ -# else - char no_fnlz_pad[3]; /* Explicit alignment (for some rare */ - /* compilers such as bcc and wcc). */ -# endif - - unsigned char flags; /* Protected by the GC lock. */ -# define FINISHED 0x1 /* Thread has exited. */ -# define DO_BLOCKING 0x20 /* Thread is in do-blocking state. */ -# define IS_SUSPENDED 0x40 /* Thread is suspended by SuspendThread. */ - -# ifdef GC_PTHREADS -# define DETACHED 2 /* Thread is intended to be detached. */ -# define KNOWN_FINISHED(t) (((t) -> flags) & FINISHED) - pthread_t pthread_id; - void *status; /* hold exit value until join in case it's a pointer */ -# else -# define KNOWN_FINISHED(t) 0 -# endif - -# ifdef THREAD_LOCAL_ALLOC - struct thread_local_freelists tlfs; -# endif - -# ifdef RETRY_GET_THREAD_CONTEXT - ptr_t context_sp; - word context_regs[PUSHED_REGS_COUNT]; - /* Populated as part of GC_suspend() as */ - /* resume/suspend loop may be needed for the */ - /* call to GetThreadContext() to succeed. */ -# endif -}; - typedef struct GC_Thread_Rep * GC_thread; typedef volatile struct GC_Thread_Rep * GC_vthread; @@ -346,12 +213,7 @@ STATIC volatile LONG GC_max_thread_index = 0; /* And now the version used if GC_win32_dll_threads is not set. */ /* This is a chained hash table, with much of the code borrowed */ /* from the Posix implementation. */ -#ifndef THREAD_TABLE_SZ -# define THREAD_TABLE_SZ 256 /* Power of 2 (for speed). */ -#endif -#define THREAD_TABLE_INDEX(id) /* id is of DWORD type */ \ - (int)((((id) >> 8) ^ (id)) % THREAD_TABLE_SZ) -STATIC GC_thread GC_threads[THREAD_TABLE_SZ]; +GC_INNER GC_thread GC_threads[THREAD_TABLE_SZ] = {0}; /* It may not be safe to allocate when we register the first thread. */ /* Thus we allocated one statically. It does not contain any pointer */ @@ -540,8 +402,7 @@ GC_INLINE LONG GC_get_max_thread_index(void) /* May be called without a lock, but should be called in contexts in */ /* which the requested thread cannot be asynchronously deleted, e.g. */ /* from the thread itself. */ -/* Also used (for assertion checking only) from thread_local_alloc.c. */ -STATIC GC_thread GC_lookup_thread_inner(thread_id_t id) +GC_INNER GC_thread GC_lookup_thread(thread_id_t id) { # ifndef GC_NO_THREADS_DISCOVERY if (GC_win32_dll_threads) { @@ -571,7 +432,7 @@ STATIC GC_thread GC_lookup_thread_inner(thread_id_t id) #ifdef LINT2 # define CHECK_LOOKUP_MY_THREAD(me) \ - if (!(me)) ABORT("GC_lookup_thread_inner(GetCurrentThreadId) failed") + if (!(me)) ABORT("GC_lookup_thread(GetCurrentThreadId) failed") #else # define CHECK_LOOKUP_MY_THREAD(me) /* empty */ #endif @@ -581,7 +442,7 @@ STATIC GC_thread GC_lookup_thread_inner(thread_id_t id) /* GC_reset_finalizer_nested() is the same as in pthread_support.c. */ GC_INNER void GC_reset_finalizer_nested(void) { - GC_thread me = GC_lookup_thread_inner(GetCurrentThreadId()); + GC_thread me = GC_lookup_thread(GetCurrentThreadId()); CHECK_LOOKUP_MY_THREAD(me); me->finalizer_nested = 0; @@ -594,7 +455,7 @@ STATIC GC_thread GC_lookup_thread_inner(thread_id_t id) unsigned nesting_level; GC_ASSERT(I_HOLD_LOCK()); - me = GC_lookup_thread_inner(GetCurrentThreadId()); + me = GC_lookup_thread(GetCurrentThreadId()); CHECK_LOOKUP_MY_THREAD(me); nesting_level = me->finalizer_nested; if (nesting_level) { @@ -617,7 +478,7 @@ STATIC GC_thread GC_lookup_thread_inner(thread_id_t id) DCL_LOCK_STATE; LOCK(); - me = GC_lookup_thread_inner(GetCurrentThreadId()); + me = GC_lookup_thread(GetCurrentThreadId()); UNLOCK(); return (word)tsd >= (word)(&me->tlfs) && (word)tsd < (word)(&me->tlfs) + sizeof(me->tlfs); @@ -631,7 +492,7 @@ GC_API int GC_CALL GC_thread_is_registered(void) DCL_LOCK_STATE; LOCK(); - me = GC_lookup_thread_inner(self_id); + me = GC_lookup_thread(self_id); UNLOCK(); return me != NULL; } @@ -665,7 +526,6 @@ GC_API void GC_CALL GC_register_altstack(void *normstack, #ifdef CYGWIN32 # define GC_PTHREAD_PTRVAL(pthread_id) pthread_id #elif defined(GC_WIN32_PTHREADS) || defined(GC_PTHREADS_PARAMARK) -# include <pthread.h> /* to check for winpthreads */ # if defined(__WINPTHREADS_VERSION_MAJOR) # define GC_PTHREAD_PTRVAL(pthread_id) pthread_id # else @@ -731,7 +591,7 @@ STATIC void GC_delete_gc_thread_no_free(GC_vthread t) STATIC void GC_delete_thread(thread_id_t id) { if (GC_win32_dll_threads) { - GC_vthread t = GC_lookup_thread_inner(id); + GC_vthread t = GC_lookup_thread(id); if (EXPECT(NULL == t, FALSE)) { WARN("Removing nonexistent thread, id= %" WARN_PRIdPTR "\n", id); @@ -771,7 +631,7 @@ GC_API void GC_CALL GC_allow_register_threads(void) /* Check GC is initialized and the current thread is registered. */ LOCK(); - GC_ASSERT(GC_lookup_thread_inner(GetCurrentThreadId()) != 0); + GC_ASSERT(GC_lookup_thread(GetCurrentThreadId()) != 0); UNLOCK(); # endif GC_start_mark_threads(); @@ -789,7 +649,7 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) /* We lock here, since we want to wait for an ongoing GC. */ LOCK(); - me = GC_lookup_thread_inner(self_id); + me = GC_lookup_thread(self_id); if (EXPECT(NULL == me, TRUE)) { # ifdef GC_PTHREADS me = GC_register_my_thread_inner(sb, self_id); @@ -873,7 +733,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) LOCK(); GC_wait_for_gc_completion(FALSE); # if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS) - me = GC_lookup_thread_inner(self_id); + me = GC_lookup_thread(self_id); CHECK_LOOKUP_MY_THREAD(me); GC_ASSERT(!KNOWN_FINISHED(me)); # endif @@ -914,7 +774,7 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void *context) UNUSED_ARG(context); LOCK(); - me = GC_lookup_thread_inner(self_id); + me = GC_lookup_thread(self_id); CHECK_LOOKUP_MY_THREAD(me); GC_ASSERT((me -> flags & DO_BLOCKING) == 0); # ifdef IA64 @@ -943,7 +803,7 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, DCL_LOCK_STATE; LOCK(); /* This will block if the world is stopped. */ - me = GC_lookup_thread_inner(self_id); + me = GC_lookup_thread(self_id); CHECK_LOOKUP_MY_THREAD(me); /* Adjust our stack bottom pointer (this could happen unless */ /* GC_get_stack_base() was used which returned GC_SUCCESS). */ @@ -1015,7 +875,7 @@ GC_API void GC_CALL GC_set_stackbottom(void *gc_thread_handle, GC_ASSERT(I_HOLD_LOCK()); if (NULL == t) { /* current thread? */ - t = GC_lookup_thread_inner(GetCurrentThreadId()); + t = GC_lookup_thread(GetCurrentThreadId()); CHECK_LOOKUP_MY_THREAD(t); } GC_ASSERT(!KNOWN_FINISHED(t)); @@ -1035,7 +895,7 @@ GC_API void * GC_CALL GC_get_my_stackbottom(struct GC_stack_base *sb) DCL_LOCK_STATE; LOCK(); - me = GC_lookup_thread_inner(self_id); + me = GC_lookup_thread(self_id); CHECK_LOOKUP_MY_THREAD(me); /* the thread is assumed to be registered */ sb -> mem_base = me -> stack_end; # ifdef IA64 @@ -1064,7 +924,7 @@ GC_API void * GC_CALL GC_get_my_stackbottom(struct GC_stack_base *sb) /* We assume that this is only called for pthread ids that */ /* have not yet terminated or are still joinable, and */ /* cannot be terminated concurrently. */ - STATIC GC_thread GC_lookup_pthread(pthread_t thread) + STATIC GC_thread GC_lookup_by_pthread(pthread_t thread) { /* TODO: search in dll_thread_table instead when DllMain-based */ /* thread registration is made compatible with pthreads (and */ @@ -1972,16 +1832,6 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, #ifdef PARALLEL_MARK -# if defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK) - /* Use pthread-based parallel mark implementation. */ - - /* Workaround a deadlock in winpthreads-3.0b internals (observed */ - /* with MinGW 32/64). */ -# if !defined(__MINGW32__) -# define GC_PTHREADS_PARAMARK -# endif -# endif - # if !defined(GC_PTHREADS_PARAMARK) STATIC HANDLE GC_marker_cv[MAX_MARKERS - 1] = {0}; /* Events with manual reset (one for each */ @@ -2091,7 +1941,6 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, static int available_markers_m1 = 0; # ifdef GC_PTHREADS_PARAMARK -# include <pthread.h> # if defined(GC_ASSERTIONS) && !defined(NUMERIC_THREAD_ID) # define NUMERIC_THREAD_ID(id) (unsigned long)(word)GC_PTHREAD_PTRVAL(id) @@ -2886,7 +2735,7 @@ GC_INNER void GC_thr_init(void) } # endif /* PARALLEL_MARK */ - GC_ASSERT(0 == GC_lookup_thread_inner(GC_main_thread)); + GC_ASSERT(0 == GC_lookup_thread(GC_main_thread)); GC_register_my_thread_inner(&sb, GC_main_thread); # undef GC_main_thread } @@ -2920,14 +2769,14 @@ GC_INNER void GC_thr_init(void) /* FIXME: It would be better if this worked more like */ /* pthread_support.c. */ # ifndef GC_WIN32_PTHREADS - while ((t = GC_lookup_pthread(thread)) == 0) + while ((t = GC_lookup_by_pthread(thread)) == 0) Sleep(10); # endif result = pthread_join(thread, retval); if (EXPECT(0 == result, TRUE)) { # ifdef GC_WIN32_PTHREADS /* pthreads-win32 and winpthreads id are unique (not recycled). */ - GC_thread t = GC_lookup_pthread(thread); + GC_thread t = GC_lookup_by_pthread(thread); if (NULL == t) ABORT("Thread not registered"); # endif @@ -3045,7 +2894,7 @@ GC_INNER void GC_thr_init(void) return GC_call_with_stack_base(GC_pthread_start_inner, arg); } - STATIC void GC_thread_exit_proc(void *arg) + GC_INNER_PTHRSTART void GC_thread_exit_proc(void *arg) { GC_thread me = (GC_thread)arg; DCL_LOCK_STATE; @@ -3095,7 +2944,7 @@ GC_INNER void GC_thr_init(void) GC_ASSERT(!GC_win32_dll_threads); /* The thread might not have registered itself yet. */ /* TODO: Wait for registration of the created thread in pthread_create. */ - while ((t = GC_lookup_pthread(thread)) == NULL) + while ((t = GC_lookup_by_pthread(thread)) == NULL) Sleep(10); result = pthread_detach(thread); if (EXPECT(0 == result, TRUE)) { @@ -3198,7 +3047,7 @@ GC_INNER void GC_init_parallel(void) GC_ASSERT(GC_is_initialized); LOCK(); - me = GC_lookup_thread_inner(GetCurrentThreadId()); + me = GC_lookup_thread(GetCurrentThreadId()); CHECK_LOOKUP_MY_THREAD(me); GC_init_thread_local(&me->tlfs); UNLOCK(); |