summaryrefslogtreecommitdiff
path: root/win32_threads.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-10-06 08:46:35 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-10-06 20:50:37 +0300
commit6b2980ab6e8f0a1dbd176eb546cdf4aba8172092 (patch)
tree007a938f0f3586d8f0fd3f08ee22d24ef6f73ff0 /win32_threads.c
parent394b6e2909a25bb4658248cc1425a8f5b06c8e70 (diff)
downloadbdwgc-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.c199
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();