Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Unity-Technologies/bdwgc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Chambers <joncham@gmail.com>2021-10-05 15:21:50 +0300
committerGitHub <noreply@github.com>2021-10-05 15:21:50 +0300
commit1032fe80d582aa4b58415b84c257091d3172b3ad (patch)
tree1959cf176e325a0f2a74633ec01b3c421a74e631
parenta27eddb837d613cb4cf436405c23ce39ed16a86d (diff)
parent1a65adc46c3a71065de2cf056d1e2edfbbd84c86 (diff)
Merge pull request #65 from Unity-Technologies/unity-master-ephemeron-callback
Add callback to support ephemeron marking in Mono.
-rw-r--r--include/gc_mark.h7
-rw-r--r--mark.c20
-rw-r--r--os_dep.c12
3 files changed, 37 insertions, 2 deletions
diff --git a/include/gc_mark.h b/include/gc_mark.h
index 108794de..2e468850 100644
--- a/include/gc_mark.h
+++ b/include/gc_mark.h
@@ -310,6 +310,13 @@ GC_API int GC_CALL GC_is_tmp_root(void *);
GC_API void GC_CALL GC_print_trace(GC_word /* gc_no */);
GC_API void GC_CALL GC_print_trace_inner(GC_word /* gc_no */);
+/* Set the client for when mark stack is empty. A client can use */
+/* this callback to process (un)marked objects and push additional */
+/* work onto the stack. Useful for implementing ephemerons. */
+typedef void (GC_CALLBACK* GC_mark_stack_empty_proc)(void);
+GC_API void GC_CALL GC_set_mark_stack_empty (GC_mark_stack_empty_proc);
+GC_API GC_mark_stack_empty_proc GC_CALL GC_get_mark_stack_empty (void);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/mark.c b/mark.c
index 72fdec6a..139ca2b9 100644
--- a/mark.c
+++ b/mark.c
@@ -116,6 +116,7 @@ GC_INNER size_t GC_mark_stack_size = 0;
GC_INNER mark_state_t GC_mark_state = MS_NONE;
GC_INNER GC_bool GC_mark_stack_too_small = FALSE;
+GC_INNER GC_bool GC_mark_stack_empty_called = FALSE;
static struct hblk * scan_ptr;
@@ -400,11 +401,26 @@ static void alloc_mark_stack(size_t);
MARK_FROM_MARK_STACK();
break;
} else {
- GC_mark_state = MS_NONE;
if (GC_mark_stack_too_small) {
+ GC_mark_state = MS_NONE;
alloc_mark_stack(2*GC_mark_stack_size);
+ return(TRUE);
+ } else {
+ GC_mark_stack_empty_proc mark_stack_empty_proc = GC_get_mark_stack_empty();
+ if (GC_mark_stack_empty_called || !mark_stack_empty_proc) {
+ GC_mark_state = MS_NONE;
+ GC_mark_stack_empty_called = FALSE;
+ return(TRUE);
+ } else {
+ if (mark_stack_empty_proc != 0)
+ mark_stack_empty_proc();
+
+ /* break below here loops us around the mark phase once again */
+ /* to process any items push by the callback */
+ GC_mark_stack_empty_called = TRUE;
+ }
}
- return(TRUE);
+ break;
}
case MS_INVALID:
diff --git a/os_dep.c b/os_dep.c
index 0158990b..ea65b02c 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -2798,6 +2798,18 @@ void GC_reset_default_push_other_roots(void)
#endif
}
+GC_push_other_roots_proc GC_on_mark_stack_empty;
+
+GC_API void GC_CALL GC_set_mark_stack_empty (GC_mark_stack_empty_proc fn)
+{
+ GC_on_mark_stack_empty = fn;
+}
+
+GC_API GC_mark_stack_empty_proc GC_CALL GC_get_mark_stack_empty (void)
+{
+ return GC_on_mark_stack_empty;
+}
+
/*
* Routines for accessing dirty bits on virtual pages.
* There are six ways to maintain this information: