mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 03:30:27 +02:00
Add call_without_gc API
This lets us call pthread_join safely
This commit is contained in:
parent
680032fa89
commit
6300203738
4 changed files with 70 additions and 3 deletions
8
bdw.h
8
bdw.h
|
@ -158,6 +158,14 @@ static void finish_gc_for_thread(struct mutator *mut) {
|
||||||
GC_unregister_my_thread();
|
GC_unregister_my_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* call_without_gc(struct mutator *mut, void* (*f)(void*),
|
||||||
|
void *data) NEVER_INLINE;
|
||||||
|
static void* call_without_gc(struct mutator *mut,
|
||||||
|
void* (*f)(void*),
|
||||||
|
void *data) {
|
||||||
|
return GC_do_blocking(f, data);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void print_start_gc_stats(struct heap *heap) {
|
static inline void print_start_gc_stats(struct heap *heap) {
|
||||||
}
|
}
|
||||||
static inline void print_end_gc_stats(struct heap *heap) {
|
static inline void print_end_gc_stats(struct heap *heap) {
|
||||||
|
|
44
mark-sweep.h
44
mark-sweep.h
|
@ -125,6 +125,7 @@ struct mark_space {
|
||||||
size_t mem_size;
|
size_t mem_size;
|
||||||
long count;
|
long count;
|
||||||
struct marker marker;
|
struct marker marker;
|
||||||
|
struct mutator *deactivated_mutators;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct heap {
|
struct heap {
|
||||||
|
@ -144,6 +145,7 @@ struct mutator {
|
||||||
struct heap *heap;
|
struct heap *heap;
|
||||||
struct handle *roots;
|
struct handle *roots;
|
||||||
struct mutator_mark_buf mark_buf;
|
struct mutator_mark_buf mark_buf;
|
||||||
|
struct mutator *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct marker* mark_space_marker(struct mark_space *space) {
|
static inline struct marker* mark_space_marker(struct mark_space *space) {
|
||||||
|
@ -352,6 +354,11 @@ static void wait_for_mutators_to_stop(struct mark_space *space) {
|
||||||
pthread_cond_wait(&space->collector_cond, &space->lock);
|
pthread_cond_wait(&space->collector_cond, &space->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mark_inactive_mutators(struct mark_space *space) {
|
||||||
|
for (struct mutator *mut = space->deactivated_mutators; mut; mut = mut->next)
|
||||||
|
mark_controlling_mutator_roots(mut);
|
||||||
|
}
|
||||||
|
|
||||||
static void mark_global_roots(struct mark_space *space) {
|
static void mark_global_roots(struct mark_space *space) {
|
||||||
for (struct handle *h = space->global_roots; h; h = h->next) {
|
for (struct handle *h = space->global_roots; h; h = h->next) {
|
||||||
struct gcobj *obj = h->v;
|
struct gcobj *obj = h->v;
|
||||||
|
@ -424,6 +431,7 @@ static void collect(struct mark_space *space, struct mutator *mut) {
|
||||||
request_mutators_to_stop(space);
|
request_mutators_to_stop(space);
|
||||||
mark_controlling_mutator_roots(mut);
|
mark_controlling_mutator_roots(mut);
|
||||||
wait_for_mutators_to_stop(space);
|
wait_for_mutators_to_stop(space);
|
||||||
|
mark_inactive_mutators(space);
|
||||||
mark_global_roots(space);
|
mark_global_roots(space);
|
||||||
marker_trace(space);
|
marker_trace(space);
|
||||||
marker_release(space);
|
marker_release(space);
|
||||||
|
@ -834,6 +842,42 @@ static void finish_gc_for_thread(struct mutator *mut) {
|
||||||
free(mut);
|
free(mut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void deactivate_mutator(struct mark_space *space, struct mutator *mut) {
|
||||||
|
ASSERT(mut->next == NULL);
|
||||||
|
mark_space_lock(space);
|
||||||
|
mut->next = space->deactivated_mutators;
|
||||||
|
space->deactivated_mutators = mut;
|
||||||
|
space->active_mutator_count--;
|
||||||
|
if (!space->active_mutator_count && mutators_are_stopping(space))
|
||||||
|
pthread_cond_signal(&space->collector_cond);
|
||||||
|
mark_space_unlock(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reactivate_mutator(struct mark_space *space, struct mutator *mut) {
|
||||||
|
mark_space_lock(space);
|
||||||
|
while (mutators_are_stopping(space))
|
||||||
|
pthread_cond_wait(&space->mutator_cond, &space->lock);
|
||||||
|
struct mutator **prev = &space->deactivated_mutators;
|
||||||
|
while (*prev != mut)
|
||||||
|
prev = &(*prev)->next;
|
||||||
|
*prev = mut->next;
|
||||||
|
mut->next = NULL;
|
||||||
|
space->active_mutator_count++;
|
||||||
|
mark_space_unlock(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* call_without_gc(struct mutator *mut, void* (*f)(void*),
|
||||||
|
void *data) NEVER_INLINE;
|
||||||
|
static void* call_without_gc(struct mutator *mut,
|
||||||
|
void* (*f)(void*),
|
||||||
|
void *data) {
|
||||||
|
struct mark_space *space = mutator_mark_space(mut);
|
||||||
|
deactivate_mutator(space, mut);
|
||||||
|
void *ret = f(data);
|
||||||
|
reactivate_mutator(space, mut);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void print_start_gc_stats(struct heap *heap) {
|
static inline void print_start_gc_stats(struct heap *heap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
mt-gcbench.c
15
mt-gcbench.c
|
@ -297,6 +297,14 @@ static void* run_one_test_in_thread(void *arg) {
|
||||||
return call_with_gc(run_one_test, heap);
|
return call_with_gc(run_one_test, heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct join_data { int status; pthread_t thread; };
|
||||||
|
static void *join_thread(void *data) {
|
||||||
|
struct join_data *join_data = data;
|
||||||
|
void *ret;
|
||||||
|
join_data->status = pthread_join(join_data->thread, &ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// Define size of Node without any GC header.
|
// Define size of Node without any GC header.
|
||||||
size_t sizeof_node = 2 * sizeof(Node*) + 2 * sizeof(int);
|
size_t sizeof_node = 2 * sizeof(Node*) + 2 * sizeof(int);
|
||||||
|
@ -350,9 +358,10 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
run_one_test(mut);
|
run_one_test(mut);
|
||||||
for (size_t i = 1; i < nthreads; i++) {
|
for (size_t i = 1; i < nthreads; i++) {
|
||||||
int status = pthread_join(threads[i], NULL);
|
struct join_data data = { 0, threads[i] };
|
||||||
if (status) {
|
call_without_gc(mut, join_thread, &data);
|
||||||
errno = status;
|
if (data.status) {
|
||||||
|
errno = data.status;
|
||||||
perror("Failed to join thread");
|
perror("Failed to join thread");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
6
semi.h
6
semi.h
|
@ -204,6 +204,12 @@ static struct mutator* initialize_gc_for_thread(uintptr_t *stack_base,
|
||||||
static void finish_gc_for_thread(struct mutator *space) {
|
static void finish_gc_for_thread(struct mutator *space) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* call_without_gc(struct mutator *mut, void* (*f)(void*),
|
||||||
|
void *data) {
|
||||||
|
// Can't be threads, then there won't be collection.
|
||||||
|
return f(data);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void print_start_gc_stats(struct heap *heap) {
|
static inline void print_start_gc_stats(struct heap *heap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue