]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Avoid spurious spmc parallel selftest errors in libarena
authorEmil Tsalapatis <emil@etsalapatis.com>
Tue, 9 Jun 2026 06:36:30 +0000 (02:36 -0400)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 9 Jun 2026 18:10:25 +0000 (11:10 -0700)
The libarena parallel spmc selftest is nondeterministic by design.
As a result it depends up to a point on the relative timing between the
producer and consumer threads. This introduces the possibility for two
kinds of spurious failures that this patch addresses.

1) Spurious timeouts. The test proceeds in phases, and threads use a
   common counter as a barrier to avoid proceeding to the next phase
   until all threads are ready to do so. If a thread takes too long to
   reach the barrier, the already waiting threads may time out.

   Increase the current timeout. The timeout's value is a balance
   between the maximum amount of time spent on the test and the
   possibility of spurious failures. Right now the timeout is too short.
   Err on the side of caution and significantly increase it to avoid
   spurious failures.

2) Spurious resize failures. Some selftests require the spmc queue to
   resize itself. This in turn requires for the producer side to be
   materially faster than the consumer side so that the queue gets full
   enough for a resize. However, in the benchmark the spmc queue's producer
   is outnumbered 3:1. To offset it we add busy waits for consume
   queues. However, we still see occasional failures due to the queue
   never resizing.

   Minimize the possibility for this in two ways: First, remove one of
   the consumers. The 2 consumers still exercise the "race between
   consumers" scenario. Second, increase the busy wait duration to
   decrease the rate by which the consumers act on the queue.

   While at it, also replace a stray invalid error value "153" with EINVAL.

Fixes: 42998f819256 ("selftests/bpf: libarena: parallel test harness and spmc parallel selftest")
Reported-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/r/20260609063630.10245-1-emil@etsalapatis.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/libarena/selftests/test_parallel_spmc.bpf.c

index 981c845e2d15d9898a65eaedc2be56e61d7ac21a..f08f2a92e19468ad698a3570a927acf05731575b 100644 (file)
@@ -7,7 +7,7 @@
 #include <libarena/asan.h>
 #include <libarena/spmc.h>
 
-#define TEST_SPMC_THREADS 4
+#define TEST_SPMC_THREADS 3
 #define TEST_SPMC_STEALERS (TEST_SPMC_THREADS - 1)
 
 /* 
@@ -17,7 +17,7 @@
  * and operations are wait-free we just spin around the quiescence
  * point instead. If we time out, we just fail the benchmark.
  */
-#define TEST_SPMC_SYNC_SPINS (1U << 18)
+#define TEST_SPMC_SYNC_SPINS BPF_MAX_LOOPS
 
 /*
  * We track all the values we retrieve from the queue
@@ -61,7 +61,7 @@ static volatile u64 round_steals;
  * We have multiple stealers and a single owner. We sometimes want the owner
  * to successfully outproduce the stealers, we add a busy loop in them.
  */
-#define TEST_SPMC_WASTE_ROUNDS (1024)
+#define TEST_SPMC_WASTE_ROUNDS (1UL << 12)
 
 /*
  * The spmc data structure depends on the runtime fully
@@ -112,10 +112,6 @@ static bool spmc_tests_enabled(void)
        {                                                               \
                return spmc_##prefix##_stealer();                                       \
        }                                                               \
-       SEC("syscall") int parallel_test_spmc_##prefix##__3(void)       \
-       {                                                               \
-               return spmc_##prefix##_stealer();                                       \
-       }
 
 static int spmc_common_init(u64 total)
 {
@@ -452,10 +448,10 @@ static int spmc_resize_owner(void)
                        resized = true;
        }
 
-       /* Did we get to resize while racing/ */
+       /* Did we get to resize while racing? */
        if (!resized) {
                test_abort = true;
-               return -153;
+               return -EINVAL;
        }
 
        /*