another futures bug fix

This commit is contained in:
Matthew Flatt 2011-12-03 07:35:39 -07:00
parent 788e8bb5f4
commit db3878e309
2 changed files with 16 additions and 10 deletions

View File

@ -1626,6 +1626,7 @@ static void direct_future_to_future_touch(Scheme_Future_State *fs, future_t *ft,
send_special_result(t_ft, retval);
t_ft->arg_S1 = NULL;
t_ft->status = HANDLING_PRIM; /* handled as if by runtime thread */
complete_rtcall(fs, t_ft);
}
@ -1882,7 +1883,7 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[])
if (ft->touching)
SCHEME_CDR(pr) = ft->touching;
ft->touching = pr;
current_ft->in_touch_queue = 1;
current_ft->in_future_specific_touch_queue = 1;
mzrt_mutex_unlock(fs->future_mutex);
} else {
/* `ft' switched to FINISHED while we were trying add,
@ -2288,6 +2289,7 @@ void scheme_check_future_work()
if (ft) {
fs->future_waiting_touch = ft->next_waiting_touch;
ft->next_waiting_touch = NULL;
ft->in_touch_queue = 0;
other_ft = get_future_for_touch(ft);
more = 1;
} else {
@ -2306,7 +2308,6 @@ void scheme_check_future_work()
mzrt_mutex_lock(fs->future_mutex);
if (other_ft->status == FINISHED) {
/* Completed while we tried to allocate a chain link. */
ft->status = HANDLING_PRIM;
direct_future_to_future_touch(fs, other_ft, ft);
} else {
/* enqueue */
@ -2460,13 +2461,16 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts,
}
if (func == touch) {
if (!future->in_touch_queue) {
if (!future->in_future_specific_touch_queue) {
/* Ask the runtime thread to put this future on the queue
of the future being touched: */
future->next_waiting_touch = fs->future_waiting_touch;
fs->future_waiting_touch = future;
if (!future->in_touch_queue) {
future->next_waiting_touch = fs->future_waiting_touch;
fs->future_waiting_touch = future;
future->in_touch_queue = 1;
}
} else {
future->in_touch_queue = 0; /* done with back-door argument */
future->in_future_specific_touch_queue = 0; /* done with back-door argument */
}
}

View File

@ -78,7 +78,7 @@ typedef struct future_t {
/* Runtime call stuff */
int want_lw;
char want_lw;
/* flag to indicate waiting for lw capture; if this flag is set,
then the future thread currently running the future must be
blocked, and the runtime thread must not already be working on
@ -90,16 +90,18 @@ typedef struct future_t {
future that completed; the `want_lw' flag should be changed only
while holding a lock */
int in_queue_waiting_for_lwc;
char in_queue_waiting_for_lwc;
/* flag to indicate whether the future is in the "waiting for lwc"
queue; the future might be in the queue even if want_lw is set to
0, and so this flag just prevents */
int in_touch_queue;
char in_touch_queue;
/* like `in_queue_waiting_for_lwc' but for being in a `touch'
future */
int rt_prim_is_atomic;
char in_future_specific_touch_queue; /* a back-door argument */
char rt_prim_is_atomic;
/* when a future thread is blocked on this future, it sets
`rt_prim_is_atomic' if the blocking operation can run
in any thread atomically (i.e., it's a "synchronizing"