Skip to content

Commit 710bc80

Browse files
authored
rt: coop should yield using waker defer strategy (#7185)
1 parent a2b12bd commit 710bc80

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

tokio/src/task/coop/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ cfg_coop! {
305305

306306
Poll::Ready(restore)
307307
} else {
308-
cx.waker().wake_by_ref();
308+
defer(cx);
309309
Poll::Pending
310310
}
311311
}).unwrap_or(Poll::Ready(RestoreOnPending(Cell::new(Budget::unconstrained()))))
@@ -325,11 +325,19 @@ cfg_coop! {
325325
#[inline(always)]
326326
fn inc_budget_forced_yield_count() {}
327327
}
328+
329+
fn defer(cx: &mut Context<'_>) {
330+
context::defer(cx.waker());
331+
}
328332
}
329333

330334
cfg_not_rt! {
331335
#[inline(always)]
332336
fn inc_budget_forced_yield_count() {}
337+
338+
fn defer(cx: &mut Context<'_>) {
339+
cx.waker().wake_by_ref();
340+
}
333341
}
334342

335343
impl Budget {

tokio/tests/rt_common.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,25 @@ rt_test! {
745745
#[cfg_attr(miri, ignore)] // No `socket` in miri.
746746
fn yield_defers_until_park() {
747747
for _ in 0..10 {
748-
if yield_defers_until_park_inner() {
748+
if yield_defers_until_park_inner(false) {
749+
// test passed
750+
return;
751+
}
752+
753+
// Wait a bit and run the test again.
754+
std::thread::sleep(std::time::Duration::from_secs(2));
755+
}
756+
757+
panic!("yield_defers_until_park is failing consistently");
758+
}
759+
760+
/// Same as above, but with cooperative scheduling.
761+
#[test]
762+
#[cfg(not(target_os="wasi"))]
763+
#[cfg_attr(miri, ignore)] // No `socket` in miri.
764+
fn coop_yield_defers_until_park() {
765+
for _ in 0..10 {
766+
if yield_defers_until_park_inner(true) {
749767
// test passed
750768
return;
751769
}
@@ -760,10 +778,12 @@ rt_test! {
760778
/// Implementation of `yield_defers_until_park` test. Returns `true` if the
761779
/// test passed.
762780
#[cfg(not(target_os="wasi"))]
763-
fn yield_defers_until_park_inner() -> bool {
781+
fn yield_defers_until_park_inner(use_coop: bool) -> bool {
764782
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
765783
use std::sync::Barrier;
766784

785+
const BUDGET: usize = 128;
786+
767787
let rt = rt();
768788

769789
let flag = Arc::new(AtomicBool::new(false));
@@ -802,7 +822,15 @@ rt_test! {
802822
// Yield until connected
803823
let mut cnt = 0;
804824
while !flag_clone.load(SeqCst){
805-
tokio::task::yield_now().await;
825+
if use_coop {
826+
// Consume a good chunk of budget, which should
827+
// force at least one yield.
828+
for _ in 0..BUDGET {
829+
tokio::task::consume_budget().await;
830+
}
831+
} else {
832+
tokio::task::yield_now().await;
833+
}
806834
cnt += 1;
807835

808836
if cnt >= 10 {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy