diff --git a/src/libcore/rt/local_services.rs b/src/libcore/rt/local_services.rs index a03bc6c409f8b..b83e1d2464890 100644 --- a/src/libcore/rt/local_services.rs +++ b/src/libcore/rt/local_services.rs @@ -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(); + } + } } \ No newline at end of file diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index a491379153e1a..885b40c0a5062 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -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 * @@ -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 diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index 761dbeade538b..bf48554696ebd 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -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); diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h index ec0515faeafc0..4976dec149a02 100644 --- a/src/rt/rust_kernel.h +++ b/src/rt/rust_kernel.h @@ -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); diff --git a/src/rt/rust_rng.cpp b/src/rt/rust_rng.cpp index 2c11691bf86b9..5cb91f4381187 100644 --- a/src/rt/rust_rng.cpp +++ b/src/rt/rust_rng.cpp @@ -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 ); + KLOG_ERR_(dom, "%s failed with error %ld: %s", fn, err, buf); + LocalFree((HLOCAL)buf); + assert(ok); + } +} +#endif + size_t rng_seed_size() { randctx rctx; @@ -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)) { @@ -72,8 +98,7 @@ 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)); } @@ -81,14 +106,14 @@ isaac_init(rust_kernel *kernel, randctx *rctx, } 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; @@ -96,16 +121,15 @@ rng_maybe_reseed(rust_kernel* kernel, rust_rng* rng) { 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; } diff --git a/src/rt/rust_rng.h b/src/rt/rust_rng.h index 3879b1138fa20..a13b5acd0eff2 100644 --- a/src/rt/rust_rng.h +++ b/src/rt/rust_rng.h @@ -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: diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp index 2911b970b1359..1f718df32aac9 100644 --- a/src/rt/rust_sched_loop.cpp +++ b/src/rt/rust_sched_loop.cpp @@ -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(); @@ -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;