Commit d7f9e264 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Stephanos Ioannidis
Browse files

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: https://nuclear.llnl.gov/CNP/rng/rngman/node4.html



Signed-off-by: default avatarNicolas Pitre <npitre@baylibre.com>
parent 3ead1cfa
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -17,23 +17,17 @@
#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.
 *