mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-03 18:50: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:
parent
d58aa71281
commit
675d8d649a
8 changed files with 93 additions and 21 deletions
|
@ -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,
|
GC_API_ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base,
|
||||||
struct gc_heap *heap);
|
struct gc_heap *heap);
|
||||||
GC_API_ void gc_finish_for_thread(struct gc_mutator *mut);
|
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*),
|
GC_API_ void* gc_deactivate_for_call(struct gc_mutator *mut,
|
||||||
void *data) GC_NEVER_INLINE;
|
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,
|
GC_API_ void gc_collect(struct gc_mutator *mut,
|
||||||
enum gc_collection_kind requested_kind);
|
enum gc_collection_kind requested_kind);
|
||||||
|
|
|
@ -183,7 +183,7 @@ static void* run_one_test_in_thread(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct join_data { int status; pthread_t thread; };
|
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;
|
struct join_data *join_data = data;
|
||||||
void *ret;
|
void *ret;
|
||||||
join_data->status = pthread_join(join_data->thread, &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);
|
run_one_test(&main_thread);
|
||||||
for (size_t i = 1; i < nthreads; i++) {
|
for (size_t i = 1; i < nthreads; i++) {
|
||||||
struct join_data data = { 0, threads[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) {
|
if (data.status) {
|
||||||
errno = data.status;
|
errno = data.status;
|
||||||
perror("Failed to join thread");
|
perror("Failed to join thread");
|
||||||
|
|
|
@ -190,7 +190,7 @@ static void* run_one_test_in_thread(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct join_data { int status; pthread_t thread; };
|
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;
|
struct join_data *join_data = data;
|
||||||
void *ret;
|
void *ret;
|
||||||
join_data->status = pthread_join(join_data->thread, &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);
|
ssize_t outstanding = (size_t)run_one_test(&main_thread);
|
||||||
for (size_t i = 1; i < nthreads; i++) {
|
for (size_t i = 1; i < nthreads; i++) {
|
||||||
struct join_data data = { 0, threads[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) {
|
if (data.status) {
|
||||||
errno = data.status;
|
errno = data.status;
|
||||||
perror("Failed to join thread");
|
perror("Failed to join thread");
|
||||||
|
|
|
@ -319,7 +319,7 @@ static void* run_one_test_in_thread(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct join_data { int status; pthread_t thread; };
|
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;
|
struct join_data *join_data = data;
|
||||||
void *ret;
|
void *ret;
|
||||||
join_data->status = pthread_join(join_data->thread, &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);
|
run_one_test(&main_thread);
|
||||||
for (size_t i = 1; i < nthreads; i++) {
|
for (size_t i = 1; i < nthreads; i++) {
|
||||||
struct join_data data = { 0, threads[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) {
|
if (data.status) {
|
||||||
errno = data.status;
|
errno = data.status;
|
||||||
perror("Failed to join thread");
|
perror("Failed to join thread");
|
||||||
|
|
27
src/bdw.c
27
src/bdw.c
|
@ -657,10 +657,29 @@ void gc_finish_for_thread(struct gc_mutator *mut) {
|
||||||
GC_unregister_my_thread();
|
GC_unregister_my_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* gc_call_without_gc(struct gc_mutator *mut,
|
struct call_with_mutator_data {
|
||||||
void* (*f)(void*),
|
void* (*proc) (struct gc_mutator*, void*);
|
||||||
void *data) {
|
struct gc_mutator *mutator;
|
||||||
return GC_do_blocking(f, data);
|
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,
|
void gc_mutator_set_roots(struct gc_mutator *mut,
|
||||||
|
|
25
src/mmc.c
25
src/mmc.c
|
@ -88,6 +88,7 @@ struct gc_mutator {
|
||||||
void *event_listener_data;
|
void *event_listener_data;
|
||||||
struct gc_mutator *next;
|
struct gc_mutator *next;
|
||||||
struct gc_mutator *prev;
|
struct gc_mutator *prev;
|
||||||
|
int active;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gc_trace_worker_data {
|
struct gc_trace_worker_data {
|
||||||
|
@ -216,6 +217,7 @@ add_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
||||||
while (mutators_are_stopping(heap))
|
while (mutators_are_stopping(heap))
|
||||||
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
||||||
mut->next = mut->prev = NULL;
|
mut->next = mut->prev = NULL;
|
||||||
|
mut->active = 1;
|
||||||
struct gc_mutator *tail = heap->mutators;
|
struct gc_mutator *tail = heap->mutators;
|
||||||
if (tail) {
|
if (tail) {
|
||||||
mut->next = tail;
|
mut->next = tail;
|
||||||
|
@ -235,6 +237,7 @@ remove_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
||||||
mut->heap = NULL;
|
mut->heap = NULL;
|
||||||
heap_lock(heap);
|
heap_lock(heap);
|
||||||
heap->mutator_count--;
|
heap->mutator_count--;
|
||||||
|
mut->active = 0;
|
||||||
if (mut->next)
|
if (mut->next)
|
||||||
mut->next->prev = mut->prev;
|
mut->next->prev = mut->prev;
|
||||||
if (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);
|
gc_field_set_writer_release_buffer(&mut->logger);
|
||||||
heap_lock(heap);
|
heap_lock(heap);
|
||||||
heap->inactive_mutator_count++;
|
heap->inactive_mutator_count++;
|
||||||
|
mut->active = 0;
|
||||||
gc_stack_capture_hot(&mut->stack);
|
gc_stack_capture_hot(&mut->stack);
|
||||||
if (all_mutators_stopped(heap))
|
if (all_mutators_stopped(heap))
|
||||||
pthread_cond_signal(&heap->collector_cond);
|
pthread_cond_signal(&heap->collector_cond);
|
||||||
|
@ -1288,15 +1292,32 @@ reactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
||||||
heap_lock(heap);
|
heap_lock(heap);
|
||||||
while (mutators_are_stopping(heap))
|
while (mutators_are_stopping(heap))
|
||||||
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
||||||
|
mut->active = 1;
|
||||||
heap->inactive_mutator_count--;
|
heap->inactive_mutator_count--;
|
||||||
heap_unlock(heap);
|
heap_unlock(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
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);
|
struct gc_heap *heap = mutator_heap(mut);
|
||||||
deactivate_mutator(heap, mut);
|
deactivate_mutator(heap, mut);
|
||||||
void *ret = f(data);
|
void *ret = f(mut, data);
|
||||||
reactivate_mutator(heap, mut);
|
reactivate_mutator(heap, mut);
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
|
28
src/pcc.c
28
src/pcc.c
|
@ -96,6 +96,7 @@ struct gc_mutator {
|
||||||
void *event_listener_data;
|
void *event_listener_data;
|
||||||
struct gc_mutator *next;
|
struct gc_mutator *next;
|
||||||
struct gc_mutator *prev;
|
struct gc_mutator *prev;
|
||||||
|
int active;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gc_trace_worker_data {
|
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))
|
while (mutators_are_stopping(heap))
|
||||||
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
||||||
mut->next = mut->prev = NULL;
|
mut->next = mut->prev = NULL;
|
||||||
|
mut->active = 1;
|
||||||
struct gc_mutator *tail = heap->mutators;
|
struct gc_mutator *tail = heap->mutators;
|
||||||
if (tail) {
|
if (tail) {
|
||||||
mut->next = tail;
|
mut->next = tail;
|
||||||
|
@ -520,6 +522,7 @@ static void remove_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
||||||
mut->heap = NULL;
|
mut->heap = NULL;
|
||||||
heap_lock(heap);
|
heap_lock(heap);
|
||||||
heap->mutator_count--;
|
heap->mutator_count--;
|
||||||
|
mut->active = 0;
|
||||||
if (mut->next)
|
if (mut->next)
|
||||||
mut->next->prev = mut->prev;
|
mut->next->prev = mut->prev;
|
||||||
if (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) {
|
static void deactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
||||||
GC_ASSERT(mut->next == NULL);
|
GC_ASSERT(mut->next == NULL);
|
||||||
|
GC_ASSERT(mut->active);
|
||||||
copy_space_allocator_finish(&mut->allocator, heap_allocation_space(heap));
|
copy_space_allocator_finish(&mut->allocator, heap_allocation_space(heap));
|
||||||
if (GC_GENERATIONAL)
|
if (GC_GENERATIONAL)
|
||||||
gc_field_set_writer_release_buffer(mutator_field_logger(mut));
|
gc_field_set_writer_release_buffer(mutator_field_logger(mut));
|
||||||
heap_lock(heap);
|
heap_lock(heap);
|
||||||
heap->inactive_mutator_count++;
|
heap->inactive_mutator_count++;
|
||||||
|
mut->active = 0;
|
||||||
if (all_mutators_stopped(heap))
|
if (all_mutators_stopped(heap))
|
||||||
pthread_cond_signal(&heap->collector_cond);
|
pthread_cond_signal(&heap->collector_cond);
|
||||||
heap_unlock(heap);
|
heap_unlock(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
static void reactivate_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
|
||||||
|
GC_ASSERT(!mut->active);
|
||||||
heap_lock(heap);
|
heap_lock(heap);
|
||||||
while (mutators_are_stopping(heap))
|
while (mutators_are_stopping(heap))
|
||||||
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
pthread_cond_wait(&heap->mutator_cond, &heap->lock);
|
||||||
|
mut->active = 1;
|
||||||
heap->inactive_mutator_count--;
|
heap->inactive_mutator_count--;
|
||||||
maybe_increase_max_active_mutator_count(heap);
|
maybe_increase_max_active_mutator_count(heap);
|
||||||
heap_unlock(heap);
|
heap_unlock(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* gc_call_without_gc(struct gc_mutator *mut,
|
void* gc_deactivate_for_call(struct gc_mutator *mut,
|
||||||
void* (*f)(void*),
|
void* (*f)(struct gc_mutator*, void*),
|
||||||
void *data) {
|
void *data) {
|
||||||
struct gc_heap *heap = mutator_heap(mut);
|
struct gc_heap *heap = mutator_heap(mut);
|
||||||
deactivate_mutator(heap, mut);
|
deactivate_mutator(heap, mut);
|
||||||
void *ret = f(data);
|
void *ret = f(mut, data);
|
||||||
reactivate_mutator(heap, mut);
|
reactivate_mutator(heap, mut);
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
|
14
src/semi.c
14
src/semi.c
|
@ -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_finish_for_thread(struct gc_mutator *space) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*),
|
void* gc_deactivate_for_call(struct gc_mutator *mut,
|
||||||
void *data) {
|
void* (*f)(struct gc_mutator *, void*),
|
||||||
|
void *data) {
|
||||||
// Can't be threads, then there won't be collection.
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue