88 lines
2.0 KiB
Rust
88 lines
2.0 KiB
Rust
//! Random generation utilities
|
|
|
|
use libk_util::{OneTimeInit, sync::IrqSafeSpinlock};
|
|
|
|
use crate::time::monotonic_time;
|
|
|
|
// use crate::device::monotonic_timestamp;
|
|
|
|
const BUFFER_SIZE: usize = 1024;
|
|
|
|
struct RandomState {
|
|
data: [u8; BUFFER_SIZE],
|
|
pos: usize,
|
|
last_state: u32,
|
|
}
|
|
|
|
impl RandomState {
|
|
fn new(seed: u32) -> Self {
|
|
Self {
|
|
data: [0; BUFFER_SIZE],
|
|
pos: BUFFER_SIZE,
|
|
last_state: seed,
|
|
}
|
|
}
|
|
|
|
fn next(&mut self) -> u32 {
|
|
let mut x = self.last_state;
|
|
x ^= x << 13;
|
|
x ^= x >> 17;
|
|
x ^= x << 5;
|
|
self.last_state = x;
|
|
x
|
|
}
|
|
|
|
fn fill_buf(&mut self) {
|
|
self.pos = 0;
|
|
for i in (0..self.data.len()).step_by(4) {
|
|
let v = self.next();
|
|
self.data[i..i + 4].copy_from_slice(&v.to_ne_bytes());
|
|
}
|
|
}
|
|
|
|
fn read_buf(&mut self, buf: &mut [u8]) {
|
|
let mut rem = buf.len();
|
|
let mut pos = 0;
|
|
|
|
while rem != 0 {
|
|
if self.pos == BUFFER_SIZE {
|
|
self.fill_buf();
|
|
}
|
|
let count = core::cmp::min(rem, BUFFER_SIZE - self.pos);
|
|
|
|
buf[pos..pos + count].copy_from_slice(&self.data[self.pos..self.pos + count]);
|
|
|
|
self.pos += count;
|
|
rem -= count;
|
|
pos += count;
|
|
}
|
|
}
|
|
}
|
|
|
|
static RANDOM_STATE: OneTimeInit<IrqSafeSpinlock<RandomState>> = OneTimeInit::new();
|
|
|
|
/// Fills `buf` with random bytes
|
|
pub fn read_unsecure(buf: &mut [u8]) {
|
|
let state = RANDOM_STATE.get();
|
|
state.lock().read_buf(buf)
|
|
}
|
|
|
|
pub fn range(a: u64, b: u64) -> u64 {
|
|
assert!(b > a);
|
|
let mut bytes = [0; 8];
|
|
read_unsecure(&mut bytes);
|
|
let v = u64::from_ne_bytes(bytes) % (b - a);
|
|
a + v
|
|
}
|
|
|
|
/// Initializes the random generator state
|
|
pub fn init() {
|
|
let now = monotonic_time();
|
|
let random_seed = now.subsec_nanos().wrapping_add(now.seconds());
|
|
|
|
let mut state = RandomState::new(random_seed as u32);
|
|
state.fill_buf();
|
|
|
|
RANDOM_STATE.init(IrqSafeSpinlock::new(state));
|
|
}
|