rand32_timer: make it more random-like for tests to pass
I get a high failure rate for tests/kernel/mem_protect/stack_random
because the default rand32_timer used with QEMU is just too mediocre.
Make it more random looking.
Reference:
#include <zephyr/random/rand32.h>
#include <zephyr/drivers/timer/system_timer.h>
#include <zephyr/kernel.h>
-#include <zephyr/sys/atomic.h>
+#include <zephyr/spinlock.h>
#include <string.h>
#if defined(__GNUC__)
-/*
- * Symbols used to ensure a rapid series of calls to random number generator
- * return different values.
- */
-static atomic_val_t _rand32_counter;
-
-#define _RAND32_INC 1000000003U
+static struct k_spinlock rand32_lock;
/**
* @brief Get a 32 bit random number
*
- * The non-random number generator returns values that are based off the
+ * This pseudo-random number generator returns values that are based off the
* target's clock counter, which means that successive calls will return
* different values.
*
@@ -41,13 +35,21 @@ static atomic_val_t _rand32_counter;
*/
uint32_t z_impl_sys_rand32_get(void)
{
- return k_cycle_get_32() + atomic_add(&_rand32_counter, _RAND32_INC);
+ static uint64_t state = 123456789UL; /* initial seed value */
+ k_spinlock_key_t key = k_spin_lock(&rand32_lock);
+
+ state = state + k_cycle_get_32();
+ state = state * 2862933555777941757ULL + 3037000493ULL;
+ uint32_t val = (uint32_t)(state >> 32);
+
+ k_spin_unlock(&rand32_lock, key);
+ return val;
}
/**
* @brief Fill destination buffer with random numbers
*
- * The non-random number generator returns values that are based off the
+ * The pseudo-random number generator returns values that are based off the
* target's clock counter, which means that successive calls will return
* different values.
*
