[RFC][PATCH 1/3] test-ww_mutex: Use prng instead of rng to avoid hangs at bootup

From: John Stultz
Date: Tue Aug 08 2023 - 13:43:55 EST


Booting w/ qemu without kvm, I noticed we'd sometimes seem to get
stuck in get_random_u32_below(). This seems potentially to be
entropy exhaustion (with the test module linked statically, it
runs pretty early in the bootup).

I'm not 100% sure on this, but this patch switches to use the
prng instead since we don't need true randomness, just mixed up
orders for testing ww_mutex lock acquisitions.

With this patch, I no longer see hangs in get_random_u32_below()

Feedback would be appreciated!

Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Will Deacon <will@xxxxxxxxxx>
Cc: Waiman Long <longman@xxxxxxxxxx>
Cc: Boqun Feng <boqun.feng@xxxxxxxxx>
Cc: "Paul E . McKenney" <paulmck@xxxxxxxxxx>
Cc: Joel Fernandes <joelaf@xxxxxxxxxx>
Cc: Li Zhijian <zhijianx.li@xxxxxxxxx>
Cc: Dietmar Eggemann <dietmar.eggemann@xxxxxxx>
Cc: kernel-team@xxxxxxxxxxx
Signed-off-by: John Stultz <jstultz@xxxxxxxxxx>
---
kernel/locking/test-ww_mutex.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
index 93cca6e69860..9bceba65858a 100644
--- a/kernel/locking/test-ww_mutex.c
+++ b/kernel/locking/test-ww_mutex.c
@@ -9,7 +9,7 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/module.h>
-#include <linux/random.h>
+#include <linux/prandom.h>
#include <linux/slab.h>
#include <linux/ww_mutex.h>

@@ -386,6 +386,19 @@ struct stress {
int nlocks;
};

+struct rnd_state rng;
+DEFINE_SPINLOCK(rng_lock);
+
+static inline u32 prandom_u32_below(u32 ceil)
+{
+ u32 ret;
+
+ spin_lock(&rng_lock);
+ ret = prandom_u32_state(&rng) % ceil;
+ spin_unlock(&rng_lock);
+ return ret;
+}
+
static int *get_random_order(int count)
{
int *order;
@@ -399,7 +412,7 @@ static int *get_random_order(int count)
order[n] = n;

for (n = count - 1; n > 1; n--) {
- r = get_random_u32_below(n + 1);
+ r = prandom_u32_below(n + 1);
if (r != n) {
tmp = order[n];
order[n] = order[r];
@@ -625,6 +638,8 @@ static int __init test_ww_mutex_init(void)

printk(KERN_INFO "Beginning ww mutex selftests\n");

+ prandom_seed_state(&rng, get_random_u64());
+
wq = alloc_workqueue("test-ww_mutex", WQ_UNBOUND, 0);
if (!wq)
return -ENOMEM;
--
2.41.0.640.ga95def55d0-goog