[LTP] LTP Release preparations

Cyril Hrubis chrubis@suse.cz
Thu Sep 4 11:53:08 CEST 2025


Hi!
> This makes sense! However, from my extensive testing, I still see
> occasional fails on KVM/Debug platforms.
> 
> I suspect the existing barriers ensure all threads are created before
> the game starts, but small scheduler skews can still allow the attacking
> thread to run for a few cycles before the defending thread migrates,
> especially on debug/RT kernels.

I guess that there is no defined order in which the threads are woken up
after the sleep on the barrier. Hence if we wake up the low prio thread
by a chance before all the high prio threads are awake they manage to do
a few cycles.

> So, based on this improve, we might need additional spin for all player
> threads (offense, defense, fans) wait at the barrier and then spin until
> the referee kicks off the ball.
> 
> --- a/testcases/realtime/func/sched_football/sched_football.c
> +++ b/testcases/realtime/func/sched_football/sched_football.c
> @@ -44,6 +44,7 @@
>  static tst_atomic_t the_ball;
>  static int players_per_team = 0;
>  static int game_length = DEF_GAME_LENGTH;
> +static tst_atomic_t kickoff_flag;
>  static tst_atomic_t game_over;
> 
>  static char *str_game_length;
> @@ -55,6 +56,9 @@ void *thread_fan(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
>         prctl(PR_SET_NAME, "crazy_fan", 0, 0, 0);
>         pthread_barrier_wait(&start_barrier);
> +       while (!tst_atomic_load(&kickoff_flag))
> +               ;
> +
>         /*occasionally wake up and run across the field */
>         while (!tst_atomic_load(&game_over)) {
>                 struct timespec start, stop;
> @@ -80,6 +84,9 @@ void *thread_defense(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
>         prctl(PR_SET_NAME, "defense", 0, 0, 0);
>         pthread_barrier_wait(&start_barrier);
> +       while (!tst_atomic_load(&kickoff_flag))
> +               ;
> +
>         /*keep the ball from being moved */
>         while (!tst_atomic_load(&game_over)) {
>         }
> @@ -92,6 +99,9 @@ void *thread_offense(void *arg LTP_ATTRIBUTE_UNUSED)
>  {
>         prctl(PR_SET_NAME, "offense", 0, 0, 0);
>         pthread_barrier_wait(&start_barrier);
> +       while (!tst_atomic_load(&kickoff_flag))
> +               ;
> +
>         while (!tst_atomic_load(&game_over)) {
>                 tst_atomic_add_return(1, &the_ball); /* move the ball ahead
> one yard */
>         }
> @@ -115,9 +125,10 @@ void referee(int game_length)
>         now = start;
> 
>         /* Start the game! */
> -       tst_atomic_store(0, &the_ball);
> -       pthread_barrier_wait(&start_barrier);
>         atrace_marker_write("sched_football", "Game_started!");
> +       pthread_barrier_wait(&start_barrier);
> +       tst_atomic_store(0, &the_ball);
> +       tst_atomic_store(1, &kickoff_flag);

Is this really 100% buletproof? Now the threads are going to wait for
the referee for the kick off but if the referee is the first thread to
be woken up after the barrier the order is stil not guaranteed.

Maybe we can just do a short sleep here in order to make sure that the
scheduller kicks in and redistributes the threads. I would say something
as 20ms (since with CONFIG_HZ=100 we have scheduller ticks every 10ms).

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list