diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2022-04-11 08:25:51 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2022-04-11 20:59:49 +0300 |
commit | b3af80d5f6f2f41ba57659f72d667b003a3274bd (patch) | |
tree | d69061f58827da313b3f032b28d9992ac01d2b2c /pthread_support.c | |
parent | a646d031e70e5f30cf15153299914afb03992159 (diff) | |
download | bdwgc-b3af80d5f6f2f41ba57659f72d667b003a3274bd.tar.gz |
Fix context saving when GC_suspend_thread(self)
(fix of commits 59e2bcf96, 1ae3d0fbb)
This prevents setting suspended_ext before saving context in
GC_suspend_thread as well as in GC_register_my_thread (for a thread
registered from a thread destructor).
* include/private/pthread_support.h [GC_ENABLE_SUSPEND_THREAD
&& SIGNAL_BASED_STOP_WORLD] (GC_suspend_self_blocked): Declare
function.
* pthread_stop_world.c [!GC_OPENBSD_UTHREADS && !NACL
&& GC_ENABLE_SUSPEND_THREAD] (GC_suspend_thread): Call
GC_with_callee_saves_pushed(GC_suspend_self_blocked) before LOCK
(instead of GC_do_blocking(GC_suspend_self_inner) after LOCK); remove
comment.
* pthread_support.c [GC_ENABLE_SUSPEND_THREAD
&& SIGNAL_BASED_STOP_WORLD] (GC_register_my_thread): Likewise.
* pthread_support.c (do_blocking_locked): New static function (move
most code of GC_do_blocking_inner except for locking and
GC_lookup_thread() call).
* pthread_support.c (GC_do_blocking_inner): Call do_blocking_locked().
* pthread_support.c [GC_ENABLE_SUSPEND_THREAD
&& SIGNAL_BASED_STOP_WORLD] (GC_suspend_self_blocked): New static
function.
Diffstat (limited to 'pthread_support.c')
-rw-r--r-- | pthread_support.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/pthread_support.c b/pthread_support.c index 5b08fdb7..ed4e2a0e 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1520,12 +1520,10 @@ GC_INNER void GC_init_parallel(void) /* Wrapper for functions that are likely to block for an appreciable */ /* length of time. */ - -GC_INNER void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED) +static void *do_blocking_locked(GC_fn_type fn, void *client_data, + GC_thread me, void *context GC_ATTR_UNUSED) { - struct blocking_data * d = (struct blocking_data *) data; - pthread_t self = pthread_self(); - GC_thread me; + void *result; # if defined(SPARC) || defined(IA64) ptr_t stack_ptr = GC_save_regs_in_stack(); # elif defined(E2K) @@ -1539,8 +1537,6 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED) # ifdef E2K (void)GC_save_regs_in_stack(); # endif - LOCK(); - me = GC_lookup_thread(self); GC_ASSERT(!(me -> thread_blocked)); # ifdef SPARC me -> stop_info.stack_ptr = stack_ptr; @@ -1565,7 +1561,7 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED) me -> thread_blocked = (unsigned char)TRUE; /* Save context here if we want to support precise stack marking */ UNLOCK(); - d -> client_data = (d -> fn)(d -> client_data); + result = fn(client_data); LOCK(); /* This will block if the world is stopped. */ # if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD) @@ -1592,9 +1588,31 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED) if (topOfStackUnset) me -> topOfStack = NULL; /* make topOfStack unset again */ # endif + return result; +} + +GC_INNER void GC_do_blocking_inner(ptr_t data, void *context) +{ + struct blocking_data *d = (struct blocking_data *)data; + GC_thread me; + DCL_LOCK_STATE; + + LOCK(); + me = GC_lookup_thread(pthread_self()); + d -> client_data = do_blocking_locked(d -> fn, d -> client_data, me, + context); UNLOCK(); } +#if defined(GC_ENABLE_SUSPEND_THREAD) && defined(SIGNAL_BASED_STOP_WORLD) + GC_INNER void GC_suspend_self_blocked(ptr_t thread_me, void *context) + { + GC_ASSERT(I_HOLD_LOCK()); + (void)do_blocking_locked(GC_suspend_self_inner /* or a no-op function */, + thread_me, (GC_thread)thread_me, context); + } +#endif + GC_API void GC_CALL GC_set_stackbottom(void *gc_thread_handle, const struct GC_stack_base *sb) { @@ -2034,9 +2052,7 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) # if defined(GC_ENABLE_SUSPEND_THREAD) \ && defined(SIGNAL_BASED_STOP_WORLD) if (me -> suspended_ext) { - UNLOCK(); - (void)GC_do_blocking(GC_suspend_self_inner, me); - return GC_SUCCESS; + GC_with_callee_saves_pushed(GC_suspend_self_blocked, (ptr_t)me); } # endif UNLOCK(); |