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 /src/lib/libc/stdlib/random.c | |
| 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
Diffstat (limited to 'src/lib/libc/stdlib/random.c')
| -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 | } | ||
