summaryrefslogtreecommitdiff
path: root/pthread_support.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-04-11 08:25:51 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-04-11 20:59:49 +0300
commitb3af80d5f6f2f41ba57659f72d667b003a3274bd (patch)
treed69061f58827da313b3f032b28d9992ac01d2b2c /pthread_support.c
parenta646d031e70e5f30cf15153299914afb03992159 (diff)
downloadbdwgc-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.c38
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();