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:
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,
|
||||
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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
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();
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
25
src/mmc.c
25
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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
28
src/pcc.c
28
src/pcc.c
|
@ -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;
|
||||
}
|
||||
|
|
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_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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue