diff --git a/src/racket/src/future.c b/src/racket/src/future.c index 67095d1e5e..1a7c17cb6a 100644 --- a/src/racket/src/future.c +++ b/src/racket/src/future.c @@ -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 */ } } diff --git a/src/racket/src/future.h b/src/racket/src/future.h index 73f6569995..d7f7aa2e56 100644 --- a/src/racket/src/future.h +++ b/src/racket/src/future.h @@ -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"