Skip to content

Commit

Permalink
Add RDRAND feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Jethro Beekman committed Jul 9, 2016
1 parent 76bf777 commit 6ca4943
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 19 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ default = ["libc"]
no_std = []
box = [] # enable use of Box on no_std, requires alloc crate and feature
vec = [] # enable use of Vec on no_std, requires collections crate and feature
rdrand = []

[dev-dependencies]
log = "0.3.0"
37 changes: 23 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
#![cfg_attr(feature="no_std",no_std)]
#![cfg_attr(feature="box",feature(alloc))]
#![cfg_attr(feature="vec",feature(collections))]
#![cfg_attr(feature="rdrand",feature(asm))]

#[cfg(test)] #[macro_use] extern crate log;

Expand All @@ -252,16 +253,16 @@
#[cfg(feature="box")] extern crate alloc;
#[cfg(feature="vec")] extern crate collections;

#[cfg(not(feature="no_std"))] use core::cell::RefCell;
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))] use core::cell::RefCell;
use core::marker;
use core::mem;
#[cfg(not(feature="no_std"))] use std::io;
#[cfg(not(feature="no_std"))] use std::rc::Rc;
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))] use std::rc::Rc;
use core::num::Wrapping as w;
#[cfg(feature="box")] use alloc::boxed::Box;
#[cfg(feature="vec")] use collections::vec::Vec;

#[cfg(not(feature="no_std"))] pub use os::OsRng;
#[cfg(any(not(feature="no_std"),feature="rdrand"))] pub use os::OsRng;

pub use isaac::{IsaacRng, Isaac64Rng};
pub use chacha::ChaChaRng;
Expand All @@ -279,7 +280,7 @@ pub mod isaac;
pub mod chacha;
pub mod reseeding;
mod rand_impls;
#[cfg(not(feature="no_std"))] pub mod os;
#[cfg(any(not(feature="no_std"),feature="rdrand"))] pub mod os;
#[cfg(any(not(feature="no_std"),feature="core_io"))] pub mod read;

#[allow(bad_style)]
Expand Down Expand Up @@ -816,7 +817,7 @@ impl StdRng {
///
/// Reading the randomness from the OS may fail, and any error is
/// propagated via the `io::Result` return value.
#[cfg(not(feature="no_std"))]
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
pub fn new() -> io::Result<StdRng> {
OsRng::new().map(|mut r| StdRng { rng: r.gen() })
}
Expand Down Expand Up @@ -855,7 +856,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng {
///
/// This will read randomness from the operating system to seed the
/// generator.
#[cfg(not(feature="no_std"))]
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
pub fn weak_rng() -> XorShiftRng {
match OsRng::new() {
Ok(mut r) => r.gen(),
Expand All @@ -864,10 +865,10 @@ pub fn weak_rng() -> XorShiftRng {
}

/// Controls how the thread-local RNG is reseeded.
#[cfg(not(feature="no_std"))]
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
struct ThreadRngReseeder;

#[cfg(not(feature="no_std"))]
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
fn reseed(&mut self, rng: &mut StdRng) {
*rng = match StdRng::new() {
Expand All @@ -876,14 +877,14 @@ impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
}
}
}
#[cfg(not(feature="no_std"))]
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
#[cfg(not(feature="no_std"))]
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;

/// The thread-local RNG.
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
#[derive(Clone)]
#[cfg(not(feature="no_std"))]
pub struct ThreadRng {
rng: Rc<RefCell<ThreadRngInner>>,
}
Expand All @@ -899,7 +900,7 @@ pub struct ThreadRng {
/// if the operating system random number generator is rigged to give
/// the same sequence always. If absolute consistency is required,
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
#[cfg(not(feature="no_std"))]
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
pub fn thread_rng() -> ThreadRng {
// used to make space in TLS for a random number generator
thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
Expand All @@ -916,7 +917,7 @@ pub fn thread_rng() -> ThreadRng {
ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
}

#[cfg(not(feature="no_std"))]
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
impl Rng for ThreadRng {
fn next_u32(&mut self) -> u32 {
self.rng.borrow_mut().next_u32()
Expand All @@ -932,6 +933,14 @@ impl Rng for ThreadRng {
}
}

#[cfg(feature="rdrand")]
pub use os::OsRng as ThreadRng;

#[cfg(feature="rdrand")]
pub fn thread_rng() -> ThreadRng {
OsRng::new().unwrap()
}

/// Generates a random value using the thread-local random number generator.
///
/// `random()` can generate various types of random things, and so may require
Expand Down Expand Up @@ -974,7 +983,7 @@ impl Rng for ThreadRng {
/// *x = rng.gen();
/// }
/// ```
#[cfg(not(feature="no_std"))]
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
#[inline]
pub fn random<T: Rand>() -> T {
thread_rng().gen()
Expand Down
41 changes: 36 additions & 5 deletions src/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
//! Interfaces to the operating system provided random number
//! generators.

use std::io;
#[cfg(not(feature="no_std"))] use std::io;
#[cfg(feature="no_std")] use io;
use Rng;

/// A random number generator that retrieves randomness straight from
Expand Down Expand Up @@ -41,7 +42,7 @@ impl Rng for OsRng {
}

#[cfg(all(unix, not(target_os = "ios"),
not(target_os = "nacl")))]
not(target_os = "nacl"), not(feature = "rdrand")))]
mod imp {
extern crate libc;

Expand Down Expand Up @@ -198,7 +199,7 @@ mod imp {
}
}

#[cfg(target_os = "ios")]
#[cfg(all(target_os = "ios", not(feature = "rdrand")))]
mod imp {
extern crate libc;

Expand Down Expand Up @@ -248,7 +249,7 @@ mod imp {
}
}

#[cfg(windows)]
#[cfg(all(windows, not(feature = "rdrand")))]
mod imp {
use std::io;
use std::mem;
Expand Down Expand Up @@ -339,7 +340,7 @@ mod imp {
}
}

#[cfg(target_os = "nacl")]
#[cfg(all(target_os = "nacl", not(feature = "rdrand")))]
mod imp {
extern crate libc;

Expand Down Expand Up @@ -417,6 +418,36 @@ mod imp {
}


#[cfg(feature = "rdrand")]
mod imp {
#[cfg(not(feature="no_std"))] use std::io;
#[cfg(feature="no_std")] use io;

use Rng;

pub struct OsRng;

impl OsRng {
pub fn new() -> io::Result<OsRng> {
Ok(OsRng)
}
}

impl Rng for OsRng {
fn next_u32(&mut self) -> u32 {
let ret;
unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")};
ret
}
#[cfg(target_arch="x86_64")]
fn next_u64(&mut self) -> u64 {
let ret;
unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")};
ret
}
}
}

#[cfg(test)]
mod test {
use std::sync::mpsc::channel;
Expand Down

0 comments on commit 6ca4943

Please sign in to comment.