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,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))
{
@ -2769,6 +2776,7 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts,
if (fts->is_runtime_thread) {
/* On runtime thread - must be slow-path tracing */
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;