summaryrefslogtreecommitdiff
path: root/libguile/loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'libguile/loader.c')
-rw-r--r--libguile/loader.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/libguile/loader.c b/libguile/loader.c
index 09bd166ec..fd2a04609 100644
--- a/libguile/loader.c
+++ b/libguile/loader.c
@@ -37,18 +37,19 @@
#include <sys/mman.h>
#endif
-#include "bdw-gc.h"
#include "boolean.h"
#include "bytevectors.h"
#include "elf.h"
#include "eval.h"
#include "extensions.h"
#include "gsubr.h"
+#include "gc-internal.h"
#include "list.h"
#include "pairs.h"
#include "programs.h"
#include "strings.h"
#include "threads.h"
+#include "trace.h"
#include "version.h"
#include "loader.h"
@@ -93,6 +94,43 @@
#define ELFDATA ELFDATA2LSB
#endif
+static scm_i_pthread_mutex_t roots_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
+static size_t roots_count = 0;
+static size_t roots_capacity = 0;
+struct loader_roots { uintptr_t lo, hi; };
+static struct loader_roots *roots;
+
+static void
+add_roots(char *lo, char *hi)
+{
+ scm_i_pthread_mutex_lock (&roots_lock);
+ if (roots_count == roots_capacity)
+ {
+ roots_capacity = roots_capacity * 2 + 128;
+ size_t elt_size = sizeof(*roots);
+ struct loader_roots *new_roots = calloc (roots_capacity, elt_size);
+ // Leak the old roots; we're still O(n) as all previous root
+ // arrays sum to less than the new roots_capacity.
+ memcpy (new_roots, roots, roots_count * elt_size);
+ roots = new_roots;
+ }
+ roots[roots_count++] = (struct loader_roots){ (uintptr_t)lo, (uintptr_t)hi };
+ scm_i_pthread_mutex_unlock (&roots_lock);
+}
+
+void
+scm_trace_loader_conservative_roots (void (*trace_range)(uintptr_t lo,
+ uintptr_t hi,
+ int possibly_interior,
+ struct gc_heap *heap,
+ void *trace_data),
+ struct gc_heap *heap,
+ void *trace_data)
+{
+ for (size_t i = 0; i < roots_count; i++)
+ trace_range(roots[i].lo, roots[i].hi, 0, heap, trace_data);
+}
+
/* The page size. */
static size_t page_size;
@@ -345,7 +383,7 @@ process_dynamic_segment (char *base, Elf_Phdr *dyn_phdr,
}
if (gc_root)
- GC_add_roots (gc_root, gc_root + gc_root_size);
+ add_roots (gc_root, gc_root + gc_root_size);
*init_out = init ? pointer_to_procedure (bytecode_kind, init) : SCM_BOOL_F;
*entry_out = pointer_to_procedure (bytecode_kind, entry);