Expose an RNG (the one used by our runtime) to Rust via std.
This commit is contained in:
parent
7ef9e82f51
commit
5b6e714d05
7 changed files with 114 additions and 25 deletions
|
@ -424,6 +424,7 @@ TEST_XFAILS_LLVM := $(addprefix test/run-pass/, \
|
||||||
lazy-and-or.rs \
|
lazy-and-or.rs \
|
||||||
lazy-init.rs \
|
lazy-init.rs \
|
||||||
lazychan.rs \
|
lazychan.rs \
|
||||||
|
lib-rand.rs \
|
||||||
linear-for-loop.rs \
|
linear-for-loop.rs \
|
||||||
list.rs \
|
list.rs \
|
||||||
many.rs \
|
many.rs \
|
||||||
|
|
25
src/lib/rand.rs
Normal file
25
src/lib/rand.rs
Normal file
|
@ -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());
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ auth _vec = unsafe;
|
||||||
|
|
||||||
auth _int.next_power_of_two = unsafe;
|
auth _int.next_power_of_two = unsafe;
|
||||||
auth map.mk_hashmap = unsafe;
|
auth map.mk_hashmap = unsafe;
|
||||||
|
auth rand.mk_rng = unsafe;
|
||||||
|
|
||||||
// Target-OS module.
|
// Target-OS module.
|
||||||
|
|
||||||
|
@ -43,3 +44,4 @@ alt (target_os) {
|
||||||
|
|
||||||
mod map;
|
mod map;
|
||||||
mod deque;
|
mod deque;
|
||||||
|
mod rand;
|
||||||
|
|
|
@ -127,6 +127,31 @@ vec_len(rust_task *task, type_desc *ty, rust_vec *v)
|
||||||
return v->fill / ty->size;
|
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:
|
// Local Variables:
|
||||||
// mode: C++
|
// mode: C++
|
||||||
|
|
|
@ -36,35 +36,12 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate) :
|
||||||
rval(0)
|
rval(0)
|
||||||
{
|
{
|
||||||
logptr("new dom", (uintptr_t)this);
|
logptr("new dom", (uintptr_t)this);
|
||||||
memset(&rctx, 0, sizeof(rctx));
|
isaac_init(this, &rctx);
|
||||||
|
#ifndef __WIN32__
|
||||||
#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);
|
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||||
pthread_attr_setdetachstate(&attr, true);
|
pthread_attr_setdetachstate(&attr, true);
|
||||||
#endif
|
#endif
|
||||||
randinit(&rctx, 1);
|
|
||||||
|
|
||||||
root_task = new (this) rust_task(this, NULL);
|
root_task = new (this) rust_task(this, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,38 @@ next_power_of_two(size_t s)
|
||||||
return tmp + 1;
|
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).
|
// Vectors (rust-user-code level).
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
|
27
src/test/run-pass/lib-rand.rs
Normal file
27
src/test/run-pass/lib-rand.rs
Normal file
|
@ -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();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue