Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make core::rand work with newsched #6307

Merged
merged 3 commits into from
May 8, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/libcore/rt/local_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,13 @@ mod test {
assert!(result.is_err());
}
}

#[test]
fn rng() {
do run_in_newsched_task() {
use rand::{rng, Rng};
let r = rng();
let _ = r.next();
}
}
}
9 changes: 4 additions & 5 deletions src/rt/rust_builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ rand_seed_size() {

extern "C" CDECL void
rand_gen_seed(uint8_t* dest, size_t size) {
rust_task *task = rust_get_current_task();
rng_gen_seed(task->kernel, dest, size);
rng_gen_seed(dest, size);
}

extern "C" CDECL void *
Expand All @@ -101,14 +100,14 @@ rand_new_seeded(uint8_t* seed, size_t seed_size) {
task->fail();
return NULL;
}
rng_init(task->kernel, rng, seed, seed_size);
char *env_seed = task->kernel->env->rust_seed;
rng_init(rng, env_seed, seed, seed_size);
return rng;
}

extern "C" CDECL uint32_t
rand_next(rust_rng *rng) {
rust_task *task = rust_get_current_task();
return rng_gen_u32(task->kernel, rng);
return rng_gen_u32(rng);
}

extern "C" CDECL void
Expand Down
19 changes: 0 additions & 19 deletions src/rt/rust_kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,25 +257,6 @@ rust_kernel::generate_task_id() {
return id;
}

#ifdef __WIN32__
void
rust_kernel::win32_require(LPCTSTR fn, BOOL ok) {
if (!ok) {
LPTSTR buf;
DWORD err = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &buf, 0, NULL );
KLOG_ERR_(dom, "%s failed with error %ld: %s", fn, err, buf);
LocalFree((HLOCAL)buf);
assert(ok);
}
}
#endif

void
rust_kernel::set_exit_status(int code) {
scoped_lock with(rval_lock);
Expand Down
4 changes: 0 additions & 4 deletions src/rt/rust_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,6 @@ class rust_kernel {
void wait_for_schedulers();
int run();

#ifdef __WIN32__
void win32_require(LPCTSTR fn, BOOL ok);
#endif

rust_task_id generate_task_id();

void set_exit_status(int code);
Expand Down
76 changes: 50 additions & 26 deletions src/rt/rust_rng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@
#include "rust_rng.h"
#include "rust_util.h"


#ifdef __WIN32__
void
win32_require(LPCTSTR fn, BOOL ok) {
if (!ok) {
LPTSTR buf;
DWORD err = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &buf, 0, NULL );
fprintf(stderr, "%s failed with error %ld: %s", fn, err, buf);
LocalFree((HLOCAL)buf);
abort();
}
}
#endif

size_t
rng_seed_size() {
randctx rctx;
Expand All @@ -21,44 +41,50 @@ rng_seed_size() {
// Initialization helpers for ISAAC RNG

void
rng_gen_seed(rust_kernel* kernel, uint8_t* dest, size_t size) {
rng_gen_seed(uint8_t* dest, size_t size) {
#ifdef __WIN32__
HCRYPTPROV hProv;
kernel->win32_require
win32_require
(_T("CryptAcquireContext"),
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
kernel->win32_require
win32_require
(_T("CryptGenRandom"), CryptGenRandom(hProv, size, (BYTE*) dest));
kernel->win32_require
win32_require
(_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0));
#else
int fd = open("/dev/urandom", O_RDONLY);
if (fd == -1)
kernel->fatal("error opening /dev/urandom: %s", strerror(errno));
if (fd == -1) {
fprintf(stderr, "error opening /dev/urandom: %s", strerror(errno));
abort();
}
size_t amount = 0;
do {
ssize_t ret = read(fd, dest+amount, size-amount);
if (ret < 0)
kernel->fatal("error reading /dev/urandom: %s", strerror(errno));
else if (ret == 0)
kernel->fatal("somehow hit eof reading from /dev/urandom");
if (ret < 0) {
fprintf(stderr, "error reading /dev/urandom: %s", strerror(errno));
abort();
}
else if (ret == 0) {
fprintf(stderr, "somehow hit eof reading from /dev/urandom");
abort();
}
amount += (size_t)ret;
} while (amount < size);
int ret = close(fd);
// FIXME #3697: Why does this fail sometimes?
if (ret != 0)
kernel->log(log_warn, "error closing /dev/urandom: %s",
strerror(errno));
if (ret != 0) {
fprintf(stderr, "error closing /dev/urandom: %s", strerror(errno));
// FIXME #3697: Why does this fail sometimes?
// abort();
}
#endif
}

static void
isaac_init(rust_kernel *kernel, randctx *rctx,
isaac_init(randctx *rctx, char *env_seed,
uint8_t* user_seed, size_t seed_len) {
memset(rctx, 0, sizeof(randctx));

char *env_seed = kernel->env->rust_seed;
if (user_seed != NULL) {
// ignore bytes after the required length
if (seed_len > sizeof(rctx->randrsl)) {
Expand All @@ -72,40 +98,38 @@ isaac_init(rust_kernel *kernel, randctx *rctx,
seed = (seed + 0x7ed55d16) + (seed << 12);
}
} else {
rng_gen_seed(kernel,
(uint8_t*)&rctx->randrsl,
rng_gen_seed((uint8_t*)&rctx->randrsl,
sizeof(rctx->randrsl));
}

randinit(rctx, 1);
}

void
rng_init(rust_kernel* kernel, rust_rng* rng,
rng_init(rust_rng* rng, char* env_seed,
uint8_t *user_seed, size_t seed_len) {
isaac_init(kernel, &rng->rctx, user_seed, seed_len);
rng->reseedable = !user_seed && !kernel->env->rust_seed;
isaac_init(&rng->rctx, env_seed, user_seed, seed_len);
rng->reseedable = !user_seed && !env_seed;
}

static void
rng_maybe_reseed(rust_kernel* kernel, rust_rng* rng) {
rng_maybe_reseed(rust_rng* rng) {
// If this RNG has generated more than 32KB of random data and was not
// seeded by the user or RUST_SEED, then we should reseed now.
const size_t RESEED_THRESHOLD = 32 * 1024;
size_t bytes_generated = rng->rctx.randc * sizeof(ub4);
if (bytes_generated < RESEED_THRESHOLD || !rng->reseedable) {
return;
}
rng_gen_seed(kernel,
(uint8_t*)rng->rctx.randrsl,
rng_gen_seed((uint8_t*)rng->rctx.randrsl,
sizeof(rng->rctx.randrsl));
randinit(&rng->rctx, 1);
}

uint32_t
rng_gen_u32(rust_kernel* kernel, rust_rng* rng) {
rng_gen_u32(rust_rng* rng) {
uint32_t x = isaac_rand(&rng->rctx);
rng_maybe_reseed(kernel, rng);
rng_maybe_reseed(rng);
return x;
}

Expand Down
7 changes: 3 additions & 4 deletions src/rt/rust_rng.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ struct rust_rng {
};

size_t rng_seed_size();
void rng_gen_seed(rust_kernel* kernel,
uint8_t* dest, size_t size);
void rng_init(rust_kernel *kernel, rust_rng *rng,
void rng_gen_seed(uint8_t* dest, size_t size);
void rng_init(rust_rng *rng, char *env_seed,
uint8_t *user_seed, size_t seed_len);
uint32_t rng_gen_u32(rust_kernel *kernel, rust_rng *rng);
uint32_t rng_gen_u32(rust_rng *rng);

//
// Local Variables:
Expand Down
4 changes: 2 additions & 2 deletions src/rt/rust_sched_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) :
name("main")
{
LOGPTR(this, "new dom", (uintptr_t)this);
rng_init(kernel, &rng, NULL, 0);
rng_init(&rng, kernel->env->rust_seed, NULL, 0);

if (!tls_initialized)
init_tls();
Expand Down Expand Up @@ -154,7 +154,7 @@ rust_sched_loop::schedule_task() {
lock.must_have_lock();
size_t tasks = running_tasks.length();
if (tasks > 0) {
size_t i = (tasks > 1) ? (rng_gen_u32(kernel, &rng) % tasks) : 0;
size_t i = (tasks > 1) ? (rng_gen_u32(&rng) % tasks) : 0;
return running_tasks[i];
}
return NULL;
Expand Down