@@ -17,45 +17,35 @@ pub extern "C" fn srand(seed: c_uint) {
17
17
RAND_STATE . store ( seed, Ordering :: Release ) ;
18
18
}
19
19
20
- /// Rust implementation of C library function `rand`
20
+ /// Rust implementation of C library function `rand`.
21
21
///
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).
24
28
#[ cfg_attr( feature = "rand" , no_mangle) ]
25
29
pub 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 _ ) } ;
32
33
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,
45
43
}
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 _ ) } ;
56
46
}
57
- portable_atomic :: cfg_has_atomic_cas! { with_cas ( ) }
58
- portable_atomic :: cfg_no_atomic_cas! { without_cas ( ) }
47
+
48
+ result as _
59
49
}
60
50
61
51
#[ cfg( test) ]
0 commit comments