@@ -11,22 +11,32 @@ use crate::Error;
1111use chacha20:: ChaCha12Rng ;
1212use core:: mem:: MaybeUninit ;
1313use rand_core:: { Rng , SeedableRng } ;
14- use std:: sync:: { Mutex , OnceLock } ;
14+ use std:: {
15+ collections:: HashMap ,
16+ sync:: { Mutex , OnceLock } ,
17+ } ;
1518
1619/// The RNG, initialised exactly once on first use.
17- static RNG : OnceLock < Mutex < ChaCha12Rng > > = OnceLock :: new ( ) ;
20+ static RNG : OnceLock < Mutex < HashMap < std :: thread :: ThreadId , ChaCha12Rng > > > = OnceLock :: new ( ) ;
1821
1922#[ inline]
2023pub fn fill_inner ( dest : & mut [ MaybeUninit < u8 > ] ) -> Result < ( ) , Error > {
21- let rng = RNG . get_or_init ( || Mutex :: new ( ChaCha12Rng :: from_seed ( [ 42u8 ; 32 ] ) ) ) ;
24+ // get current thread id
25+ let id = std:: thread:: current ( ) . id ( ) ;
26+
27+ let rng = RNG . get_or_init ( || HashMap :: new ( ) . into ( ) ) ;
2228
2329 let mut guard = rng. lock ( ) . unwrap ( ) ;
2430
31+ let entry = guard
32+ . entry ( id)
33+ . or_insert_with ( || ChaCha12Rng :: from_seed ( [ 42u8 ; 32 ] ) ) ;
34+
2535 // SAFETY: `fill_bytes` fully overwrites every byte of the slice, so
2636 // treating uninitialized `MaybeUninit<u8>` as `u8` for the purpose of
2737 // writing (never reading) is sound.
2838 let dest_init = unsafe { dest. assume_init_mut ( ) } ;
29- guard . fill_bytes ( dest_init) ;
39+ entry . fill_bytes ( dest_init) ;
3040
3141 Ok ( ( ) )
3242}
@@ -48,4 +58,32 @@ mod tests {
4858 buf
4959 ) ;
5060 }
61+ use std:: thread;
62+ #[ test]
63+ fn test_deterministic_multithread ( ) {
64+ thread:: spawn ( || {
65+ let mut buf = [ 0u8 ; 32 ] ;
66+ crate :: fill ( & mut buf) . unwrap ( ) ;
67+ assert_eq ! (
68+ [
69+ 0x1b , 0x8c , 0x20 , 0xcd , 0xe2 , 0xdb , 0xb4 , 0x3c , 0xd3 , 0xc7 , 0x9 , 0xb2 , 0x90 ,
70+ 0xac , 0x50 , 0xdc , 0xd2 , 0xbe , 0x2a , 0x87 , 0xa3 , 0xa2 , 0x45 , 0x44 , 0xb5 , 0xa5 ,
71+ 0x10 , 0x9b , 0xc7 , 0x6e , 0xa7 , 0xfb ,
72+ ] ,
73+ buf
74+ ) ;
75+ } ) ;
76+ thread:: spawn ( || {
77+ let mut buf = [ 0u8 ; 32 ] ;
78+ crate :: fill ( & mut buf) . unwrap ( ) ;
79+ assert_eq ! (
80+ [
81+ 0x1b , 0x8c , 0x20 , 0xcd , 0xe2 , 0xdb , 0xb4 , 0x3c , 0xd3 , 0xc7 , 0x9 , 0xb2 , 0x90 ,
82+ 0xac , 0x50 , 0xdc , 0xd2 , 0xbe , 0x2a , 0x87 , 0xa3 , 0xa2 , 0x45 , 0x44 , 0xb5 , 0xa5 ,
83+ 0x10 , 0x9b , 0xc7 , 0x6e , 0xa7 , 0xfb ,
84+ ] ,
85+ buf
86+ ) ;
87+ } ) ;
88+ }
5189}
0 commit comments