@@ -17,45 +17,35 @@ pub extern "C" fn srand(seed: c_uint) {
1717 RAND_STATE . store ( seed, Ordering :: Release ) ;
1818}
1919
20- /// Rust implementation of C library function `rand`
20+ /// Rust implementation of C library function `rand`.
2121///
22- /// Returns a pseudo-random integer in the range 0 to `RAND_MAX` (inclusive).
23- /// May produce the same value in a row if called from multiple threads on platforms not supporting CAS operations.
22+ /// Returns a pseudo-random integer in the range 0 to [`RAND_MAX`](crate::RAND_MAX) (inclusive).
23+ /// This requires CAS operations. If your platform does not support them natively,
24+ /// you either have to enable the `rand-cs` feature of `tinyrlibc`,
25+ /// or the [`critical-section`](https://docs.rs/portable-atomic/1.9.0/portable_atomic/#optional-features-critical-section) feature,
26+ /// or the [`unsafe-assume-single-core`](https://docs.rs/portable-atomic/1.9.0/portable_atomic/#optional-features-unsafe-assume-single-core) feature
27+ /// in [`portable-atomic`](https://crates.io/crates/portable-atomic).
2428#[ cfg_attr( feature = "rand" , no_mangle) ]
2529pub extern "C" fn rand ( ) -> c_int {
26- // Atomically update the global LFSR state using compare_and_swap if available
27- #[ allow( dead_code) ]
28- fn with_cas ( ) -> c_int {
29- let mut current_state = RAND_STATE . load ( Ordering :: Relaxed ) ;
30- let mut new_state = current_state;
31- let mut result = unsafe { crate :: rand_r ( & mut new_state as * mut _ ) } ;
30+ let mut current_state = RAND_STATE . load ( Ordering :: Relaxed ) ;
31+ let mut new_state = current_state;
32+ let mut result = unsafe { crate :: rand_r ( & mut new_state as * mut _ ) } ;
3233
33- loop {
34- match RAND_STATE . compare_exchange_weak (
35- current_state,
36- new_state,
37- Ordering :: SeqCst ,
38- Ordering :: Relaxed ,
39- ) {
40- Ok ( _) => break ,
41- Err ( c) => current_state = c,
42- }
43- new_state = current_state;
44- result = unsafe { crate :: rand_r ( & mut new_state as * mut _ ) } ;
34+ loop {
35+ match RAND_STATE . compare_exchange_weak (
36+ current_state,
37+ new_state,
38+ Ordering :: SeqCst ,
39+ Ordering :: Relaxed ,
40+ ) {
41+ Ok ( _) => break ,
42+ Err ( c) => current_state = c,
4543 }
46-
47- result as _
48- }
49- // Fallback to non-atomic operation if compare_and_swap is not available
50- #[ allow( dead_code) ]
51- fn without_cas ( ) -> c_int {
52- let mut current_state = RAND_STATE . load ( Ordering :: Acquire ) ;
53- let result = unsafe { crate :: rand_r ( & mut current_state as * mut _ ) } ;
54- RAND_STATE . store ( current_state, Ordering :: Release ) ;
55- result as _
44+ new_state = current_state;
45+ result = unsafe { crate :: rand_r ( & mut new_state as * mut _ ) } ;
5646 }
57- portable_atomic :: cfg_has_atomic_cas! { with_cas ( ) }
58- portable_atomic :: cfg_no_atomic_cas! { without_cas ( ) }
47+
48+ result as _
5949}
6050
6151#[ cfg( test) ]
0 commit comments