about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoy Frostig <rfrostig@mozilla.com>2010-07-25 21:45:09 -0700
committerRoy Frostig <rfrostig@mozilla.com>2010-07-25 21:45:09 -0700
commit5b6e714d05a0c96ade618256a67a9cb7f337f196 (patch)
tree45406973ea3c0ffb1a9e070588f4ca5fc8c7744c
parent7ef9e82f51de73e89759910fd1b45ce5ccc363b3 (diff)
downloadrust-5b6e714d05a0c96ade618256a67a9cb7f337f196.tar.gz
rust-5b6e714d05a0c96ade618256a67a9cb7f337f196.zip
Expose an RNG (the one used by our runtime) to Rust via std.
-rw-r--r--src/Makefile1
-rw-r--r--src/lib/rand.rs25
-rw-r--r--src/lib/std.rc2
-rw-r--r--src/rt/rust_builtin.cpp25
-rw-r--r--src/rt/rust_dom.cpp27
-rw-r--r--src/rt/rust_util.h32
-rw-r--r--src/test/run-pass/lib-rand.rs27
7 files changed, 114 insertions, 25 deletions
diff --git a/src/Makefile b/src/Makefile
index 8f96fd700b7..638cba0af28 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -424,6 +424,7 @@ TEST_XFAILS_LLVM := $(addprefix test/run-pass/, \
                       lazy-and-or.rs \
                       lazy-init.rs \
                       lazychan.rs \
+                      lib-rand.rs \
                       linear-for-loop.rs \
                       list.rs \
                       many.rs \
diff --git a/src/lib/rand.rs b/src/lib/rand.rs
new file mode 100644
index 00000000000..96dcbaf7d73
--- /dev/null
+++ b/src/lib/rand.rs
@@ -0,0 +1,25 @@
+/**
+ * Bindings the runtime's random number generator (ISAAC).
+ */
+
+native "rust" mod rustrt {
+  type rctx;
+  fn rand_new() -> rctx;
+  fn rand_next(rctx c) -> u32;
+  fn rand_free(rctx c);
+}
+
+type rng = obj { fn next() -> u32; };
+
+fn mk_rng() -> rng {
+  obj rt_rng(rustrt.rctx c) {
+    fn next() -> u32 {
+      ret rustrt.rand_next(c);
+    }
+    drop {
+      rustrt.rand_free(c);
+    }
+  }
+
+  ret rt_rng(rustrt.rand_new());
+}
diff --git a/src/lib/std.rc b/src/lib/std.rc
index dfc404ecbe9..8c956691f98 100644
--- a/src/lib/std.rc
+++ b/src/lib/std.rc
@@ -28,6 +28,7 @@ auth _vec = unsafe;
 
 auth _int.next_power_of_two = unsafe;
 auth map.mk_hashmap = unsafe;
+auth rand.mk_rng = unsafe;
 
 // Target-OS module.
 
@@ -43,3 +44,4 @@ alt (target_os) {
 
 mod map;
 mod deque;
+mod rand;
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 99fa953580c..e8d2d67d3c7 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -127,6 +127,31 @@ vec_len(rust_task *task, type_desc *ty, rust_vec *v)
     return v->fill / ty->size;
 }
 
+extern "C" CDECL void *
+rand_new(rust_task *task)
+{
+    rust_dom *dom = task->dom;
+    randctx *rctx = (randctx *) task->malloc(sizeof(randctx));
+    if (!rctx) {
+        task->fail(1);
+        return NULL;
+    }
+    isaac_init(dom, rctx);
+    return rctx;
+}
+
+extern "C" CDECL size_t
+rand_next(rust_task *task, randctx *rctx)
+{
+    return rand(rctx);
+}
+
+extern "C" CDECL void
+rand_free(rust_task *task, randctx *rctx)
+{
+    task->free(rctx);
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp
index ac1e7d0cc42..205084ff263 100644
--- a/src/rt/rust_dom.cpp
+++ b/src/rt/rust_dom.cpp
@@ -36,35 +36,12 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate) :
     rval(0)
 {
     logptr("new dom", (uintptr_t)this);
-    memset(&rctx, 0, sizeof(rctx));
-
-#ifdef __WIN32__
-    {
-        HCRYPTPROV hProv;
-        win32_require
-            (_T("CryptAcquireContext"),
-             CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
-                                 CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
-        win32_require
-            (_T("CryptGenRandom"),
-             CryptGenRandom(hProv, sizeof(rctx.randrsl),
-                            (BYTE*)(&rctx.randrsl)));
-        win32_require
-            (_T("CryptReleaseContext"),
-             CryptReleaseContext(hProv, 0));
-    }
-#else
-    int fd = open("/dev/urandom", O_RDONLY);
-    I(this, fd > 0);
-    I(this, read(fd, (void*) &rctx.randrsl, sizeof(rctx.randrsl))
-      == sizeof(rctx.randrsl));
-    I(this, close(fd) == 0);
+    isaac_init(this, &rctx);
+#ifndef __WIN32__
     pthread_attr_init(&attr);
     pthread_attr_setstacksize(&attr, 1024 * 1024);
     pthread_attr_setdetachstate(&attr, true);
 #endif
-    randinit(&rctx, 1);
-
     root_task = new (this) rust_task(this, NULL);
 }
 
diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h
index 62ac7de2d25..95010f17830 100644
--- a/src/rt/rust_util.h
+++ b/src/rt/rust_util.h
@@ -117,6 +117,38 @@ next_power_of_two(size_t s)
     return tmp + 1;
 }
 
+// Initialization helper for ISAAC RNG
+
+static inline void
+isaac_init(rust_dom *dom, randctx *rctx)
+{
+        memset(rctx, 0, sizeof(randctx));
+
+#ifdef __WIN32__
+        {
+            HCRYPTPROV hProv;
+            win32_require
+                (_T("CryptAcquireContext"),
+                 CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
+                                     CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
+            win32_require
+                (_T("CryptGenRandom"),
+                 CryptGenRandom(hProv, sizeof(rctx->randrsl),
+                                (BYTE*)(&rctx->randrsl)));
+            win32_require
+                (_T("CryptReleaseContext"),
+                 CryptReleaseContext(hProv, 0));
+        }
+#else
+        int fd = open("/dev/urandom", O_RDONLY);
+        I(dom, fd > 0);
+        I(dom, read(fd, (void*) &rctx->randrsl, sizeof(rctx->randrsl))
+          == sizeof(rctx->randrsl));
+        I(dom, close(fd) == 0);
+#endif
+        randinit(rctx, 1);
+}
+
 // Vectors (rust-user-code level).
 
 struct
diff --git a/src/test/run-pass/lib-rand.rs b/src/test/run-pass/lib-rand.rs
new file mode 100644
index 00000000000..df227f6632c
--- /dev/null
+++ b/src/test/run-pass/lib-rand.rs
@@ -0,0 +1,27 @@
+// -*- rust -*-
+
+use std;
+import std.rand;
+
+fn main() {
+  let rand.rng r1 = rand.mk_rng();
+  log r1.next();
+  log r1.next();
+  {
+    auto r2 = rand.mk_rng();
+    log r1.next();
+    log r2.next();
+    log r1.next();
+    log r1.next();
+    log r2.next();
+    log r2.next();
+    log r1.next();
+    log r1.next();
+    log r1.next();
+    log r2.next();
+    log r2.next();
+    log r2.next();
+  }
+  log r1.next();
+  log r1.next();
+}