From 1991cde5a7db0c117f018966500574b941c830d7 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 20 Nov 2009 13:59:46 +0000 Subject: [PATCH] fix handling of future atomic runtime requests svn: r16920 --- src/mzscheme/src/future.c | 29 +++++++++++++++++++---------- src/mzscheme/src/future.h | 2 ++ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/mzscheme/src/future.c b/src/mzscheme/src/future.c index 83db07dc8c..8b15acc3ac 100644 --- a/src/mzscheme/src/future.c +++ b/src/mzscheme/src/future.c @@ -799,15 +799,18 @@ void scheme_check_future_work() ft = g_future_waiting_atomic; if (ft) { g_future_waiting_atomic = ft->next_waiting_atomic; + ft->next_waiting_atomic = NULL; + ft->waiting_atomic = 0; } pthread_mutex_unlock(&g_future_queue_mutex); - if (ft && ft->rt_prim && ft->rt_prim_is_atomic) { - invoke_rtcall(ft); + if (ft) { + if (ft->rt_prim && ft->rt_prim_is_atomic) { + invoke_rtcall(ft); + } } else break; } - } //Returns 0 if the call isn't actually executed by this function, @@ -849,8 +852,11 @@ void future_do_runtimecall(void *func, future->rt_prim_is_atomic = is_atomic; if (is_atomic) { - future->next_waiting_atomic = g_future_waiting_atomic; - g_future_waiting_atomic = future; + if (!future->waiting_atomic) { + future->next_waiting_atomic = g_future_waiting_atomic; + g_future_waiting_atomic = future; + future->waiting_atomic = 1; + } } //Update the future's status to waiting @@ -861,12 +867,13 @@ void future_do_runtimecall(void *func, //Wait for the signal that the RT call is finished future->can_continue_cv = &worker_can_continue_cv; end_gc_not_ok(future); - pthread_cond_wait(&worker_can_continue_cv, &g_future_queue_mutex); + while (future->can_continue_cv) { + pthread_cond_wait(&worker_can_continue_cv, &g_future_queue_mutex); + //Fetch the future instance again, in case the GC has moved the pointer + future = current_ft; + } start_gc_not_ok(); - //Fetch the future instance again, in case the GC has moved the pointer - future = current_ft; - pthread_mutex_unlock(&g_future_queue_mutex); if (future->no_retval) { @@ -907,7 +914,7 @@ void *scheme_rtcall_alloc_void_pvoid(const char *who, int src_type, void (*f)()) while (1) { future = current_ft; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = 0; /* takes too long?: scheme_get_inexact_milliseconds(); */ future->source_of_request = who; future->source_type = src_type; @@ -1029,6 +1036,7 @@ static void do_invoke_rtcall(future_t *future) //Signal the waiting worker thread that it //can continue running machine code pthread_cond_signal(future->can_continue_cv); + future->can_continue_cv= NULL; pthread_mutex_unlock(&g_future_queue_mutex); } @@ -1045,6 +1053,7 @@ static void invoke_rtcall(future_t * volatile future) //Signal the waiting worker thread that it //can continue running machine code pthread_cond_signal(future->can_continue_cv); + future->can_continue_cv = NULL; pthread_mutex_unlock(&g_future_queue_mutex); scheme_longjmp(*savebuf, 1); } else { diff --git a/src/mzscheme/src/future.h b/src/mzscheme/src/future.h index 638a158eae..6fb9893ffa 100644 --- a/src/mzscheme/src/future.h +++ b/src/mzscheme/src/future.h @@ -105,6 +105,8 @@ typedef struct future_t { Scheme_Object *retval; struct future_t *prev; struct future_t *next; + + int waiting_atomic; struct future_t *next_waiting_atomic; } future_t;