1use hermit_sync::InterruptTicketMutex;
7use rand_chacha::ChaCha20Rng;
8use rand_chacha::rand_core::{RngCore, SeedableRng};
9
10use crate::arch::kernel::processor::{get_timer_ticks, seed_entropy};
11use crate::errno::ENOSYS;
12
13const RESEED_INTERVAL: u64 = 1_000_000;
16
17bitflags! {
18 pub struct Flags: u32 {}
19}
20
21struct Pool {
22 rng: ChaCha20Rng,
23 last_reseed: u64,
24}
25
26static POOL: InterruptTicketMutex<Option<Pool>> = InterruptTicketMutex::new(None);
27
28pub fn read(buf: &mut [u8], _flags: Flags) -> isize {
33 let pool = &mut *POOL.lock();
34 let now = get_timer_ticks();
35 let pool = match pool {
36 Some(pool) if now.saturating_sub(pool.last_reseed) <= RESEED_INTERVAL => pool,
37 pool => {
38 if let Some(seed) = seed_entropy() {
39 pool.insert(Pool {
40 rng: ChaCha20Rng::from_seed(seed),
41 last_reseed: now,
42 })
43 } else {
44 return -ENOSYS as isize;
45 }
46 }
47 };
48
49 pool.rng.fill_bytes(buf);
50 buf.len() as isize
53}