commit 79104becf42b ("sched/fair: Forfeit vruntime on yield") changed
yield_task_fair() to only bump the deadline when the entity is eligible
(vruntime <= avg_vruntime). When the entity is ineligible the yield
becomes a complete no-op from scheduling perspective.lost_exception_test calls sched_yield() 100,000 times per iteration to race the EBB exception delivery with a context switch to the eat_cpu companion process. After enough iterations the test process's vruntime races ahead of avg_vruntime (each eligible yield bumps vruntime to deadline, then advances deadline by one slice). Once ineligible, yield_task_fair() does nothing: so the scheduler won't pick the eat_cpu child. No context switch occurs, the PMAO race is never triggered, and ebb_count stays at 0 forever causing the test to hang until timeout. Fix by replacing sched_yield() with nanosleep(0, 1ns). nanosleep() goes through hrtimer_nanosleep() -> do_nanosleep(), which puts the task into TASK_INTERRUPTIBLE and removes it from the run queue entirely. This guarantees the scheduler picks the eat_cpu child, restoring the context-switch guarantee the test requires. The 1ns duration is enough to engage the hrtimer path while keeping the sleep effectively instantaneous; the same race window between PMU overflow and context switch is preserved. Reported-by: Venkat Rao Bagalkote <[email protected]> Signed-off-by: Athira Rajeev <[email protected]> --- .../selftests/powerpc/pmu/ebb/lost_exception_test.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c b/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c index ba2681a12cc7..9be5945f3b1f 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/lost_exception_test.c @@ -8,6 +8,7 @@ #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> +#include <time.h> #include "ebb.h" @@ -22,6 +23,7 @@ static int test_body(void) { int i, orig_period, max_period; struct event event; + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1 }; SKIP_IF(!ebb_is_supported()); @@ -57,10 +59,15 @@ static int test_body(void) * kernel to decide our timeslice is up and context switch to * the other thread. When we come back our EBB will have been * lost and we'll spin in this while loop forever. + * + * Use nanosleep(0) instead of sched_yield() to guarantee a + * context switch to the eat_cpu child regardless of the + * eligibility state. sched_yield() via yield_task_fair() may + * become a no-op when the task is ineligible (vruntime ahead + * of avg_vruntime), preventing the required context switch. */ - for (i = 0; i < 100000; i++) - sched_yield(); + nanosleep(&ts, NULL); /* Change the sample period slightly to try and hit the race */ if (sample_period >= (orig_period + 200)) -- 2.43.0
