about summary refs log tree commit diff
path: root/stdlib/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/random.c')
-rw-r--r--stdlib/random.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/stdlib/random.c b/stdlib/random.c
index e2b191b696..461b76f29b 100644
--- a/stdlib/random.c
+++ b/stdlib/random.c
@@ -22,6 +22,7 @@
  * Rewritten to use reentrant functions by Ulrich Drepper, 1995.
  */
 
+#include <libc-lock.h>
 #include <limits.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -162,6 +163,11 @@ static struct random_data unsafe_state =
     end_ptr : &randtbl[sizeof (randtbl) / sizeof (randtbl[0])]
 };
 
+/* POSIX.1c requires that there is mutual exclusion for the `rand' and
+   `srand' functions to prevent concurrent calls from modifying common
+   data.  */
+__libc_lock_define_initialized (static, lock)
+
 /* Initialize the random number generator based on the given seed.  If the
    type is the trivial no-state-information type, just remember the seed.
    Otherwise, initializes state[] based on the given "seed" via a linear
@@ -174,7 +180,9 @@ void
 __srandom (x)
      unsigned int x;
 {
+  __libc_lock_lock (lock)
   (void) __srandom_r (x, &unsafe_state);
+  __libc_lock_unlock (lock)
 }
 
 weak_alias (__srandom, srandom)
@@ -197,10 +205,16 @@ __initstate (seed, arg_state, n)
      void *arg_state;
      size_t n;
 {
-  void *ostate = (void *) &unsafe_state.state[-1];
+  void *ostate;
+
+  __libc_lock_lock (lock)
+
+  ostate = (void *) &unsafe_state.state[-1];
 
   __initstate_r (seed, arg_state, n, &unsafe_state);
 
+  __libc_lock_unlock (lock)
+
   return ostate;
 }
 
@@ -218,10 +232,16 @@ void *
 __setstate (arg_state)
      void *arg_state;
 {
-  void *ostate = (void *) &unsafe_state.state[-1];
+  void *ostate;
+
+  __libc_lock_lock (lock)
+
+  ostate = (void *) &unsafe_state.state[-1];
 
   if (__setstate_r (arg_state, &unsafe_state) < 0)
-    return NULL;
+    ostate = NULL;
+
+  __libc_lock_unlock (lock)
 
   return ostate;
 }
@@ -244,8 +264,12 @@ __random ()
 {
   int32_t retval;
 
+  __libc_lock_lock (lock)
+
   (void) __random_r (&unsafe_state, &retval);
 
+  __libc_lock_unlock (lock)
+
   return retval;
 }