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