1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-02 02:10:19 +02:00

Rework gc_call_without_gc to allow reentrancy

Rename to gc_deactivate_for_call / gc_reactivate_for_call
This commit is contained in:
Andy Wingo 2025-05-15 11:26:27 +02:00
parent d58aa71281
commit 675d8d649a
8 changed files with 93 additions and 21 deletions

View file

@ -53,8 +53,12 @@ GC_API_ void gc_heap_set_extern_space(struct gc_heap *heap,
GC_API_ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base,
struct gc_heap *heap);
GC_API_ void gc_finish_for_thread(struct gc_mutator *mut);
GC_API_ void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*),
void *data) GC_NEVER_INLINE;
GC_API_ void* gc_deactivate_for_call(struct gc_mutator *mut,
void* (*f)(struct gc_mutator*, void*),
void *data) GC_NEVER_INLINE;
GC_API_ void* gc_reactivate_for_call(struct gc_mutator *mut,
void* (*f)(struct gc_mutator*, void*),
void *data) GC_NEVER_INLINE;
GC_API_ void gc_collect(struct gc_mutator *mut,
enum gc_collection_kind requested_kind);

View file

@ -183,7 +183,7 @@ static void* run_one_test_in_thread(void *arg) {
}
struct join_data { int status; pthread_t thread; };
static void *join_thread(void *data) {
static void *join_thread(struct gc_mutator *unused, void *data) {
struct join_data *join_data = data;
void *ret;
join_data->status = pthread_join(join_data->thread, &ret);
@ -256,7 +256,7 @@ int main(int argc, char *argv[]) {
run_one_test(&main_thread);
for (size_t i = 1; i < nthreads; i++) {
struct join_data data = { 0, threads[i] };
gc_call_without_gc(mut, join_thread, &data);
gc_deactivate_for_call(mut, join_thread, &data);
if (data.status) {
errno = data.status;
perror("Failed to join thread");

View file

@ -190,7 +190,7 @@ static void* run_one_test_in_thread(void *arg) {
}
struct join_data { int status; pthread_t thread; };
static void *join_thread(void *data) {
static void *join_thread(struct gc_mutator *unused, void *data) {
struct join_data *join_data = data;
void *ret;
join_data->status = pthread_join(join_data->thread, &ret);
@ -263,7 +263,7 @@ int main(int argc, char *argv[]) {
ssize_t outstanding = (size_t)run_one_test(&main_thread);
for (size_t i = 1; i < nthreads; i++) {
struct join_data data = { 0, threads[i] };
void *ret = gc_call_without_gc(mut, join_thread, &data);
void *ret = gc_deactivate_for_call(mut, join_thread, &data);
if (data.status) {
errno = data.status;
perror("Failed to join thread");

View file

@ -319,7 +319,7 @@ static void* run_one_test_in_thread(void *arg) {
}
struct join_data { int status; pthread_t thread; };
static void *join_thread(void *data) {
static void *join_thread(struct gc_mutator *unused, void *data) {
struct join_data *join_data = data;
void *ret;
join_data->status = pthread_join(join_data->thread, &ret);
@ -389,7 +389,7 @@ int main(int argc, char *argv[]) {
run_one_test(&main_thread);
for (size_t i = 1; i < nthreads; i++) {
struct join_data data = { 0, threads[i] };
gc_call_without_gc(mut, join_thread, &data);
gc_deactivate_for_call(mut, join_thread, &data);
if (data.status) {
errno = data.status;
perror("Failed to join thread");

View file

@ -657,10 +657,29 @@ void gc_finish_for_thread(struct gc_mutator *mut) {
GC_unregister_my_thread();
}
void* gc_call_without_gc(struct gc_mutator *mut,
void* (*f)(void*),
void *data) {
return GC_do_blocking(f, data);
struct call_with_mutator_data {
void* (*proc) (struct gc_mutator*, void*);
struct gc_mutator *mutator;
void *data;
};
static void* call_with_mutator (void *p) {
struct call_with_mutator_data *data = p;
return data->proc(data->mutator, data->data);
}
void* gc_deactivate_for_call(struct gc_mutator *mut,
void* (*f)(struct gc_mutator *, void*),
void *data) {
struct call_with_mutator_data d = { f, mut, data };
return GC_do_blocking(call_with_mutator, &d);
}
void* gc_reactivate_for_call(struct gc_mutator *mut,
void* (*f)(struct gc_mutator *, void*),
void *data) {
struct call_with_mutator_data d = { f, mut, data };
return GC_call_with_gc_active(call_with_mutator, &d);
}
void gc_mutator_set_roots(struct gc_mutator *mut,

View file

@ -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)
@ -1277,6 +1280,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);
@ -1288,15 +1292,32 @@ 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_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;
}

View file

@ -96,6 +96,7 @@ struct gc_mutator {
void *event_listener_data;
struct gc_mutator *next;
struct gc_mutator *prev;
int active;
};
struct gc_trace_worker_data {
@ -501,6 +502,7 @@ static void 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;
@ -520,6 +522,7 @@ static void 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)
@ -1357,31 +1360,48 @@ void gc_finish_for_thread(struct gc_mutator *mut) {
static void deactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
GC_ASSERT(mut->next == NULL);
GC_ASSERT(mut->active);
copy_space_allocator_finish(&mut->allocator, heap_allocation_space(heap));
if (GC_GENERATIONAL)
gc_field_set_writer_release_buffer(mutator_field_logger(mut));
heap_lock(heap);
heap->inactive_mutator_count++;
mut->active = 0;
if (all_mutators_stopped(heap))
pthread_cond_signal(&heap->collector_cond);
heap_unlock(heap);
}
static void reactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
GC_ASSERT(!mut->active);
heap_lock(heap);
while (mutators_are_stopping(heap))
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
mut->active = 1;
heap->inactive_mutator_count--;
maybe_increase_max_active_mutator_count(heap);
heap_unlock(heap);
}
void* gc_call_without_gc(struct gc_mutator *mut,
void* (*f)(void*),
void *data) {
void* 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;
}

View file

@ -763,8 +763,16 @@ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base,
void gc_finish_for_thread(struct gc_mutator *space) {
}
void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*),
void *data) {
void* gc_deactivate_for_call(struct gc_mutator *mut,
void* (*f)(struct gc_mutator *, void*),
void *data) {
// Can't be threads, then there won't be collection.
return f(data);
return f(mut, data);
}
void* gc_reactivate_for_call(struct gc_mutator *mut,
void* (*f)(struct gc_mutator *mut, void*),
void *data) {
// Can't be threads, then there won't be collection.
return f(mut, data);
}