diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/random32.c | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/lib/random32.c b/lib/random32.c index 9f2f2fb03dfe..27adb753180f 100644 --- a/lib/random32.c +++ b/lib/random32.c | |||
| @@ -2,19 +2,19 @@ | |||
| 2 | This is a maximally equidistributed combined Tausworthe generator | 2 | This is a maximally equidistributed combined Tausworthe generator |
| 3 | based on code from GNU Scientific Library 1.5 (30 Jun 2004) | 3 | based on code from GNU Scientific Library 1.5 (30 Jun 2004) |
| 4 | 4 | ||
| 5 | x_n = (s1_n ^ s2_n ^ s3_n) | 5 | lfsr113 version: |
| 6 | 6 | ||
| 7 | s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19)) | 7 | x_n = (s1_n ^ s2_n ^ s3_n ^ s4_n) |
| 8 | s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25)) | ||
| 9 | s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11)) | ||
| 10 | 8 | ||
| 11 | The period of this generator is about 2^88. | 9 | s1_{n+1} = (((s1_n & 4294967294) << 18) ^ (((s1_n << 6) ^ s1_n) >> 13)) |
| 10 | s2_{n+1} = (((s2_n & 4294967288) << 2) ^ (((s2_n << 2) ^ s2_n) >> 27)) | ||
| 11 | s3_{n+1} = (((s3_n & 4294967280) << 7) ^ (((s3_n << 13) ^ s3_n) >> 21)) | ||
| 12 | s4_{n+1} = (((s4_n & 4294967168) << 13) ^ (((s4_n << 3) ^ s4_n) >> 12)) | ||
| 12 | 13 | ||
| 13 | From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe | 14 | The period of this generator is about 2^113 (see erratum paper). |
| 14 | Generators", Mathematics of Computation, 65, 213 (1996), 203--213. | ||
| 15 | |||
| 16 | This is available on the net from L'Ecuyer's home page, | ||
| 17 | 15 | ||
| 16 | From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe | ||
| 17 | Generators", Mathematics of Computation, 65, 213 (1996), 203--213: | ||
| 18 | http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps | 18 | http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps |
| 19 | ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps | 19 | ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps |
| 20 | 20 | ||
| @@ -29,7 +29,7 @@ | |||
| 29 | that paper.) | 29 | that paper.) |
| 30 | 30 | ||
| 31 | This affects the seeding procedure by imposing the requirement | 31 | This affects the seeding procedure by imposing the requirement |
| 32 | s1 > 1, s2 > 7, s3 > 15. | 32 | s1 > 1, s2 > 7, s3 > 15, s4 > 127. |
| 33 | 33 | ||
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| @@ -52,11 +52,12 @@ u32 prandom_u32_state(struct rnd_state *state) | |||
| 52 | { | 52 | { |
| 53 | #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b) | 53 | #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b) |
| 54 | 54 | ||
| 55 | state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12); | 55 | state->s1 = TAUSWORTHE(state->s1, 6U, 13U, 4294967294U, 18U); |
| 56 | state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4); | 56 | state->s2 = TAUSWORTHE(state->s2, 2U, 27U, 4294967288U, 2U); |
| 57 | state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17); | 57 | state->s3 = TAUSWORTHE(state->s3, 13U, 21U, 4294967280U, 7U); |
| 58 | state->s4 = TAUSWORTHE(state->s4, 3U, 12U, 4294967168U, 13U); | ||
| 58 | 59 | ||
| 59 | return (state->s1 ^ state->s2 ^ state->s3); | 60 | return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4); |
| 60 | } | 61 | } |
| 61 | EXPORT_SYMBOL(prandom_u32_state); | 62 | EXPORT_SYMBOL(prandom_u32_state); |
| 62 | 63 | ||
| @@ -126,6 +127,21 @@ void prandom_bytes(void *buf, int bytes) | |||
| 126 | } | 127 | } |
| 127 | EXPORT_SYMBOL(prandom_bytes); | 128 | EXPORT_SYMBOL(prandom_bytes); |
| 128 | 129 | ||
| 130 | static void prandom_warmup(struct rnd_state *state) | ||
| 131 | { | ||
| 132 | /* Calling RNG ten times to satify recurrence condition */ | ||
| 133 | prandom_u32_state(state); | ||
| 134 | prandom_u32_state(state); | ||
| 135 | prandom_u32_state(state); | ||
| 136 | prandom_u32_state(state); | ||
| 137 | prandom_u32_state(state); | ||
| 138 | prandom_u32_state(state); | ||
| 139 | prandom_u32_state(state); | ||
| 140 | prandom_u32_state(state); | ||
| 141 | prandom_u32_state(state); | ||
| 142 | prandom_u32_state(state); | ||
| 143 | } | ||
| 144 | |||
| 129 | /** | 145 | /** |
| 130 | * prandom_seed - add entropy to pseudo random number generator | 146 | * prandom_seed - add entropy to pseudo random number generator |
| 131 | * @seed: seed value | 147 | * @seed: seed value |
| @@ -141,8 +157,9 @@ void prandom_seed(u32 entropy) | |||
| 141 | */ | 157 | */ |
| 142 | for_each_possible_cpu (i) { | 158 | for_each_possible_cpu (i) { |
| 143 | struct rnd_state *state = &per_cpu(net_rand_state, i); | 159 | struct rnd_state *state = &per_cpu(net_rand_state, i); |
| 144 | state->s1 = __seed(state->s1 ^ entropy, 2); | 160 | |
| 145 | prandom_u32_state(state); | 161 | state->s1 = __seed(state->s1 ^ entropy, 2U); |
| 162 | prandom_warmup(state); | ||
| 146 | } | 163 | } |
| 147 | } | 164 | } |
| 148 | EXPORT_SYMBOL(prandom_seed); | 165 | EXPORT_SYMBOL(prandom_seed); |
| @@ -158,18 +175,13 @@ static int __init prandom_init(void) | |||
| 158 | for_each_possible_cpu(i) { | 175 | for_each_possible_cpu(i) { |
| 159 | struct rnd_state *state = &per_cpu(net_rand_state,i); | 176 | struct rnd_state *state = &per_cpu(net_rand_state,i); |
| 160 | 177 | ||
| 161 | #define LCG(x) ((x) * 69069) /* super-duper LCG */ | 178 | #define LCG(x) ((x) * 69069U) /* super-duper LCG */ |
| 162 | state->s1 = __seed(LCG(i + jiffies), 2); | 179 | state->s1 = __seed(LCG((i + jiffies) ^ random_get_entropy()), 2U); |
| 163 | state->s2 = __seed(LCG(state->s1), 8); | 180 | state->s2 = __seed(LCG(state->s1), 8U); |
| 164 | state->s3 = __seed(LCG(state->s2), 16); | 181 | state->s3 = __seed(LCG(state->s2), 16U); |
| 165 | 182 | state->s4 = __seed(LCG(state->s3), 128U); | |
| 166 | /* "warm it up" */ | 183 | |
| 167 | prandom_u32_state(state); | 184 | prandom_warmup(state); |
| 168 | prandom_u32_state(state); | ||
| 169 | prandom_u32_state(state); | ||
| 170 | prandom_u32_state(state); | ||
| 171 | prandom_u32_state(state); | ||
| 172 | prandom_u32_state(state); | ||
| 173 | } | 185 | } |
| 174 | return 0; | 186 | return 0; |
| 175 | } | 187 | } |
| @@ -215,15 +227,15 @@ static void __prandom_reseed(bool late) | |||
| 215 | 227 | ||
| 216 | for_each_possible_cpu(i) { | 228 | for_each_possible_cpu(i) { |
| 217 | struct rnd_state *state = &per_cpu(net_rand_state,i); | 229 | struct rnd_state *state = &per_cpu(net_rand_state,i); |
| 218 | u32 seeds[3]; | 230 | u32 seeds[4]; |
| 219 | 231 | ||
| 220 | get_random_bytes(&seeds, sizeof(seeds)); | 232 | get_random_bytes(&seeds, sizeof(seeds)); |
| 221 | state->s1 = __seed(seeds[0], 2); | 233 | state->s1 = __seed(seeds[0], 2U); |
| 222 | state->s2 = __seed(seeds[1], 8); | 234 | state->s2 = __seed(seeds[1], 8U); |
| 223 | state->s3 = __seed(seeds[2], 16); | 235 | state->s3 = __seed(seeds[2], 16U); |
| 236 | state->s4 = __seed(seeds[3], 128U); | ||
| 224 | 237 | ||
| 225 | /* mix it in */ | 238 | prandom_warmup(state); |
| 226 | prandom_u32_state(state); | ||
| 227 | } | 239 | } |
| 228 | out: | 240 | out: |
| 229 | spin_unlock_irqrestore(&lock, flags); | 241 | spin_unlock_irqrestore(&lock, flags); |
