1 | /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: |
3 | #ident "$Id$" |
4 | /*====== |
5 | This file is part of PerconaFT. |
6 | |
7 | |
8 | Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. |
9 | |
10 | PerconaFT is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU General Public License, version 2, |
12 | as published by the Free Software Foundation. |
13 | |
14 | PerconaFT is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | GNU General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
21 | |
22 | ---------------------------------------- |
23 | |
24 | PerconaFT is free software: you can redistribute it and/or modify |
25 | it under the terms of the GNU Affero General Public License, version 3, |
26 | as published by the Free Software Foundation. |
27 | |
28 | PerconaFT is distributed in the hope that it will be useful, |
29 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 | GNU Affero General Public License for more details. |
32 | |
33 | You should have received a copy of the GNU Affero General Public License |
34 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
35 | ======= */ |
36 | |
37 | #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." |
38 | |
39 | #pragma once |
40 | |
41 | #include <portability/toku_config.h> |
42 | #include <toku_portability.h> |
43 | #include <toku_assert.h> |
44 | #include <stdlib.h> |
45 | #include <stdint.h> |
46 | #include <limits.h> |
47 | |
48 | #if defined(HAVE_RANDOM_R) |
49 | // Definition of randu62 and randu64 assume myrandom_r generates 31 low-order bits |
50 | static_assert(RAND_MAX == INT32_MAX, "Unexpected RAND_MAX" ); |
51 | static inline int |
52 | myinitstate_r(unsigned int seed, char *statebuf, size_t statelen, struct random_data *buf) |
53 | { |
54 | return initstate_r(seed, statebuf, statelen, buf); |
55 | } |
56 | static inline int32_t |
57 | myrandom_r(struct random_data *buf) |
58 | { |
59 | int32_t x; |
60 | int r = random_r(buf, &x); |
61 | lazy_assert_zero(r); |
62 | return x; |
63 | } |
64 | #elif defined(HAVE_NRAND48) |
65 | struct random_data { |
66 | unsigned short xsubi[3]; |
67 | }; |
68 | static inline int |
69 | myinitstate_r(unsigned int seed, char *UU(statebuf), size_t UU(statelen), struct random_data *buf) |
70 | { |
71 | buf->xsubi[0] = (seed & 0xffff0000) >> 16; |
72 | buf->xsubi[0] = (seed & 0x0000ffff); |
73 | buf->xsubi[2] = (seed & 0x00ffff00) >> 8; |
74 | return 0; |
75 | } |
76 | static inline int32_t |
77 | myrandom_r(struct random_data *buf) |
78 | { |
79 | int32_t x = nrand48(buf->xsubi); |
80 | return x; |
81 | } |
82 | #else |
83 | # error "no suitable reentrant random function available (checked random_r and nrand48)" |
84 | #endif |
85 | |
86 | static inline uint64_t |
87 | randu62(struct random_data *buf) |
88 | { |
89 | uint64_t a = myrandom_r(buf); |
90 | uint64_t b = myrandom_r(buf); |
91 | return (a | (b << 31)); |
92 | } |
93 | |
94 | static inline uint64_t |
95 | randu64(struct random_data *buf) |
96 | { |
97 | uint64_t r62 = randu62(buf); |
98 | uint64_t c = myrandom_r(buf); |
99 | return (r62 | ((c & 0x3) << 62)); |
100 | } |
101 | |
102 | static inline uint32_t |
103 | rand_choices(struct random_data *buf, uint32_t choices) { |
104 | invariant(choices >= 2); |
105 | invariant(choices < INT32_MAX); |
106 | uint32_t bits = 2; |
107 | while (bits < choices) { |
108 | bits *= 2; |
109 | } |
110 | --bits; |
111 | |
112 | uint32_t result; |
113 | do { |
114 | result = myrandom_r(buf) & bits; |
115 | } while (result >= choices); |
116 | |
117 | return result; |
118 | } |
119 | |