Relocate mutator data structure to gc module

This commit is contained in:
Justin Ethier 2015-11-09 22:25:17 -05:00
parent 2460573534
commit 2b2a96c84d
4 changed files with 38 additions and 56 deletions

80
gc.c
View file

@ -12,6 +12,19 @@
#include "cyclone/types.h"
static gc_thread_data **Cyc_mutators;
static int Cyc_num_mutators;
void gc_init_mutators()
{
// TODO: alloca this using a vpbuffer, or maybe another type of data structure??
// Will need this list for later use, but only by the collector thread. so it would be
// nice if there was a way to allocate mutators that avoids expensive synchronization...
// need to think on this when adding thread support, after upgrading the collector
Cyc_num_mutators = 1;
Cyc_mutators = calloc(Cyc_num_mutators, sizeof(gc_thread_data *));
}
gc_heap *gc_heap_create(size_t size, size_t max_size, size_t chunk_size)
{
gc_free_list *free, *next;
@ -488,63 +501,38 @@ void gc_mark_gray(gc_thread_data *thd, object obj)
// either object type or mark. Both should be stable once the object is placed
// into the heap, with the collector being the only thread that changes marks.
if (is_object_type(obj) && mark(obj) == gc_color_clear) { // TODO: sync??
//TODO: // TODO: lock mark buffer (not ideal, but a possible first step)?
//TODO: pthread_mutex_lock(&(thd->lock));
//TODO: thd->mark_buffer = vpbuffer_add(thd->mark_buffer,
//TODO: &(thd->mark_buffer_len),
//TODO: thd->last_write,
//TODO: obj);
//TODO: pthread_mutex_unlock(&(thd->lock));
//TODO: ATOMIC_INC(&(thd->last_write));
// Place marked object in a buffer to avoid repeated scans of the heap.
// TODO:
// Note that ideally this should be a lock-free data structure to make the
// algorithm more efficient. So this code (and the corresponding collector
// trace code) should be converted at some point.
pthread_mutex_lock(&(thd->lock));
thd->mark_buffer = vpbuffer_add(thd->mark_buffer,
&(thd->mark_buffer_len),
thd->last_write,
obj);
(thd->last_write)++; // Already locked, just do it...
pthread_mutex_unlock(&(thd->lock));
}
}
void gc_collector_trace()
{
int clean = 0;
// while (!clean) {
// clean = 1;
// }
// TODO: need a list of mutators.
// could keep a buffer or linked list of them. a list may be more efficient
// also need to consider how to map thread back to its gc_thread_data,
// which we will need during GC (cooperate). maybe use a (platform-specific)
// call like below to get a unique ID for the thread, and then use a
// hashtable to get the thread info. how often will we be accessing this data?
// seems we will need to be able to access it from 2 places:
// - from mutator (can compute thread id here)
// - from collector (need to be able to iterate across all mutators)
// #include <syscall.h>
// printf("tid = %d\n", syscall(SYS_gettid));
//
// TODO:
// ACTION - I think the most efficient solution is to have each thread pass around
// the pointer to it's thread data. this param would have to be passed to all
// continuation calls made by the thread.
// the collector/runtime will need to maintain a list of the thread data structures,
// and will need to maintain it when a thread is created or terminated (either
// explicitly or when it returns).
// practically the required changes are:
// - stabilize this branch so it builds and runs (hope this just means commenting out
// the pthread calls for right now)
// - extend the runtime and compiled code to have a new thread_data (sp?) param
// also need to judge if there are issues that would prevent being able to add
// one, but it seems like it should be no problem
// - build the code and test that the value is actually maintained across calls
// (maybe assign it to a global at start and exit from GC if cur val != global val)
// note - can atomic operations be used for last read/write, to prevent
// coarser-grained synchronization there?
// TODO:
// clean = FALSE
// while (!(clean))
// clean = TRUE
int clean = 0, i;
while (!clean) {
clean = 1;
// TODO: need to sync access to mutator int/void data, UNLESS
// the collector thread is the only one that is using these
// fields.
for (i = 0; i < Cyc_num_mutators; i++) {
}
// For each m in mutators
// while (lastread[m] < lastwrite[m]) // TODO: use atomic sub to compare?
// clean = FALSE
// lastread[m] = lastread[m] + 1 // TODO: atomic increment
// markBlack(markbuffer[m][lastread[m]])
// EmptyCollectorStack()
}
}
// TODO: seriously consider changing the mark() macro to color(),

View file

@ -28,12 +28,7 @@ static void Cyc_heap_init(long heap_size)
printf("main: Allocating and initializing heap...\n");
#endif
Cyc_heap = gc_heap_create(heap_size / 2, 0, 0);
// TODO: alloca this using a vpbuffer, or maybe another type of data structure??
// Will need this list for later use, but only by the collector thread. so it would be
// nice if there was a way to allocate mutators that avoids expensive synchronization...
// need to think on this when adding thread support, after upgrading the collector
Cyc_num_mutators = 1;
Cyc_mutators = calloc(Cyc_num_mutators, sizeof(gc_thread_data *));
gc_init_mutators();
}
#endif /* CYCLONE_RUNTIME_MAIN_H */

View file

@ -209,8 +209,6 @@ void do_dispatch(void *data, int argc, function_type func, object clo, object *b
/* Global variables. */
extern gc_heap *Cyc_heap;
extern gc_thread_data **Cyc_mutators;
extern int Cyc_num_mutators;
extern long no_gcs; /* Count the number of GC's. */
extern long no_major_gcs; /* Count the number of GC's. */

View file

@ -16,7 +16,7 @@
#include <stdarg.h>
#include <string.h>
#include <math.h>
// TODO: #include <pthread.h>
#include <pthread.h>
// Maximum number of args that GC will accept
#define NUM_GC_ANS 128
@ -58,7 +58,7 @@ struct gc_thread_data_t {
int last_read;
void **mark_buffer;
int mark_buffer_len;
// TODO: pthread_mutex_t lock;
pthread_mutex_t lock;
};
/* GC data structures */
@ -125,6 +125,7 @@ void **vpbuffer_add(void **buf, int *len, int i, void *obj);
void vpbuffer_free(void **buf);
/* GC prototypes */
void gc_init_mutators();
gc_heap *gc_heap_create(size_t size, size_t max_size, size_t chunk_size);
int gc_grow_heap(gc_heap *h, size_t size, size_t chunk_size);
void *gc_try_alloc(gc_heap *h, size_t size);