feat(rand48): rwlock for global params

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2024-12-31 01:21:47 +11:00
parent bc51d8e1d5
commit 5eeb59dad2
3 changed files with 37 additions and 15 deletions
+9 -9
View File
@@ -297,7 +297,7 @@ pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
/// state.
#[no_mangle]
pub extern "C" fn drand48() -> c_double {
let params = rand48::params_lock();
let params = rand48::params();
let mut xsubi = rand48::xsubi_lock();
*xsubi = params.step(*xsubi);
xsubi.get_f64()
@@ -330,7 +330,7 @@ pub extern "C" fn ecvt(
/// state.
#[no_mangle]
pub unsafe extern "C" fn erand48(xsubi: *mut c_ushort) -> c_double {
let params = rand48::params_lock();
let params = rand48::params();
let xsubi_mut: &mut [c_ushort; 3] = slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap();
let new_xsubi_value = params.step(xsubi_mut.into());
*xsubi_mut = new_xsubi_value.into();
@@ -521,7 +521,7 @@ pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: size_
/// state.
#[no_mangle]
pub unsafe extern "C" fn jrand48(xsubi: *mut c_ushort) -> c_long {
let params = rand48::params_lock();
let params = rand48::params();
let xsubi_mut: &mut [c_ushort; 3] = slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap();
let new_xsubi_value = params.step(xsubi_mut.into());
*xsubi_mut = new_xsubi_value.into();
@@ -586,7 +586,7 @@ pub extern "C" fn labs(i: c_long) -> c_long {
#[no_mangle]
pub unsafe extern "C" fn lcong48(param: *mut c_ushort) {
let mut xsubi = rand48::xsubi_lock();
let mut params = rand48::params_lock();
let mut params = rand48::params_mut();
let param_slice = slice::from_raw_parts(param, 7);
@@ -643,7 +643,7 @@ pub extern "C" fn lldiv(numer: c_longlong, denom: c_longlong) -> lldiv_t {
/// state.
#[no_mangle]
pub extern "C" fn lrand48() -> c_long {
let params = rand48::params_lock();
let params = rand48::params();
let mut xsubi = rand48::xsubi_lock();
*xsubi = params.step(*xsubi);
xsubi.get_u31()
@@ -843,7 +843,7 @@ pub unsafe extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
/// state.
#[no_mangle]
pub extern "C" fn mrand48() -> c_long {
let params = rand48::params_lock();
let params = rand48::params();
let mut xsubi = rand48::xsubi_lock();
*xsubi = params.step(*xsubi);
xsubi.get_i32()
@@ -860,7 +860,7 @@ pub extern "C" fn mrand48() -> c_long {
/// state.
#[no_mangle]
pub unsafe extern "C" fn nrand48(xsubi: *mut c_ushort) -> c_long {
let params = rand48::params_lock();
let params = rand48::params();
let xsubi_mut: &mut [c_ushort; 3] = slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap();
let new_xsubi_value = params.step(xsubi_mut.into());
*xsubi_mut = new_xsubi_value.into();
@@ -1196,7 +1196,7 @@ pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
pub unsafe extern "C" fn seed48(seed16v: *mut c_ushort) -> *mut c_ushort {
static mut BUFFER: [c_ushort; 3] = [0; 3];
let mut params = rand48::params_lock();
let mut params = rand48::params_mut();
let mut xsubi = rand48::xsubi_lock();
let seed16v_ref: &[c_ushort; 3] = slice::from_raw_parts(seed16v, 3).try_into().unwrap();
@@ -1296,7 +1296,7 @@ pub unsafe extern "C" fn srand(seed: c_uint) {
/// state.
#[no_mangle]
pub extern "C" fn srand48(seedval: c_long) {
let mut params = rand48::params_lock();
let mut params = rand48::params_mut();
let mut xsubi = rand48::xsubi_lock();
params.reset();
+12 -6
View File
@@ -2,7 +2,7 @@
use crate::{
platform::types::*,
sync::{Mutex, MutexGuard},
sync::{rwlock::{self, RwLock}, Mutex, MutexGuard},
};
/// A 48-bit integer, used for the 48-bit arithmetic in these functions.
@@ -119,13 +119,19 @@ impl Params {
}
}
// TODO: consider using rwlock instead of mutex for more fine-grained access
/// Immediately get the global Params lock, or panic if unsuccessful.
pub fn params_lock<'a>() -> MutexGuard<'a, Params> {
static PARAMS: Mutex<Params> = Mutex::<Params>::new(Params::new());
static PARAMS: RwLock<Params> = RwLock::<Params>::new(Params::new());
/// Immediately get the global [`Params`] lock for reading, or panic if unsuccessful.
pub fn params<'a>() -> rwlock::ReadGuard<'a, Params> {
PARAMS
.try_lock()
.try_read()
.expect("unable to acquire LCG parameter lock")
}
/// Immediately get the global [`Params`] lock for writing, or panic if unsuccessful.
pub fn params_mut<'a>() -> rwlock::WriteGuard<'a, Params> {
PARAMS
.try_write()
.expect("unable to acquire LCG parameter lock")
}
+16
View File
@@ -176,6 +176,22 @@ impl<T: ?Sized> RwLock<T> {
self.inner.acquire_write_lock(None);
unsafe { WriteGuard::new(self) }
}
pub fn try_read(&self) -> Option<ReadGuard<'_, T>> {
if self.inner.try_acquire_read_lock().is_ok() {
Some(unsafe { ReadGuard::new(self) })
} else {
None
}
}
pub fn try_write(&self) -> Option<WriteGuard<'_, T>> {
if self.inner.try_acquire_write_lock().is_ok() {
Some(unsafe { WriteGuard::new(self) })
} else {
None
}
}
}
pub struct ReadGuard<'a, T: ?Sized + 'a> {