From 1117392cb5524a2ce150384d405fb2a81ef47daa Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 11 Jun 2020 14:55:39 -0600 Subject: [PATCH] cs: fix `touch` on future waiting for an atomic action When the runtime thread `touch`es a future that is blocked on an atomic action (just as JIT compilation), the runtime thread would eagerly run the action, but still leave the future on the atomic-action queue. Atomic actions tend to be ok to run a second time (including JIT compilation), so a problem may not show up immediately, but a semaphore can get out of sync and cause problems later. --- racket/src/racket/src/future.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/racket/src/racket/src/future.c b/racket/src/racket/src/future.c index 4e1f87e5e6..243512bb0d 100644 --- a/racket/src/racket/src/future.c +++ b/racket/src/racket/src/future.c @@ -2023,13 +2023,20 @@ Scheme_Object *general_touch(int argc, Scheme_Object *argv[]) } else if (ft->status == WAITING_FOR_PRIM) { - /* Invoke the primitive and stash the result. - Release the lock so other threads can manipulate the queue - while the runtime call executes. */ - ft->status = HANDLING_PRIM; - ft->want_lw = 0; - mzrt_mutex_unlock(fs->future_mutex); - invoke_rtcall(fs, ft, 0); + if (ft->rt_prim_is_atomic) { + /* Should be in the atomic-wait queue, so + handle those actions now: */ + mzrt_mutex_unlock(fs->future_mutex); + scheme_check_future_work(); + } else { + /* Invoke the primitive and stash the result. + Release the lock so other threads can manipulate the queue + while the runtime call executes. */ + ft->status = HANDLING_PRIM; + ft->want_lw = 0; + mzrt_mutex_unlock(fs->future_mutex); + invoke_rtcall(fs, ft, 0); + } } else if (ft->maybe_suspended_lw && (ft->status != WAITING_FOR_FSEMA)) { @@ -2768,7 +2775,8 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, /* Check whether we are in slow-path trace mode */ if (fts->is_runtime_thread) { /* On runtime thread - must be slow-path tracing */ - future->prim_func = func; + future->prim_func = func; + future->rt_prim_is_atomic = 0; future->status = WAITING_FOR_PRIM; invoke_rtcall(scheme_future_state, future, 0); fts->worker_gc_counter = *fs->gc_counter_ptr;