@@ -7,6 +7,7 @@ use core::arch::{asm, global_asm};
77use std:: {
88 alloc:: { Layout , alloc_zeroed} ,
99 ptr:: null,
10+ sync:: atomic:: { AtomicU32 , Ordering } ,
1011} ;
1112
1213#[ cfg( target_arch = "riscv32" ) ]
@@ -49,26 +50,40 @@ pub extern "C" fn sys_getenv(_name: *const u8) -> *const u8 {
4950#[ unsafe( no_mangle) ]
5051#[ linkage = "weak" ]
5152pub unsafe extern "C" fn sys_rand ( recv_buf : * mut u8 , words : usize ) {
52- unsafe fn step ( ) -> u32 {
53- static mut X : u32 = 0xae569764 ;
54- // We are stealing Borland Delphi's random number generator.
55- // The random numbers here are only good enough to make eg
56- // HashMap work.
53+ // We are stealing Borland Delphi's random number generator.
54+ // The random numbers here are only good enough to make eg
55+ // HashMap work.
56+ fn step ( ) -> u32 {
57+ static X : AtomicU32 = AtomicU32 :: new ( 0xae569764 ) ;
58+ let rslt = X . fetch_update ( Ordering :: Relaxed , Ordering :: Relaxed , |x| {
59+ Some ( x. wrapping_mul ( 134775813 ) . wrapping_add ( 1 ) )
60+ } ) ;
61+ match rslt {
62+ Ok ( el) => el,
63+ Err ( err) => err,
64+ }
65+ }
66+ let mut idx = 0 ;
67+ let steps = words / 4 ;
68+ let rest = words % 4 ;
69+ for _ in 0 ..steps {
70+ let [ a, b, c, d] = step ( ) . to_le_bytes ( ) ;
71+ // SAFETY: Up to the caller
5772 unsafe {
58- X = X . wrapping_mul ( 134775813 ) + 1 ;
59- X
73+ * recv_buf. add ( idx) = a;
74+ * recv_buf. add ( idx. wrapping_add ( 1 ) ) = b;
75+ * recv_buf. add ( idx. wrapping_add ( 2 ) ) = c;
76+ * recv_buf. add ( idx. wrapping_add ( 3 ) ) = d;
6077 }
78+ idx = idx. wrapping_add ( 4 ) ;
6179 }
62- // TODO(Matthias): this is a bit inefficient,
63- // we could fill whole u32 words at a time.
64- // But it's just for testing.
65- for i in 0 ..words {
80+ let [ a, b, c, _] = step ( ) . to_le_bytes ( ) ;
81+ for ( _, el) in ( 0 ..rest) . zip ( [ a, b, c] ) {
82+ // SAFETY: Up to the caller
6683 unsafe {
67- let element = recv_buf. add ( i) ;
68- // The lower bits ain't really random, so might as well take
69- // the higher order ones, if we are only using 8 bits.
70- * element = step ( ) . to_le_bytes ( ) [ 3 ] ;
84+ * recv_buf. add ( idx) = el;
7185 }
86+ idx = idx. wrapping_add ( 1 ) ;
7287 }
7388}
7489
@@ -153,3 +168,17 @@ unsafe extern "C" {
153168 // The address of this variable is the start of the stack (growing downwards).
154169 static _stack_start: u8 ;
155170}
171+
172+ #[ cfg( test) ]
173+ mod tests {
174+ use crate :: sys_rand;
175+
176+ #[ test]
177+ fn fills_with_random_bytes ( ) {
178+ let mut buf = [ 0u8 ; 65 ] ;
179+ unsafe {
180+ sys_rand ( buf. as_mut_ptr ( ) , buf. len ( ) ) ;
181+ }
182+ assert_ne ! ( buf, [ 0u8 ; 65 ] ) ;
183+ }
184+ }
0 commit comments