PageRenderTime 44ms CodeModel.GetById 2ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  1#ifndef RUST_UTIL_H
  2#define RUST_UTIL_H
  3
  4#include <limits.h>
  5#include "rust_task.h"
  6#include "rust_env.h"
  7
  8extern struct type_desc str_body_tydesc;
  9
 10// Inline fn used regularly elsewhere.
 11
 12static inline size_t
 13next_power_of_two(size_t s)
 14{
 15    size_t tmp = s - 1;
 16    tmp |= tmp >> 1;
 17    tmp |= tmp >> 2;
 18    tmp |= tmp >> 4;
 19    tmp |= tmp >> 8;
 20    tmp |= tmp >> 16;
 21#ifdef _LP64
 22    tmp |= tmp >> 32;
 23#endif
 24    return tmp + 1;
 25}
 26
 27// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
 28// of two.
 29template<typename T>
 30static inline T
 31align_to(T size, size_t alignment) {
 32    assert(alignment);
 33    T x = (T)(((uintptr_t)size + alignment - 1) & ~(alignment - 1));
 34    return x;
 35}
 36
 37// Interior vectors (rust-user-code level).
 38
 39struct
 40rust_vec
 41{
 42    size_t fill;    // in bytes; if zero, heapified
 43    size_t alloc;   // in bytes
 44    uint8_t data[0];
 45};
 46
 47struct
 48rust_vec_box
 49{
 50    rust_opaque_box header;
 51    rust_vec body;
 52};
 53
 54template <typename T>
 55inline size_t vec_size(size_t elems) {
 56    return sizeof(rust_vec_box) + sizeof(T) * elems;
 57}
 58
 59template <typename T>
 60inline T *
 61vec_data(rust_vec *v) {
 62    return reinterpret_cast<T*>(v->data);
 63}
 64
 65inline void reserve_vec_exact_shared(rust_task* task, rust_vec_box** vpp,
 66                                     size_t size) {
 67    rust_opaque_box** ovpp = (rust_opaque_box**)vpp;
 68    if (size > (*vpp)->body.alloc) {
 69        *vpp = (rust_vec_box*)task->boxed.realloc(
 70            *ovpp, size + sizeof(rust_vec));
 71        (*vpp)->body.alloc = size;
 72    }
 73}
 74
 75inline void reserve_vec_exact(rust_task* task, rust_vec_box** vpp,
 76                              size_t size) {
 77    if (size > (*vpp)->body.alloc) {
 78        *vpp = (rust_vec_box*)task->kernel
 79            ->realloc(*vpp, size + sizeof(rust_vec_box));
 80        (*vpp)->body.alloc = size;
 81    }
 82}
 83
 84inline void reserve_vec(rust_task* task, rust_vec_box** vpp, size_t size) {
 85    reserve_vec_exact(task, vpp, next_power_of_two(size));
 86}
 87
 88typedef rust_vec_box rust_str;
 89
 90inline rust_str *
 91make_str(rust_kernel* kernel, const char* c, size_t strlen,
 92         const char* name) {
 93    size_t str_fill = strlen + 1;
 94    size_t str_alloc = str_fill;
 95    rust_str *str = (rust_str *)
 96        kernel->malloc(vec_size<char>(str_fill), name);
 97    str->header.td = &str_body_tydesc;
 98    str->body.fill = str_fill;
 99    str->body.alloc = str_alloc;
100    memcpy(&str->body.data, c, strlen);
101    str->body.data[strlen] = '\0';
102    return str;
103}
104
105inline rust_vec_box *
106make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) {
107    rust_vec_box *v = (rust_vec_box *)
108        kernel->malloc(vec_size<rust_vec_box*>(nstrs),
109                       "str vec interior");
110    // FIXME: should have a real td (Issue #2639)
111    v->header.td = NULL;
112    v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs;
113    for (size_t i = 0; i < nstrs; ++i) {
114        rust_str *str = make_str(kernel, strs[i],
115                                 strlen(strs[i]),
116                                 "str");
117        ((rust_str**)&v->body.data)[i] = str;
118    }
119    return v;
120}
121
122inline size_t get_box_size(size_t body_size, size_t body_align) {
123    size_t header_size = sizeof(rust_opaque_box);
124    // FIXME (#2699): This alignment calculation is suspicious. Is it right?
125    size_t total_size = align_to(header_size, body_align) + body_size;
126    return total_size;
127}
128
129// Initialization helpers for ISAAC RNG
130
131inline void isaac_seed(rust_kernel* kernel, uint8_t* dest, size_t size)
132{
133#ifdef __WIN32__
134    HCRYPTPROV hProv;
135    kernel->win32_require
136        (_T("CryptAcquireContext"),
137         CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
138                             CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
139    kernel->win32_require
140        (_T("CryptGenRandom"), CryptGenRandom(hProv, size, (BYTE*) dest));
141    kernel->win32_require
142        (_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0));
143#else
144    int fd = open("/dev/urandom", O_RDONLY);
145    assert(fd > 0);
146    size_t amount = 0;
147    do {
148        ssize_t ret = read(fd, dest+amount, size-amount);
149        assert(ret >= 0);
150        amount += (size_t)ret;
151    } while (amount < size);
152    int ret = close(fd);
153    assert(ret == 0);
154#endif
155}
156
157inline void
158isaac_init(rust_kernel *kernel, randctx *rctx, rust_vec_box* user_seed)
159{
160    memset(rctx, 0, sizeof(randctx));
161
162    char *env_seed = kernel->env->rust_seed;
163    if (user_seed != NULL) {
164        // ignore bytes after the required length
165        size_t seed_len = user_seed->body.fill < sizeof(rctx->randrsl)
166            ? user_seed->body.fill : sizeof(rctx->randrsl);
167        memcpy(&rctx->randrsl, user_seed->body.data, seed_len);
168    } else if (env_seed != NULL) {
169        ub4 seed = (ub4) atoi(env_seed);
170        for (size_t i = 0; i < RANDSIZ; i ++) {
171            memcpy(&rctx->randrsl[i], &seed, sizeof(ub4));
172            seed = (seed + 0x7ed55d16) + (seed << 12);
173        }
174    } else {
175        isaac_seed(kernel, (uint8_t*) &rctx->randrsl, sizeof(rctx->randrsl));
176    }
177
178    randinit(rctx, 1);
179}
180
181//
182// Local Variables:
183// mode: C++
184// fill-column: 78;
185// indent-tabs-mode: nil
186// c-basic-offset: 4
187// buffer-file-coding-system: utf-8-unix
188// End:
189//
190
191#endif