write-barrier handling with multiple threads

svn: r16880
This commit is contained in:
Matthew Flatt 2009-11-18 20:46:49 +00:00
parent f921cf62cc
commit 3b92693146
4 changed files with 35 additions and 7 deletions

View File

@ -1698,8 +1698,13 @@ static int designate_modified_gc(NewGC *gc, void *p)
page->mprotected = 0;
vm_protect_pages(page->addr, (page->size_class > 1) ? round_to_apage_size(page->size) : APAGE_SIZE, 1);
page->back_pointers = 1;
return 1;
}
/* For a single mutator thread, we shouldn't get here
(and a `return 1' in the braces above would make more
sense). With multiple mutators, though, two threads might
hit the same page at effectively the same time, and only
the first one of them will handle the signal. */
return 1;
} else {
if (gc->primoridal_gc) {
return designate_modified_gc(gc->primoridal_gc, p);

View File

@ -50,7 +50,7 @@ void scheme_init_futures(Scheme_Env *env)
extern void *on_demand_jit_code;
#define THREAD_POOL_SIZE 3
#define THREAD_POOL_SIZE 1
#define INITIAL_C_STACK_SIZE 500000
static pthread_t g_pool_threads[THREAD_POOL_SIZE];
static int *g_fuel_pointers[THREAD_POOL_SIZE];
@ -59,6 +59,7 @@ static int g_num_avail_threads = 0;
static unsigned long g_cur_cpu_mask = 1;
static void *g_signal_handle = NULL;
static struct NewGC *g_shared_GC;
future_t *g_future_queue = NULL;
int g_next_futureid = 0;
pthread_t g_rt_threadid = 0;
@ -86,7 +87,7 @@ static void register_traversers(void);
extern void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv);
static void start_gc_not_ok();
static void end_gc_not_ok();
static void end_gc_not_ok(future_t *ft);
THREAD_LOCAL_DECL(static future_t *current_ft);
@ -310,6 +311,7 @@ void futures_init(void)
for (i = 0; i < THREAD_POOL_SIZE; i++)
{
gc_counter_ptr = &scheme_did_gc_count;
g_shared_GC = GC;
pthread_create(&threadid, &attr, worker_thread_future_loop, &i);
sema_wait(&ready_sema);
@ -337,8 +339,14 @@ static void start_gc_not_ok()
#endif
}
static void end_gc_not_ok()
static void end_gc_not_ok(future_t *ft)
{
if (ft) {
scheme_set_runstack_limits(ft->runstack_start,
ft->runstack_size,
ft->runstack - ft->runstack_start,
ft->runstack_size);
}
pthread_mutex_lock(&gc_ok_m);
--gc_not_ok;
pthread_cond_signal(&gc_ok_c);
@ -465,6 +473,7 @@ Scheme_Object *future(int argc, Scheme_Object *argv[])
rs = rs_start XFORM_OK_PLUS init_runstack_size;
ft->runstack_start = rs_start;
ft->runstack = rs;
ft->runstack_size = init_runstack_size;
}
//pthread_mutex_unlock(&g_future_queue_mutex);
@ -603,6 +612,8 @@ void *worker_thread_future_loop(void *arg)
scheme_init_os_thread();
GC = g_shared_GC;
//Set processor affinity
/*pthread_mutex_lock(&g_future_queue_mutex);
if (pthread_setaffinity_np(pthread_self(), sizeof(g_cur_cpu_mask), &g_cur_cpu_mask))
@ -635,7 +646,7 @@ void *worker_thread_future_loop(void *arg)
pthread_mutex_lock(&g_future_queue_mutex);
while (!(ft = get_pending_future()))
{
end_gc_not_ok();
end_gc_not_ok(NULL);
pthread_cond_wait(&g_future_pending_cv, &g_future_queue_mutex);
start_gc_not_ok();
}
@ -679,12 +690,15 @@ void *worker_thread_future_loop(void *arg)
ft->work_completed = 1;
ft->retval = v;
ft->runstack = NULL;
ft->runstack_start = NULL;
//Update the status
ft->status = FINISHED;
scheme_signal_received_at(g_signal_handle);
pthread_mutex_unlock(&g_future_queue_mutex);
end_gc_not_ok();
end_gc_not_ok(NULL);
goto wait_for_work;
@ -737,7 +751,7 @@ int future_do_runtimecall(
//Wait for the signal that the RT call is finished
future->can_continue_cv = &worker_can_continue_cv;
end_gc_not_ok();
end_gc_not_ok(future);
pthread_cond_wait(&worker_can_continue_cv, &g_future_queue_mutex);
start_gc_not_ok();

View File

@ -80,6 +80,7 @@ typedef struct future {
int work_completed;
pthread_cond_t *can_continue_cv;
long runstack_size;
Scheme_Object **runstack;
Scheme_Object **runstack_start;
Scheme_Object *orig_lambda;

View File

@ -65,6 +65,9 @@ THREAD_LOCAL Thread_Local_Variables scheme_thread_locals;
extern int scheme_num_copied_stacks;
static unsigned long scheme_primordial_os_thread_stack_base;
THREAD_LOCAL_DECL(static unsigned long scheme_os_thread_stack_base);
#ifdef USE_THREAD_LOCAL
Thread_Local_Variables *scheme_vars; /* for debugging */
#endif
static Scheme_Report_Out_Of_Memory_Proc more_report_out_of_memory;
@ -164,7 +167,12 @@ int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void
fprintf(stderr, "pthread key create failed");
abort();
}
#endif
scheme_init_os_thread();
#ifdef USE_THREAD_LOCAL
scheme_vars = scheme_get_thread_local_variables();
#endif
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);