+ // The active thread yielded. Let's see if there are any timeouts to take care of. We do
+ // this *before* running any other thread, to ensure that timeouts "in the past" fire before
+ // any other thread can take an action. This ensures that for `pthread_cond_timedwait`, "an
+ // error is returned if [...] the absolute time specified by abstime has already been passed
+ // at the time of the call".
+ // <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
+ let potential_sleep_time =
+ self.timeout_callbacks.values().map(|info| info.call_time.get_wait_time()).min();
+ if potential_sleep_time == Some(Duration::new(0, 0)) {
+ return Ok(SchedulingAction::ExecuteTimeoutCallback);
+ }
+ // No callbacks scheduled, pick a regular thread to execute.
+ // The active thread blocked or yielded. So we go search for another enabled thread.
+ // Curcially, we start searching at the current active thread ID, rather than at 0, since we
+ // want to avoid always scheduling threads 0 and 1 without ever making progress in thread 2.
+ //
+ // `skip(N)` means we start iterating at thread N, so we skip 1 more to start just *after*
+ // the active thread. Then after that we look at `take(N)`, i.e., the threads *before* the
+ // active thread.
+ let threads = self
+ .threads
+ .iter_enumerated()
+ .skip(self.active_thread.index() + 1)
+ .chain(self.threads.iter_enumerated().take(self.active_thread.index()));
+ for (id, thread) in threads {
+ debug_assert_ne!(self.active_thread, id);