diff options
author | tedu <> | 2013-03-15 19:07:53 +0000 |
---|---|---|
committer | tedu <> | 2013-03-15 19:07:53 +0000 |
commit | 29262687e14b26418671088467d4b032efc4eba5 (patch) | |
tree | 2e2209a6c81eba8ed9286252a842e20a0b9f3d51 | |
parent | 75b6cf9109045444be3a959b9090dcf695a2e662 (diff) | |
download | openbsd-29262687e14b26418671088467d4b032efc4eba5.tar.gz openbsd-29262687e14b26418671088467d4b032efc4eba5.tar.bz2 openbsd-29262687e14b26418671088467d4b032efc4eba5.zip |
threadsafe random().
reported by ajacoutot and (much earlier, sorry) by Alexey Suslikov
-rw-r--r-- | src/lib/libc/stdlib/random.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c index 9c5b9d0f3f..f299d8e2f6 100644 --- a/src/lib/libc/stdlib/random.c +++ b/src/lib/libc/stdlib/random.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: random.c,v 1.17 2012/06/01 01:01:57 guenther Exp $ */ | 1 | /* $OpenBSD: random.c,v 1.18 2013/03/15 19:07:53 tedu Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1983 Regents of the University of California. | 3 | * Copyright (c) 1983 Regents of the University of California. |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -36,6 +36,8 @@ | |||
36 | #include <stdlib.h> | 36 | #include <stdlib.h> |
37 | #include <unistd.h> | 37 | #include <unistd.h> |
38 | 38 | ||
39 | #include "thread_private.h" | ||
40 | |||
39 | /* | 41 | /* |
40 | * random.c: | 42 | * random.c: |
41 | * | 43 | * |
@@ -174,6 +176,12 @@ static int rand_type = TYPE_3; | |||
174 | static int rand_deg = DEG_3; | 176 | static int rand_deg = DEG_3; |
175 | static int rand_sep = SEP_3; | 177 | static int rand_sep = SEP_3; |
176 | 178 | ||
179 | _THREAD_PRIVATE_MUTEX(random); | ||
180 | static long random_l(void); | ||
181 | |||
182 | #define LOCK() _THREAD_PRIVATE_MUTEX_LOCK(random) | ||
183 | #define UNLOCK() _THREAD_PRIVATE_MUTEX_UNLOCK(random) | ||
184 | |||
177 | /* | 185 | /* |
178 | * srandom: | 186 | * srandom: |
179 | * | 187 | * |
@@ -186,8 +194,8 @@ static int rand_sep = SEP_3; | |||
186 | * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] | 194 | * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] |
187 | * for default usage relies on values produced by this routine. | 195 | * for default usage relies on values produced by this routine. |
188 | */ | 196 | */ |
189 | void | 197 | static void |
190 | srandom(unsigned int x) | 198 | srandom_l(unsigned int x) |
191 | { | 199 | { |
192 | int i; | 200 | int i; |
193 | int32_t test; | 201 | int32_t test; |
@@ -213,10 +221,18 @@ srandom(unsigned int x) | |||
213 | fptr = &state[rand_sep]; | 221 | fptr = &state[rand_sep]; |
214 | rptr = &state[0]; | 222 | rptr = &state[0]; |
215 | for (i = 0; i < 10 * rand_deg; i++) | 223 | for (i = 0; i < 10 * rand_deg; i++) |
216 | (void)random(); | 224 | (void)random_l(); |
217 | } | 225 | } |
218 | } | 226 | } |
219 | 227 | ||
228 | void | ||
229 | srandom(unsigned int x) | ||
230 | { | ||
231 | LOCK(); | ||
232 | srandom_l(x); | ||
233 | UNLOCK(); | ||
234 | } | ||
235 | |||
220 | /* | 236 | /* |
221 | * srandomdev: | 237 | * srandomdev: |
222 | * | 238 | * |
@@ -234,6 +250,7 @@ srandomdev(void) | |||
234 | int mib[2]; | 250 | int mib[2]; |
235 | size_t len; | 251 | size_t len; |
236 | 252 | ||
253 | LOCK(); | ||
237 | if (rand_type == TYPE_0) | 254 | if (rand_type == TYPE_0) |
238 | len = sizeof(state[0]); | 255 | len = sizeof(state[0]); |
239 | else | 256 | else |
@@ -247,6 +264,7 @@ srandomdev(void) | |||
247 | fptr = &state[rand_sep]; | 264 | fptr = &state[rand_sep]; |
248 | rptr = &state[0]; | 265 | rptr = &state[0]; |
249 | } | 266 | } |
267 | UNLOCK(); | ||
250 | } | 268 | } |
251 | 269 | ||
252 | /* | 270 | /* |
@@ -273,12 +291,15 @@ initstate(u_int seed, char *arg_state, size_t n) | |||
273 | { | 291 | { |
274 | char *ostate = (char *)(&state[-1]); | 292 | char *ostate = (char *)(&state[-1]); |
275 | 293 | ||
294 | LOCK(); | ||
276 | if (rand_type == TYPE_0) | 295 | if (rand_type == TYPE_0) |
277 | state[-1] = rand_type; | 296 | state[-1] = rand_type; |
278 | else | 297 | else |
279 | state[-1] = MAX_TYPES * (rptr - state) + rand_type; | 298 | state[-1] = MAX_TYPES * (rptr - state) + rand_type; |
280 | if (n < BREAK_0) | 299 | if (n < BREAK_0) { |
300 | UNLOCK(); | ||
281 | return(NULL); | 301 | return(NULL); |
302 | } | ||
282 | if (n < BREAK_1) { | 303 | if (n < BREAK_1) { |
283 | rand_type = TYPE_0; | 304 | rand_type = TYPE_0; |
284 | rand_deg = DEG_0; | 305 | rand_deg = DEG_0; |
@@ -302,11 +323,12 @@ initstate(u_int seed, char *arg_state, size_t n) | |||
302 | } | 323 | } |
303 | state = &(((int32_t *)arg_state)[1]); /* first location */ | 324 | state = &(((int32_t *)arg_state)[1]); /* first location */ |
304 | end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ | 325 | end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ |
305 | srandom(seed); | 326 | srandom_l(seed); |
306 | if (rand_type == TYPE_0) | 327 | if (rand_type == TYPE_0) |
307 | state[-1] = rand_type; | 328 | state[-1] = rand_type; |
308 | else | 329 | else |
309 | state[-1] = MAX_TYPES*(rptr - state) + rand_type; | 330 | state[-1] = MAX_TYPES*(rptr - state) + rand_type; |
331 | UNLOCK(); | ||
310 | return(ostate); | 332 | return(ostate); |
311 | } | 333 | } |
312 | 334 | ||
@@ -333,6 +355,7 @@ setstate(char *arg_state) | |||
333 | int32_t rear = new_state[0] / MAX_TYPES; | 355 | int32_t rear = new_state[0] / MAX_TYPES; |
334 | char *ostate = (char *)(&state[-1]); | 356 | char *ostate = (char *)(&state[-1]); |
335 | 357 | ||
358 | LOCK(); | ||
336 | if (rand_type == TYPE_0) | 359 | if (rand_type == TYPE_0) |
337 | state[-1] = rand_type; | 360 | state[-1] = rand_type; |
338 | else | 361 | else |
@@ -348,6 +371,7 @@ setstate(char *arg_state) | |||
348 | rand_sep = seps[type]; | 371 | rand_sep = seps[type]; |
349 | break; | 372 | break; |
350 | default: | 373 | default: |
374 | UNLOCK(); | ||
351 | return(NULL); | 375 | return(NULL); |
352 | } | 376 | } |
353 | state = &new_state[1]; | 377 | state = &new_state[1]; |
@@ -356,6 +380,7 @@ setstate(char *arg_state) | |||
356 | fptr = &state[(rear + rand_sep) % rand_deg]; | 380 | fptr = &state[(rear + rand_sep) % rand_deg]; |
357 | } | 381 | } |
358 | end_ptr = &state[rand_deg]; /* set end_ptr too */ | 382 | end_ptr = &state[rand_deg]; /* set end_ptr too */ |
383 | UNLOCK(); | ||
359 | return(ostate); | 384 | return(ostate); |
360 | } | 385 | } |
361 | 386 | ||
@@ -376,8 +401,8 @@ setstate(char *arg_state) | |||
376 | * | 401 | * |
377 | * Returns a 31-bit random number. | 402 | * Returns a 31-bit random number. |
378 | */ | 403 | */ |
379 | long | 404 | static long |
380 | random(void) | 405 | random_l(void) |
381 | { | 406 | { |
382 | int32_t i; | 407 | int32_t i; |
383 | 408 | ||
@@ -394,3 +419,13 @@ random(void) | |||
394 | } | 419 | } |
395 | return((long)i); | 420 | return((long)i); |
396 | } | 421 | } |
422 | |||
423 | long | ||
424 | random(void) | ||
425 | { | ||
426 | long r; | ||
427 | LOCK(); | ||
428 | r = random_l(); | ||
429 | UNLOCK(); | ||
430 | return r; | ||
431 | } | ||