@@ -4,8 +4,7 @@ use crate::Error;
44use core:: {
55 ffi:: c_void,
66 mem:: { MaybeUninit , transmute} ,
7- ptr:: NonNull ,
8- sync:: atomic:: { AtomicPtr , Ordering } ,
7+ ptr:: { self , NonNull } ,
98} ;
109use use_file:: utils;
1110
@@ -17,18 +16,12 @@ type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint)
1716/// or not supported by kernel.
1817const NOT_AVAILABLE : NonNull < c_void > = unsafe { NonNull :: new_unchecked ( usize:: MAX as * mut c_void ) } ;
1918
20- static GETRANDOM_FN : AtomicPtr < c_void > = AtomicPtr :: new ( core:: ptr:: null_mut ( ) ) ;
21-
2219#[ cold]
2320#[ inline( never) ]
2421fn init ( ) -> NonNull < c_void > {
2522 // Use static linking to `libc::getrandom` on MUSL targets and `dlsym` everywhere else
2623 #[ cfg( not( target_env = "musl" ) ) ]
27- let raw_ptr = {
28- static NAME : & [ u8 ] = b"getrandom\0 " ;
29- let name_ptr = NAME . as_ptr ( ) . cast :: < libc:: c_char > ( ) ;
30- unsafe { libc:: dlsym ( libc:: RTLD_DEFAULT , name_ptr) }
31- } ;
24+ let raw_ptr = unsafe { libc:: dlsym ( libc:: RTLD_DEFAULT , c"getrandom" . as_ptr ( ) ) } ;
3225 #[ cfg( target_env = "musl" ) ]
3326 let raw_ptr = {
3427 let fptr: GetRandomFn = libc:: getrandom;
@@ -37,10 +30,9 @@ fn init() -> NonNull<c_void> {
3730
3831 let res_ptr = match NonNull :: new ( raw_ptr) {
3932 Some ( fptr) => {
40- let getrandom_fn = unsafe { transmute :: < NonNull < c_void > , GetRandomFn > ( fptr) } ;
41- let dangling_ptr = NonNull :: dangling ( ) . as_ptr ( ) ;
33+ let getrandom_fn = unsafe { transmute :: < * mut c_void , GetRandomFn > ( fptr. as_ptr ( ) ) } ;
4234 // Check that `getrandom` syscall is supported by kernel
43- let res = unsafe { getrandom_fn ( dangling_ptr , 0 , 0 ) } ;
35+ let res = unsafe { getrandom_fn ( ptr :: dangling_mut ( ) , 0 , 0 ) } ;
4436 if cfg ! ( getrandom_test_linux_fallback) {
4537 NOT_AVAILABLE
4638 } else if res. is_negative ( ) {
@@ -65,7 +57,6 @@ fn init() -> NonNull<c_void> {
6557 panic ! ( "Fallback is triggered with enabled `getrandom_test_linux_without_fallback`" )
6658 }
6759
68- GETRANDOM_FN . store ( res_ptr. as_ptr ( ) , Ordering :: Release ) ;
6960 res_ptr
7061}
7162
@@ -77,23 +68,17 @@ fn use_file_fallback(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
7768
7869#[ inline]
7970pub fn fill_inner ( dest : & mut [ MaybeUninit < u8 > ] ) -> Result < ( ) , Error > {
80- // Despite being only a single atomic variable, we still cannot always use
81- // Ordering::Relaxed, as we need to make sure a successful call to `init`
82- // is "ordered before" any data read through the returned pointer (which
83- // occurs when the function is called). Our implementation mirrors that of
84- // the one in libstd, meaning that the use of non-Relaxed operations is
85- // probably unnecessary.
86- let raw_ptr = GETRANDOM_FN . load ( Ordering :: Acquire ) ;
87- let fptr = match NonNull :: new ( raw_ptr) {
88- Some ( p) => p,
89- None => init ( ) ,
90- } ;
71+ #[ path = "../utils/lazy_ptr.rs" ]
72+ mod lazy;
73+
74+ static GETRANDOM_FN : lazy:: LazyPtr < c_void > = lazy:: LazyPtr :: new ( ) ;
75+ let fptr = GETRANDOM_FN . unsync_init ( init) ;
9176
9277 if fptr == NOT_AVAILABLE {
9378 use_file_fallback ( dest)
9479 } else {
9580 // note: `transmute` is currently the only way to convert a pointer into a function reference
96- let getrandom_fn = unsafe { transmute :: < NonNull < c_void > , GetRandomFn > ( fptr) } ;
81+ let getrandom_fn = unsafe { transmute :: < * mut c_void , GetRandomFn > ( fptr. as_ptr ( ) ) } ;
9782 utils:: sys_fill_exact ( dest, |buf| unsafe {
9883 getrandom_fn ( buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) , 0 )
9984 } )
0 commit comments