History

selftests/bpf: Avoid spurious spmc parallel selftest errors in libarena

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.

Emil Tsalapatis committed 5 months ago

Commit 68f4e481 parent f1a660b1 file · +5 −9Browse files

Unified · Split

tools/testing/selftests/bpf/libarena/selftests/test_parallel_spmc.bpf.c+5−9
@@ -7,7 +7,7 @@ · 6 unmodified lines
77 #include <libarena/asan.h>
88 #include <libarena/spmc.h>
99
10−#define TEST_SPMC_THREADS 4
10+#define TEST_SPMC_THREADS 3
1111 #define TEST_SPMC_STEALERS (TEST_SPMC_THREADS - 1)
1212
1313 /*
@@ -17,7 +17,7 @@ · 3 unmodified lines
1717 * and operations are wait-free we just spin around the quiescence
1818 * point instead. If we time out, we just fail the benchmark.
1919 */
20−#define TEST_SPMC_SYNC_SPINS (1U << 18)
20+#define TEST_SPMC_SYNC_SPINS BPF_MAX_LOOPS
2121
2222 /*
2323 * We track all the values we retrieve from the queue
@@ -61,7 +61,7 @@ static volatile u64 round_steals; · 37 unmodified lines
6161 * We have multiple stealers and a single owner. We sometimes want the owner
6262 * to successfully outproduce the stealers, we add a busy loop in them.
6363 */
64−#define TEST_SPMC_WASTE_ROUNDS (1024)
64+#define TEST_SPMC_WASTE_ROUNDS (1UL << 12)
6565
6666 /*
6767 * The spmc data structure depends on the runtime fully
@@ -112,10 +112,6 @@ static bool spmc_tests_enabled(void) · 44 unmodified lines
112112 { \
113113 return spmc_##prefix##_stealer(); \
114114 } \
115− SEC("syscall") int parallel_test_spmc_##prefix##__3(void) \
116− { \
117− return spmc_##prefix##_stealer(); \
118− }
119115
120116 static int spmc_common_init(u64 total)
121117 {
@@ -452,10 +448,10 @@ static int spmc_resize_owner(void) · 330 unmodified lines
452448 resized = true;
453449 }
454450
455− /* Did we get to resize while racing/ */
451+ /* Did we get to resize while racing? */
456452 if (!resized) {
457453 test_abort = true;
458− return -153;
454+ return -EINVAL;
459455 }
460456
461457 /*