Skip to content

Commit c16d298

Browse files
committed
Require CAS for rand
1 parent f109f21 commit c16d298

File tree

2 files changed

+8
-17
lines changed

2 files changed

+8
-17
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ memchr = []
6262
qsort = []
6363
rand_r = []
6464
rand = ["rand_r", "dep:portable-atomic"]
65+
rand-cs = ["rand", "portable-atomic/critical-section"]
6566
signal = ["dep:portable-atomic"]
6667
signal-cs = ["portable-atomic/critical-section"]
6768
snprintf = []

src/rand.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ 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)]
2529
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 {
2930
let mut current_state = RAND_STATE.load(Ordering::Relaxed);
3031
let mut new_state = current_state;
3132
let mut result = unsafe { crate::rand_r(&mut new_state as *mut _) };
@@ -45,17 +46,6 @@ pub extern "C" fn rand() -> c_int {
4546
}
4647

4748
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 _
56-
}
57-
portable_atomic::cfg_has_atomic_cas! { with_cas() }
58-
portable_atomic::cfg_no_atomic_cas! { without_cas() }
5949
}
6050

6151
#[cfg(test)]

0 commit comments

Comments
 (0)