summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-05-19 09:38:30 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-06-15 22:50:43 +0300
commitc5fb8828c247373200c80d33771bfa3c5956b8ed (patch)
treee92033169a2d5cbb3fcc3725c2f740812c0f3ee4
parentcbb38ea627b43703a81b38f1ef5f5b262cbba53b (diff)
downloadbdwgc-c5fb8828c247373200c80d33771bfa3c5956b8ed.tar.gz
Prevent changing of GC_markers_m1 value while collection in progress
GC_markers_m1 (GC_parallel) value affects some logic in the garbage collector, e.g. GC_clear_fl_marks, so it would be safer to wait for any ongoing collection before proceeding with marker threads creation (in the child). * pthread_support.c [PARALLEL_MARK && CAN_HANDLE_FORK] (GC_wait_for_gc_completion): Declare (before GC_start_mark_threads_inner). * pthread_support.c [PARALLEL_MARK] (GC_start_mark_threads_inner): Add assertion that cancellation is disabled. * win32_threads.c [PARALLEL_MARK] (GC_start_mark_threads_inner): Likewise. * pthread_support.c [PARALLEL_MARK && CAN_HANDLE_FORK] (GC_start_mark_threads_inner): Call GC_wait_for_gc_completion(TRUE) before initialization of mark_cv. * win32_threads.c [PARALLEL_MARK && GC_PTHREADS_PARAMARK && CAN_HANDLE_FORK] (GC_start_mark_threads_inner): Likewise.
-rw-r--r--pthread_support.c3
-rw-r--r--win32_threads.c3
2 files changed, 6 insertions, 0 deletions
diff --git a/pthread_support.c b/pthread_support.c
index fefb1ed6..7e6a13a3 100644
--- a/pthread_support.c
+++ b/pthread_support.c
@@ -383,6 +383,7 @@ STATIC pthread_t GC_mark_threads[MAX_MARKERS];
static int available_markers_m1 = 0;
static pthread_cond_t mark_cv;
/* initialized by GC_start_mark_threads_inner */
+ STATIC void GC_wait_for_gc_completion(GC_bool wait_for_all);
#else
# define available_markers_m1 GC_markers_m1
static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
@@ -397,10 +398,12 @@ GC_INNER void GC_start_mark_threads_inner(void)
# endif
GC_ASSERT(I_HOLD_LOCK());
+ ASSERT_CANCEL_DISABLED();
if (available_markers_m1 <= 0) return;
/* Skip if parallel markers disabled or already started. */
# ifdef CAN_HANDLE_FORK
if (GC_parallel) return;
+ GC_wait_for_gc_completion(TRUE);
/* Initialize mark_cv (for the first time), or cleanup its value */
/* after forking in the child process. All the marker threads in */
diff --git a/win32_threads.c b/win32_threads.c
index 7fcee339..196bc7bf 100644
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -2008,10 +2008,12 @@ GC_INNER void GC_get_next_stack(char *start, char *limit,
# endif
GC_ASSERT(I_HOLD_LOCK());
+ ASSERT_CANCEL_DISABLED();
if (available_markers_m1 <= 0) return;
/* Skip if parallel markers disabled or already started. */
# ifdef CAN_HANDLE_FORK
if (GC_parallel) return;
+ GC_wait_for_gc_completion(TRUE);
/* Reset mark_cv state after forking (as in pthread_support.c). */
{
@@ -2181,6 +2183,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit,
int i;
GC_ASSERT(I_HOLD_LOCK());
+ ASSERT_CANCEL_DISABLED();
if (available_markers_m1 <= 0) return;
GC_ASSERT(GC_fl_builder_count == 0);