Skip to content

Commit bda328e

Browse files
committed
only check timeouts when a thread yields
1 parent 1ae7bfc commit bda328e

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

src/thread.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
477477
if self.threads[self.active_thread].check_terminated() {
478478
return Ok(SchedulingAction::ExecuteDtors);
479479
}
480+
// If we get here again and the thread is *still* terminated, there are no more dtors to run.
480481
if self.threads[MAIN_THREAD].state == ThreadState::Terminated {
481482
// The main thread terminated; stop the program.
482483
if self.threads.iter().any(|thread| thread.state != ThreadState::Terminated) {
@@ -490,26 +491,25 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
490491
}
491492
return Ok(SchedulingAction::Stop);
492493
}
493-
// At least for `pthread_cond_timedwait` we need to report timeout when
494-
// the function is called already after the specified time even if a
495-
// signal is received before the thread gets scheduled. Therefore, we
496-
// need to schedule all timeout callbacks before we continue regular
497-
// execution.
498-
//
499-
// Documentation:
500-
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html#
501-
let potential_sleep_time =
502-
self.timeout_callbacks.values().map(|info| info.call_time.get_wait_time()).min();
503-
if potential_sleep_time == Some(Duration::new(0, 0)) {
504-
return Ok(SchedulingAction::ExecuteTimeoutCallback);
505-
}
506-
// No callbacks scheduled, pick a regular thread to execute.
494+
// This thread and the program can keep going.
507495
if self.threads[self.active_thread].state == ThreadState::Enabled
508496
&& !self.yield_active_thread
509497
{
510498
// The currently active thread is still enabled, just continue with it.
511499
return Ok(SchedulingAction::ExecuteStep);
512500
}
501+
// The active thread yielded. Let's see if there are any timeouts to take care of. We do
502+
// this *before* running any other thread, to ensure that timeouts "in the past" fire before
503+
// any other thread can take an action. This ensures that for `pthread_cond_timedwait`, "an
504+
// error is returned if [...] the absolute time specified by abstime has already been passed
505+
// at the time of the call".
506+
// <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
507+
let potential_sleep_time =
508+
self.timeout_callbacks.values().map(|info| info.call_time.get_wait_time()).min();
509+
if potential_sleep_time == Some(Duration::new(0, 0)) {
510+
return Ok(SchedulingAction::ExecuteTimeoutCallback);
511+
}
512+
// No callbacks scheduled, pick a regular thread to execute.
513513
// We need to pick a new thread for execution.
514514
for (id, thread) in self.threads.iter_enumerated() {
515515
if thread.state == ThreadState::Enabled {

0 commit comments

Comments
 (0)