Places GC cleanup on place termination
This commit is contained in:
parent
ac8aa01a48
commit
1ce41d49f4
|
@ -413,6 +413,11 @@ GC2_EXTERN void GC_construct_child_gc();
|
||||||
Creates a new place specific GC and links to the master GC.
|
Creates a new place specific GC and links to the master GC.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
GC2_EXTERN void GC_destruct_child_gc();
|
||||||
|
/*
|
||||||
|
Destroys a place specific GC once the place has finished.
|
||||||
|
*/
|
||||||
|
|
||||||
GC2_EXTERN void *GC_switch_to_master_gc();
|
GC2_EXTERN void *GC_switch_to_master_gc();
|
||||||
/*
|
/*
|
||||||
Switches to the master GC
|
Switches to the master GC
|
||||||
|
|
|
@ -1876,82 +1876,66 @@ void GC_write_barrier(void *p)
|
||||||
|
|
||||||
#ifdef MZ_USE_PLACES
|
#ifdef MZ_USE_PLACES
|
||||||
static void NewGCMasterInfo_initialize() {
|
static void NewGCMasterInfo_initialize() {
|
||||||
|
int i;
|
||||||
MASTERGCINFO = ofm_malloc_zero(sizeof(NewGCMasterInfo));
|
MASTERGCINFO = ofm_malloc_zero(sizeof(NewGCMasterInfo));
|
||||||
|
MASTERGCINFO->size = 32;
|
||||||
|
MASTERGCINFO->alive = 0;
|
||||||
|
MASTERGCINFO->ready = 0;
|
||||||
|
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->size);
|
||||||
|
for (i=0; i < 32; i++ ) {
|
||||||
|
MASTERGCINFO->signal_fds[i] = (void *)-2;
|
||||||
|
}
|
||||||
mzrt_rwlock_create(&MASTERGCINFO->cangc);
|
mzrt_rwlock_create(&MASTERGCINFO->cangc);
|
||||||
mzrt_sema_create(&MASTERGCINFO->wait_sema, 0);
|
mzrt_sema_create(&MASTERGCINFO->wait_sema, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NewGCMasterInfo_cleanup() {
|
static void NewGCMasterInfo_cleanup() {
|
||||||
mzrt_rwlock_destroy(MASTERGCINFO->cangc);
|
mzrt_rwlock_destroy(MASTERGCINFO->cangc);
|
||||||
|
free(MASTERGCINFO->signal_fds);
|
||||||
free(MASTERGCINFO);
|
free(MASTERGCINFO);
|
||||||
MASTERGCINFO = NULL;
|
MASTERGCINFO = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NewGCMasterInfo_set_have_collected(NewGC *gc) {
|
|
||||||
MASTERGCINFO->have_collected[gc->place_id] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* signals every place to do a full gc at then end of
|
/* signals every place to do a full gc at then end of
|
||||||
garbage_collect the places will call
|
garbage_collect the places will call
|
||||||
wait_if_master_in_progress and
|
wait_if_master_in_progress and
|
||||||
rendezvous for a master gc */
|
rendezvous for a master gc */
|
||||||
|
/* this is only called from the master so the cangc lock should already be held */
|
||||||
static void master_collect_initiate() {
|
static void master_collect_initiate() {
|
||||||
if (MASTERGC->major_places_gc == 0) {
|
if (MASTERGC->major_places_gc == 0) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int maxid = MASTERGCINFO->next_GC_id;
|
int size = MASTERGCINFO->size;
|
||||||
|
int count = 0;
|
||||||
MASTERGC->major_places_gc = 1;
|
MASTERGC->major_places_gc = 1;
|
||||||
|
MASTERGCINFO->ready = 0;
|
||||||
|
|
||||||
for (i=1; i < maxid; i++) {
|
for (i=1; i < size; i++) {
|
||||||
void *signal_fd = MASTERGCINFO->signal_fds[i];
|
void *signal_fd = MASTERGCINFO->signal_fds[i];
|
||||||
MASTERGCINFO->have_collected[i] = -1;
|
if (signal_fd < (void*) -2) {
|
||||||
if (signal_fd >= 0 ) {
|
|
||||||
scheme_signal_received_at(signal_fd);
|
scheme_signal_received_at(signal_fd);
|
||||||
}
|
|
||||||
#if defined(DEBUG_GC_PAGES)
|
#if defined(DEBUG_GC_PAGES)
|
||||||
printf("%i SIGNALED BUT NOT COLLECTED\n", i);
|
printf("%i SIGNALED BUT NOT COLLECTED\n", i);
|
||||||
GCVERBOSEprintf("%i SIGNALED BUT NOT COLLECTED\n", i);
|
GCVERBOSEprintf("%i SIGNALED BUT NOT COLLECTED\n", i);
|
||||||
#endif
|
#endif
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
if (count == (MASTERGCINFO->alive -1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count != (MASTERGCINFO->alive -1)) {
|
||||||
|
printf("GC2 count != MASTERGCINFO->alive %i %li\n", count, MASTERGCINFO->alive);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_GC_PAGES)
|
||||||
|
printf("Woke up %i places for MASTER GC\n", count);
|
||||||
|
GCVERBOSEprintf("Woke up %i places for MASTER GC\n", count);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void collect_master() {
|
||||||
static void wait_if_master_in_progress(NewGC *gc) {
|
|
||||||
if (MASTERGC->major_places_gc == 1) {
|
|
||||||
int last_one_here = 1;
|
|
||||||
|
|
||||||
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
|
||||||
GC_LOCK_DEBUG("MGCLOCK GC_switch_to_master_gc\n");
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
int maxid = MASTERGCINFO->next_GC_id;
|
|
||||||
|
|
||||||
NewGCMasterInfo_set_have_collected(gc);
|
|
||||||
for (i=1; i < maxid; i++) {
|
|
||||||
int have_collected = MASTERGCINFO->have_collected[i];
|
|
||||||
if (have_collected == 1) {
|
|
||||||
#if defined(DEBUG_GC_PAGES)
|
|
||||||
printf("%i READY\n", i);
|
|
||||||
GCVERBOSEprintf("%i READY\n", i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
#if defined(DEBUG_GC_PAGES)
|
|
||||||
printf("%i SIGNALED BUT NOT COLLECTED\n", i);
|
|
||||||
GCVERBOSEprintf("%i SIGNALED BUT NOT COLLECTED\n", i);
|
|
||||||
#endif
|
|
||||||
last_one_here = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (last_one_here) {
|
|
||||||
NewGC *saved_gc;
|
NewGC *saved_gc;
|
||||||
|
|
||||||
GC_LOCK_DEBUG("UNMGCLOCK GC_switch_to_master_gc\n");
|
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
|
||||||
|
|
||||||
|
|
||||||
saved_gc = GC_switch_to_master_gc();
|
saved_gc = GC_switch_to_master_gc();
|
||||||
{
|
{
|
||||||
#if defined(DEBUG_GC_PAGES)
|
#if defined(DEBUG_GC_PAGES)
|
||||||
|
@ -1967,44 +1951,105 @@ static void wait_if_master_in_progress(NewGC *gc) {
|
||||||
|
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int maxid = MASTERGCINFO->next_GC_id;
|
int alive = MASTERGCINFO->alive;
|
||||||
/* wake everyone back up */
|
/* wake everyone back up, except MASTERGC and ourself */
|
||||||
for (i=2; i < maxid; i++) {
|
for (i=2; i < alive; i++) {
|
||||||
mzrt_sema_post(MASTERGCINFO->wait_sema);
|
mzrt_sema_post(MASTERGCINFO->wait_sema);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GC_switch_back_from_master(saved_gc);
|
GC_switch_back_from_master(saved_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wait_if_master_in_progress(NewGC *gc) {
|
||||||
|
int last_one_here = -1;
|
||||||
|
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
||||||
|
GC_LOCK_DEBUG("MGCLOCK wait_if_master_in_progress\n");
|
||||||
|
{
|
||||||
|
if (MASTERGC->major_places_gc == 1) {
|
||||||
|
MASTERGCINFO->ready++;
|
||||||
|
#if defined(DEBUG_GC_PAGES)
|
||||||
|
printf("%i READY\n", gc->place_id);
|
||||||
|
GCVERBOSEprintf("%i READY\n", i);
|
||||||
|
#endif
|
||||||
|
/* don't count MASTERGC*/
|
||||||
|
if ((MASTERGCINFO->alive -1) == MASTERGCINFO->ready) {
|
||||||
|
last_one_here = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GC_LOCK_DEBUG("UNMGCLOCK GC_switch_to_master_gc\n");
|
last_one_here = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last_one_here = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GC_LOCK_DEBUG("UNMGCLOCK wait_if_master_in_progress\n");
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
||||||
|
|
||||||
/* wait on semaphonre */
|
switch(last_one_here) {
|
||||||
|
case -1:
|
||||||
|
/* master doesn't want to collect */
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/* wait on semaphore */
|
||||||
mzrt_sema_wait(MASTERGCINFO->wait_sema);
|
mzrt_sema_wait(MASTERGCINFO->wait_sema);
|
||||||
}
|
break;
|
||||||
|
case 1:
|
||||||
|
/* Your the last one here. */
|
||||||
|
collect_master();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("GC2 wait_if_master_in_progress invalid case, unreachable\n");
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NewGCMasterInfo_get_next_id(NewGC *newgc) {
|
/* MUST CALL WITH cangc lock */
|
||||||
int newid;
|
static long NewGCMasterInfo_find_free_id() {
|
||||||
/* this could just be an atomic op if we had those */
|
GC_ASSERT(MASTERGCINFO->live <= MASTERGCINFO->size);
|
||||||
/* waiting for other threads to finish a possible concurrent GC is not optimal*/
|
if ((MASTERGCINFO->alive + 1) == MASTERGCINFO->size) {
|
||||||
|
MASTERGCINFO->size++;
|
||||||
|
MASTERGCINFO->alive++;
|
||||||
|
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->size);
|
||||||
|
return MASTERGCINFO->size - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int i;
|
||||||
|
int size = MASTERGCINFO->size;
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if (MASTERGCINFO->signal_fds[i] == (void*)-2) {
|
||||||
|
MASTERGCINFO->alive++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Error in MASTERGCINFO table\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NewGCMasterInfo_register_gc(NewGC *newgc) {
|
||||||
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
||||||
newid = MASTERGCINFO->next_GC_id++;
|
GC_LOCK_DEBUG("MGCLOCK NewGCMasterInfo_register_gc\n");
|
||||||
|
{
|
||||||
|
long newid = NewGCMasterInfo_find_free_id();
|
||||||
newgc->place_id = newid;
|
newgc->place_id = newid;
|
||||||
/* printf("ALLOCATED GC OID %li\n", newgc->place_id); */
|
|
||||||
MASTERGCINFO->have_collected = realloc(MASTERGCINFO->have_collected, sizeof(char) * MASTERGCINFO->next_GC_id);
|
|
||||||
MASTERGCINFO->signal_fds = realloc(MASTERGCINFO->signal_fds, sizeof(void*) * MASTERGCINFO->next_GC_id);
|
|
||||||
MASTERGCINFO->have_collected[newid] = 0;
|
|
||||||
MASTERGCINFO->signal_fds[newid] = (void *)-1;
|
MASTERGCINFO->signal_fds[newid] = (void *)-1;
|
||||||
|
}
|
||||||
|
GC_LOCK_DEBUG("UNMGCLOCK NewGCMasterInfo_register_gc\n");
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC_set_put_external_event_fd(void *fd) {
|
void GC_set_put_external_event_fd(void *fd) {
|
||||||
NewGC *gc = GC_get_GC();
|
NewGC *gc = GC_get_GC();
|
||||||
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
||||||
|
GC_LOCK_DEBUG("MGCLOCK GC_set_put_external_event_fd\n");
|
||||||
|
{
|
||||||
MASTERGCINFO->signal_fds[gc->place_id] = fd;
|
MASTERGCINFO->signal_fds[gc->place_id] = fd;
|
||||||
|
}
|
||||||
|
GC_LOCK_DEBUG("UNMGCLOCK GC_set_put_external_event_fd\n");
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2027,7 +2072,7 @@ static void NewGC_initialize(NewGC *newgc, NewGC *parentgc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MZ_USE_PLACES
|
#ifdef MZ_USE_PLACES
|
||||||
NewGCMasterInfo_get_next_id(newgc);
|
NewGCMasterInfo_register_gc(newgc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mark_stack_initialize(newgc);
|
mark_stack_initialize(newgc);
|
||||||
|
@ -2110,6 +2155,31 @@ void GC_construct_child_gc() {
|
||||||
newgc->primoridal_gc = MASTERGC;
|
newgc->primoridal_gc = MASTERGC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GC_destruct_child_gc() {
|
||||||
|
NewGC *gc = GC_get_GC();
|
||||||
|
int waiting = 0;
|
||||||
|
do {
|
||||||
|
|
||||||
|
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
||||||
|
GC_LOCK_DEBUG("MGCLOCK GC_destruct_child_gc\n");
|
||||||
|
waiting = MASTERGC->major_places_gc;
|
||||||
|
if (!waiting) {
|
||||||
|
MASTERGCINFO->signal_fds[gc->place_id] = (void *)-2;
|
||||||
|
gc->place_id = -1;
|
||||||
|
MASTERGCINFO->alive--;
|
||||||
|
}
|
||||||
|
GC_LOCK_DEBUG("UNMGCLOCK GC_destruct_child_gc\n");
|
||||||
|
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
||||||
|
|
||||||
|
|
||||||
|
if (waiting) {
|
||||||
|
garbage_collect(gc, 1, 0);
|
||||||
|
waiting = 1;
|
||||||
|
}
|
||||||
|
} while (waiting == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void save_globals_to_gc(NewGC *gc) {
|
static inline void save_globals_to_gc(NewGC *gc) {
|
||||||
gc->saved_GC_variable_stack = GC_variable_stack;
|
gc->saved_GC_variable_stack = GC_variable_stack;
|
||||||
gc->saved_GC_gen0_alloc_page_ptr = GC_gen0_alloc_page_ptr;
|
gc->saved_GC_gen0_alloc_page_ptr = GC_gen0_alloc_page_ptr;
|
||||||
|
@ -2156,7 +2226,7 @@ void *GC_switch_to_master_gc() {
|
||||||
|
|
||||||
/*obtain exclusive access to MASTERGC*/
|
/*obtain exclusive access to MASTERGC*/
|
||||||
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_wrlock(MASTERGCINFO->cangc);
|
||||||
GC_LOCK_DEBUG("MGCLOCK GC_switch_to_master_gc\n");
|
//GC_LOCK_DEBUG("MGCLOCK GC_switch_to_master_gc\n");
|
||||||
|
|
||||||
GC_set_GC(MASTERGC);
|
GC_set_GC(MASTERGC);
|
||||||
restore_globals_from_gc(MASTERGC);
|
restore_globals_from_gc(MASTERGC);
|
||||||
|
@ -2169,7 +2239,7 @@ void GC_switch_back_from_master(void *gc) {
|
||||||
save_globals_to_gc(MASTERGC);
|
save_globals_to_gc(MASTERGC);
|
||||||
|
|
||||||
/*release exclusive access to MASTERGC*/
|
/*release exclusive access to MASTERGC*/
|
||||||
GC_LOCK_DEBUG("UNMGCLOCK GC_switch_to_master_gc\n");
|
//GC_LOCK_DEBUG("UNMGCLOCK GC_switch_to_master_gc\n");
|
||||||
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
mzrt_rwlock_unlock(MASTERGCINFO->cangc);
|
||||||
|
|
||||||
GC_set_GC(gc);
|
GC_set_GC(gc);
|
||||||
|
|
|
@ -87,8 +87,9 @@ typedef struct Page_Range {
|
||||||
|
|
||||||
#ifdef MZ_USE_PLACES
|
#ifdef MZ_USE_PLACES
|
||||||
typedef struct NewGCMasterInfo {
|
typedef struct NewGCMasterInfo {
|
||||||
unsigned short next_GC_id;
|
unsigned long size;
|
||||||
unsigned char *have_collected;
|
unsigned long alive;
|
||||||
|
unsigned long ready;
|
||||||
void **signal_fds;
|
void **signal_fds;
|
||||||
mzrt_rwlock *cangc;
|
mzrt_rwlock *cangc;
|
||||||
mzrt_sema *wait_sema;
|
mzrt_sema *wait_sema;
|
||||||
|
|
|
@ -567,6 +567,9 @@ void scheme_place_instance_destroy() {
|
||||||
#if defined(MZ_USE_PLACES)
|
#if defined(MZ_USE_PLACES)
|
||||||
scheme_kill_green_thread_timer();
|
scheme_kill_green_thread_timer();
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MZ_PRECISE_GC) && defined(MZ_USE_PLACES)
|
||||||
|
GC_destruct_child_gc();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_kernel_env(void)
|
static void make_kernel_env(void)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user