about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/sched.rs50
-rw-r--r--src/libstd/rt/task.rs2
2 files changed, 50 insertions, 2 deletions
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index cbffec51cc9..ee43ced44ab 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -140,7 +140,7 @@ impl Scheduler {
             cleanup_job: None,
             run_anything: run_anything,
             friend_handle: friend,
-            rng: XorShiftRng::new(),
+            rng: new_sched_rng(),
             idle_callback: None,
             yield_check_count: 0,
             steal_for_yield: false
@@ -844,6 +844,54 @@ impl ClosureConverter for UnsafeTaskReceiver {
     fn to_fn(self) -> &fn(&mut Scheduler, ~Task) { unsafe { transmute(self) } }
 }
 
+// On unix, we read randomness straight from /dev/urandom, but the
+// default constructor of an XorShiftRng does this via io::file, which
+// relies on the scheduler existing, so we have to manually load
+// randomness. Windows has its own C API for this, so we don't need to
+// worry there.
+#[cfg(windows)]
+fn new_sched_rng() -> XorShiftRng {
+    XorShiftRng::new()
+}
+#[cfg(unix)]
+#[fixed_stack_segment] #[inline(never)]
+fn new_sched_rng() -> XorShiftRng {
+    use libc;
+    use sys;
+    use c_str::ToCStr;
+    use vec::MutableVector;
+    use iter::Iterator;
+    use rand::SeedableRng;
+
+    let fd = do "/dev/urandom".with_c_str |name| {
+        unsafe { libc::open(name, libc::O_RDONLY, 0) }
+    };
+    if fd == -1 {
+        rtabort!("could not open /dev/urandom for reading.")
+    }
+
+    let mut seeds = [0u32, .. 4];
+    let size = sys::size_of_val(&seeds);
+    loop {
+        let nbytes = do seeds.as_mut_buf |buf, _| {
+            unsafe {
+                libc::read(fd,
+                           buf as *mut libc::c_void,
+                           size as libc::size_t)
+            }
+        };
+        rtassert!(nbytes as uint == size);
+
+        if !seeds.iter().all(|x| *x == 0) {
+            break;
+        }
+    }
+
+    unsafe {libc::close(fd);}
+
+    SeedableRng::from_seed(seeds)
+}
+
 #[cfg(test)]
 mod test {
     extern mod extra;
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 2d1b57cebf5..48b894f51e0 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -509,7 +509,7 @@ mod test {
         do run_in_newsched_task() {
             use rand::{rng, Rng};
             let mut r = rng();
-            let _ = r.next();
+            let _ = r.next_u32();
         }
     }