diff options
Diffstat (limited to 'libguile/whippet/src/mmc.c')
-rw-r--r-- | libguile/whippet/src/mmc.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/libguile/whippet/src/mmc.c b/libguile/whippet/src/mmc.c index 1ae342f5e..4e79675cc 100644 --- a/libguile/whippet/src/mmc.c +++ b/libguile/whippet/src/mmc.c @@ -88,6 +88,7 @@ struct gc_mutator { void *event_listener_data; struct gc_mutator *next; struct gc_mutator *prev; + int active; }; struct gc_trace_worker_data { @@ -216,6 +217,7 @@ add_mutator(struct gc_heap *heap, struct gc_mutator *mut) { while (mutators_are_stopping(heap)) pthread_cond_wait(&heap->mutator_cond, &heap->lock); mut->next = mut->prev = NULL; + mut->active = 1; struct gc_mutator *tail = heap->mutators; if (tail) { mut->next = tail; @@ -235,6 +237,7 @@ remove_mutator(struct gc_heap *heap, struct gc_mutator *mut) { mut->heap = NULL; heap_lock(heap); heap->mutator_count--; + mut->active = 0; if (mut->next) mut->next->prev = mut->prev; if (mut->prev) @@ -325,7 +328,8 @@ load_conservative_ref(uintptr_t addr) { static inline void trace_conservative_edges(uintptr_t low, uintptr_t high, int possibly_interior, - struct gc_heap *heap, struct gc_trace_worker *worker) { + struct gc_heap *heap, void *data) { + struct gc_trace_worker *worker = data; GC_ASSERT(low == align_down(low, sizeof(uintptr_t))); GC_ASSERT(high == align_down(high, sizeof(uintptr_t))); for (uintptr_t addr = low; addr < high; addr += sizeof(uintptr_t)) @@ -399,6 +403,14 @@ trace_root(struct gc_root root, struct gc_heap *heap, gc_field_set_visit_edge_buffer(&heap->remembered_set, root.edge_buffer, trace_remembered_edge, heap, worker); break; + case GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS: + gc_trace_heap_conservative_roots(root.heap->roots, trace_conservative_edges, + heap, worker); + break; + case GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS: + gc_trace_mutator_conservative_roots(root.mutator->roots, + trace_conservative_edges, heap, worker); + break; default: GC_CRASH(); } @@ -636,9 +648,13 @@ enqueue_mutator_conservative_roots(struct gc_heap *heap) { int possibly_interior = gc_mutator_conservative_roots_may_be_interior(); for (struct gc_mutator *mut = heap->mutators; mut; - mut = mut->next) + mut = mut->next) { gc_stack_visit(&mut->stack, enqueue_conservative_roots, heap, &possibly_interior); + if (mut->roots) + gc_tracer_add_root(&heap->tracer, + gc_root_mutator_conservative_roots(mut)); + } return 1; } return 0; @@ -650,6 +666,8 @@ enqueue_global_conservative_roots(struct gc_heap *heap) { int possibly_interior = 0; gc_platform_visit_global_conservative_roots (enqueue_conservative_roots, heap, &possibly_interior); + if (heap->roots) + gc_tracer_add_root(&heap->tracer, gc_root_heap_conservative_roots(heap)); return 1; } return 0; @@ -869,6 +887,10 @@ gc_safepoint_slow(struct gc_mutator *mut) { heap_unlock(heap); } +int gc_safepoint_signal_number(void) { GC_CRASH(); } +void gc_safepoint_signal_inhibit(struct gc_mutator *mut) { GC_CRASH(); } +void gc_safepoint_signal_reallow(struct gc_mutator *mut) { GC_CRASH(); } + static enum gc_trace_kind compute_trace_kind(enum gc_allocation_kind kind) { if (GC_CONSERVATIVE_TRACE) { @@ -1274,6 +1296,7 @@ deactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) { gc_field_set_writer_release_buffer(&mut->logger); heap_lock(heap); heap->inactive_mutator_count++; + mut->active = 0; gc_stack_capture_hot(&mut->stack); if (all_mutators_stopped(heap)) pthread_cond_signal(&heap->collector_cond); @@ -1285,15 +1308,42 @@ reactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) { heap_lock(heap); while (mutators_are_stopping(heap)) pthread_cond_wait(&heap->mutator_cond, &heap->lock); + mut->active = 1; heap->inactive_mutator_count--; heap_unlock(heap); } +void gc_deactivate(struct gc_mutator *mut) { + GC_ASSERT(mut->active); + deactivate_mutator(mutator_heap(mut), mut); +} + +void gc_reactivate(struct gc_mutator *mut) { + GC_ASSERT(!mut->active); + reactivate_mutator(mutator_heap(mut), mut); +} + void* -gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*), void *data) { +gc_deactivate_for_call(struct gc_mutator *mut, + void* (*f)(struct gc_mutator*, void*), + void *data) { struct gc_heap *heap = mutator_heap(mut); deactivate_mutator(heap, mut); - void *ret = f(data); + void *ret = f(mut, data); reactivate_mutator(heap, mut); return ret; } + +void* +gc_reactivate_for_call(struct gc_mutator *mut, + void* (*f)(struct gc_mutator*, void*), + void *data) { + struct gc_heap *heap = mutator_heap(mut); + int reactivate = !mut->active; + if (reactivate) + reactivate_mutator(heap, mut); + void *ret = f(mut, data); + if (reactivate) + deactivate_mutator(heap, mut); + return ret; +} |