/src/rt/rust_util.h
http://github.com/jruderman/rust · C Header · 191 lines · 150 code · 24 blank · 17 comment · 12 complexity · 21a0ff542db7cd80a3152112a6ce48da MD5 · raw file
- #ifndef RUST_UTIL_H
- #define RUST_UTIL_H
- #include <limits.h>
- #include "rust_task.h"
- #include "rust_env.h"
- extern struct type_desc str_body_tydesc;
- // Inline fn used regularly elsewhere.
- static inline size_t
- next_power_of_two(size_t s)
- {
- size_t tmp = s - 1;
- tmp |= tmp >> 1;
- tmp |= tmp >> 2;
- tmp |= tmp >> 4;
- tmp |= tmp >> 8;
- tmp |= tmp >> 16;
- #ifdef _LP64
- tmp |= tmp >> 32;
- #endif
- return tmp + 1;
- }
- // Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
- // of two.
- template<typename T>
- static inline T
- align_to(T size, size_t alignment) {
- assert(alignment);
- T x = (T)(((uintptr_t)size + alignment - 1) & ~(alignment - 1));
- return x;
- }
- // Interior vectors (rust-user-code level).
- struct
- rust_vec
- {
- size_t fill; // in bytes; if zero, heapified
- size_t alloc; // in bytes
- uint8_t data[0];
- };
- struct
- rust_vec_box
- {
- rust_opaque_box header;
- rust_vec body;
- };
- template <typename T>
- inline size_t vec_size(size_t elems) {
- return sizeof(rust_vec_box) + sizeof(T) * elems;
- }
- template <typename T>
- inline T *
- vec_data(rust_vec *v) {
- return reinterpret_cast<T*>(v->data);
- }
- inline void reserve_vec_exact_shared(rust_task* task, rust_vec_box** vpp,
- size_t size) {
- rust_opaque_box** ovpp = (rust_opaque_box**)vpp;
- if (size > (*vpp)->body.alloc) {
- *vpp = (rust_vec_box*)task->boxed.realloc(
- *ovpp, size + sizeof(rust_vec));
- (*vpp)->body.alloc = size;
- }
- }
- inline void reserve_vec_exact(rust_task* task, rust_vec_box** vpp,
- size_t size) {
- if (size > (*vpp)->body.alloc) {
- *vpp = (rust_vec_box*)task->kernel
- ->realloc(*vpp, size + sizeof(rust_vec_box));
- (*vpp)->body.alloc = size;
- }
- }
- inline void reserve_vec(rust_task* task, rust_vec_box** vpp, size_t size) {
- reserve_vec_exact(task, vpp, next_power_of_two(size));
- }
- typedef rust_vec_box rust_str;
- inline rust_str *
- make_str(rust_kernel* kernel, const char* c, size_t strlen,
- const char* name) {
- size_t str_fill = strlen + 1;
- size_t str_alloc = str_fill;
- rust_str *str = (rust_str *)
- kernel->malloc(vec_size<char>(str_fill), name);
- str->header.td = &str_body_tydesc;
- str->body.fill = str_fill;
- str->body.alloc = str_alloc;
- memcpy(&str->body.data, c, strlen);
- str->body.data[strlen] = '\0';
- return str;
- }
- inline rust_vec_box *
- make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) {
- rust_vec_box *v = (rust_vec_box *)
- kernel->malloc(vec_size<rust_vec_box*>(nstrs),
- "str vec interior");
- // FIXME: should have a real td (Issue #2639)
- v->header.td = NULL;
- v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs;
- for (size_t i = 0; i < nstrs; ++i) {
- rust_str *str = make_str(kernel, strs[i],
- strlen(strs[i]),
- "str");
- ((rust_str**)&v->body.data)[i] = str;
- }
- return v;
- }
- inline size_t get_box_size(size_t body_size, size_t body_align) {
- size_t header_size = sizeof(rust_opaque_box);
- // FIXME (#2699): This alignment calculation is suspicious. Is it right?
- size_t total_size = align_to(header_size, body_align) + body_size;
- return total_size;
- }
- // Initialization helpers for ISAAC RNG
- inline void isaac_seed(rust_kernel* kernel, uint8_t* dest, size_t size)
- {
- #ifdef __WIN32__
- HCRYPTPROV hProv;
- kernel->win32_require
- (_T("CryptAcquireContext"),
- CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
- kernel->win32_require
- (_T("CryptGenRandom"), CryptGenRandom(hProv, size, (BYTE*) dest));
- kernel->win32_require
- (_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0));
- #else
- int fd = open("/dev/urandom", O_RDONLY);
- assert(fd > 0);
- size_t amount = 0;
- do {
- ssize_t ret = read(fd, dest+amount, size-amount);
- assert(ret >= 0);
- amount += (size_t)ret;
- } while (amount < size);
- int ret = close(fd);
- assert(ret == 0);
- #endif
- }
- inline void
- isaac_init(rust_kernel *kernel, randctx *rctx, rust_vec_box* user_seed)
- {
- memset(rctx, 0, sizeof(randctx));
- char *env_seed = kernel->env->rust_seed;
- if (user_seed != NULL) {
- // ignore bytes after the required length
- size_t seed_len = user_seed->body.fill < sizeof(rctx->randrsl)
- ? user_seed->body.fill : sizeof(rctx->randrsl);
- memcpy(&rctx->randrsl, user_seed->body.data, seed_len);
- } else if (env_seed != NULL) {
- ub4 seed = (ub4) atoi(env_seed);
- for (size_t i = 0; i < RANDSIZ; i ++) {
- memcpy(&rctx->randrsl[i], &seed, sizeof(ub4));
- seed = (seed + 0x7ed55d16) + (seed << 12);
- }
- } else {
- isaac_seed(kernel, (uint8_t*) &rctx->randrsl, sizeof(rctx->randrsl));
- }
- randinit(rctx, 1);
- }
- //
- // Local Variables:
- // mode: C++
- // fill-column: 78;
- // indent-tabs-mode: nil
- // c-basic-offset: 4
- // buffer-file-coding-system: utf-8-unix
- // End:
- //
- #endif