diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2013-03-15 19:07:54 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2013-03-15 19:07:54 +0000 |
commit | e6b15f71622f38cf8e48b0be9387727ef85ffec2 (patch) | |
tree | 68b4993dfdbbeb2f986c5e788c2eac0861b534a5 | |
parent | 57851a76602513591fbdd9c7a15cc57b68e226e9 (diff) |
threadsafe random().
reported by ajacoutot and (much earlier, sorry) by Alexey Suslikov
-rw-r--r-- | lib/libc/stdlib/random.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c index 9c5b9d0f3f3..f299d8e2f65 100644 --- a/lib/libc/stdlib/random.c +++ b/lib/libc/stdlib/random.c @@ -1,4 +1,4 @@ -/* $OpenBSD: random.c,v 1.17 2012/06/01 01:01:57 guenther Exp $ */ +/* $OpenBSD: random.c,v 1.18 2013/03/15 19:07:53 tedu Exp $ */ /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. @@ -36,6 +36,8 @@ #include <stdlib.h> #include <unistd.h> +#include "thread_private.h" + /* * random.c: * @@ -174,6 +176,12 @@ static int rand_type = TYPE_3; static int rand_deg = DEG_3; static int rand_sep = SEP_3; +_THREAD_PRIVATE_MUTEX(random); +static long random_l(void); + +#define LOCK() _THREAD_PRIVATE_MUTEX_LOCK(random) +#define UNLOCK() _THREAD_PRIVATE_MUTEX_UNLOCK(random) + /* * srandom: * @@ -186,8 +194,8 @@ static int rand_sep = SEP_3; * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] * for default usage relies on values produced by this routine. */ -void -srandom(unsigned int x) +static void +srandom_l(unsigned int x) { int i; int32_t test; @@ -213,10 +221,18 @@ srandom(unsigned int x) fptr = &state[rand_sep]; rptr = &state[0]; for (i = 0; i < 10 * rand_deg; i++) - (void)random(); + (void)random_l(); } } +void +srandom(unsigned int x) +{ + LOCK(); + srandom_l(x); + UNLOCK(); +} + /* * srandomdev: * @@ -234,6 +250,7 @@ srandomdev(void) int mib[2]; size_t len; + LOCK(); if (rand_type == TYPE_0) len = sizeof(state[0]); else @@ -247,6 +264,7 @@ srandomdev(void) fptr = &state[rand_sep]; rptr = &state[0]; } + UNLOCK(); } /* @@ -273,12 +291,15 @@ initstate(u_int seed, char *arg_state, size_t n) { char *ostate = (char *)(&state[-1]); + LOCK(); if (rand_type == TYPE_0) state[-1] = rand_type; else state[-1] = MAX_TYPES * (rptr - state) + rand_type; - if (n < BREAK_0) + if (n < BREAK_0) { + UNLOCK(); return(NULL); + } if (n < BREAK_1) { rand_type = TYPE_0; rand_deg = DEG_0; @@ -302,11 +323,12 @@ initstate(u_int seed, char *arg_state, size_t n) } state = &(((int32_t *)arg_state)[1]); /* first location */ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ - srandom(seed); + srandom_l(seed); if (rand_type == TYPE_0) state[-1] = rand_type; else state[-1] = MAX_TYPES*(rptr - state) + rand_type; + UNLOCK(); return(ostate); } @@ -333,6 +355,7 @@ setstate(char *arg_state) int32_t rear = new_state[0] / MAX_TYPES; char *ostate = (char *)(&state[-1]); + LOCK(); if (rand_type == TYPE_0) state[-1] = rand_type; else @@ -348,6 +371,7 @@ setstate(char *arg_state) rand_sep = seps[type]; break; default: + UNLOCK(); return(NULL); } state = &new_state[1]; @@ -356,6 +380,7 @@ setstate(char *arg_state) fptr = &state[(rear + rand_sep) % rand_deg]; } end_ptr = &state[rand_deg]; /* set end_ptr too */ + UNLOCK(); return(ostate); } @@ -376,8 +401,8 @@ setstate(char *arg_state) * * Returns a 31-bit random number. */ -long -random(void) +static long +random_l(void) { int32_t i; @@ -394,3 +419,13 @@ random(void) } return((long)i); } + +long +random(void) +{ + long r; + LOCK(); + r = random_l(); + UNLOCK(); + return r; +} |