fix interaction of alarm-evt and replace-evt

With `replace-evt` the time that the system needs to wake up
to check the event can drift later, but scheduling state was
carried in a way that works only if the wake-up time drifts
earlier.

Unfortunately, I don't know how to write a test for this bug.
The usual stategy of using `system-idle-evt` to detect busy
waiting doesn't work here, because the business happens despite
the scheduler's conclusion that the system is idle.

As reported by Jan Dvořák on the mailing list.
This commit is contained in:
Matthew Flatt 2014-09-04 14:20:27 +02:00
parent 59fac3d38a
commit 52514a4af4

View File

@ -5177,14 +5177,14 @@ int scheme_block_until(Scheme_Ready_Fun _f, Scheme_Needs_Wakeup_Fun fdf,
init_schedule_info(&sinfo, NULL, 1, sleep_end);
while (!(result = f((Scheme_Object *)data, &sinfo))) {
sleep_end = sinfo.sleep_end;
double now_sleep_end = sinfo.sleep_end;
if (sinfo.spin) {
init_schedule_info(&sinfo, NULL, 1, 0.0);
scheme_thread_block(0.0);
scheme_current_thread->ran_some = 1;
} else {
if (sleep_end) {
delay = (float)(sleep_end - scheme_get_inexact_milliseconds());
if (now_sleep_end) {
delay = (float)(now_sleep_end - scheme_get_inexact_milliseconds());
delay /= 1000.0;
if (delay <= 0)
delay = (float)0.00001;
@ -5203,6 +5203,7 @@ int scheme_block_until(Scheme_Ready_Fun _f, Scheme_Needs_Wakeup_Fun fdf,
p->block_check = NULL;
p->block_needs_wakeup = NULL;
}
sinfo.sleep_end = sleep_end;
}
p->ran_some = 1;
@ -6647,11 +6648,10 @@ int scheme_syncing_ready(Syncing *syncing, Scheme_Schedule_Info *sinfo, int can_
set_sleep_end_and_return:
syncing->sleep_end = sleep_end;
if (syncing->sleep_end
if (sleep_end
&& (!sinfo->sleep_end
|| (sinfo->sleep_end > syncing->sleep_end)))
sinfo->sleep_end = syncing->sleep_end;
|| (sinfo->sleep_end > sleep_end)))
sinfo->sleep_end = sleep_end;
return result;
}