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.
This commit is contained in:
Matthew Flatt 2020-06-11 14:55:39 -06:00
parent 42cb80bc70
commit 1117392cb5

View File

@ -2023,6 +2023,12 @@ Scheme_Object *general_touch(int argc, Scheme_Object *argv[])
} }
else if (ft->status == WAITING_FOR_PRIM) else if (ft->status == WAITING_FOR_PRIM)
{ {
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. /* Invoke the primitive and stash the result.
Release the lock so other threads can manipulate the queue Release the lock so other threads can manipulate the queue
while the runtime call executes. */ while the runtime call executes. */
@ -2031,6 +2037,7 @@ Scheme_Object *general_touch(int argc, Scheme_Object *argv[])
mzrt_mutex_unlock(fs->future_mutex); mzrt_mutex_unlock(fs->future_mutex);
invoke_rtcall(fs, ft, 0); invoke_rtcall(fs, ft, 0);
} }
}
else if (ft->maybe_suspended_lw && (ft->status != WAITING_FOR_FSEMA)) else if (ft->maybe_suspended_lw && (ft->status != WAITING_FOR_FSEMA))
{ {
ft->maybe_suspended_lw = 0; ft->maybe_suspended_lw = 0;
@ -2769,6 +2776,7 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts,
if (fts->is_runtime_thread) { if (fts->is_runtime_thread) {
/* On runtime thread - must be slow-path tracing */ /* 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; future->status = WAITING_FOR_PRIM;
invoke_rtcall(scheme_future_state, future, 0); invoke_rtcall(scheme_future_state, future, 0);
fts->worker_gc_counter = *fs->gc_counter_ptr; fts->worker_gc_counter = *fs->gc_counter_ptr;