]> sourceware.org Git - newlib-cygwin.git/commitdiff
Cygwin: random: make random(3) functions thread-safe
authorCorinna Vinschen <corinna@vinschen.de>
Mon, 13 Nov 2023 18:41:08 +0000 (19:41 +0100)
committerCorinna Vinschen <corinna@vinschen.de>
Mon, 13 Nov 2023 18:52:37 +0000 (19:52 +0100)
Add locking to the random(3) family of functions to gain
thread-safety per POSIX. Use NetBSD version of the file as
role-model.

Reported-by: Bruno Haible <bruno@clisp.org>
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
winsup/cygwin/random.cc

index 163fc040cef514d6cdfe9728e85a3ed19769a168..b38fdc078189c111a58f41f82c49ad22dcfe6db4 100644 (file)
 
 #define __INSIDE_CYGWIN__
 
+#include "winsup.h"
+
+SRWLOCK NO_COPY rndlock = SRWLOCK_INIT;
+# define __random_lock()       { if (__isthreaded) \
+                                       AcquireSRWLockExclusive (&rndlock); }
+# define __random_unlock()     { if (__isthreaded) \
+                                       ReleaseSRWLockExclusive (&rndlock); }
+
 extern "C" {
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)random.c   8.2 (Berkeley) 5/19/95";
@@ -248,6 +256,8 @@ static inline uint32_t good_rand (int32_t x)
 #endif  /* !USE_WEAK_SEEDING */
 }
 
+static long __random_unlocked();
+
 /*
  * srandom:
  *
@@ -260,8 +270,8 @@ static inline uint32_t good_rand (int32_t x)
  * 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 x)
+static void
+__srandom_unlocked(unsigned x)
 {
        int i, lim;
 
@@ -276,7 +286,15 @@ srandom(unsigned x)
                lim = 10 * rand_deg;
        }
        for (i = 0; i < lim; i++)
-               (void)random();
+               (void)__random_unlocked();
+}
+
+void
+srandom(unsigned x)
+{
+       __random_lock();
+       __srandom_unlocked(x);
+       __random_unlock();
 }
 
 /*
@@ -350,6 +368,7 @@ initstate(unsigned seed,            /* seed for R.N.G. */
        char *ostate = (char *)(&state[-1]);
        uint32_t *int_arg_state = (uint32_t *)arg_state;
 
+       __random_lock();
        if (rand_type == TYPE_0)
                state[-1] = rand_type;
        else
@@ -358,6 +377,7 @@ initstate(unsigned seed,            /* seed for R.N.G. */
                (void)fprintf(stderr,
                    "random: not enough state (%lu bytes); ignored.\n",
                    (unsigned long) n);
+               __random_unlock();
                return(0);
        }
        if (n < BREAK_1) {
@@ -383,11 +403,12 @@ initstate(unsigned seed,          /* seed for R.N.G. */
        }
        state = int_arg_state + 1; /* first location */
        end_ptr = &state[rand_deg];     /* must set end_ptr before srandom */
-       srandom(seed);
+       __srandom_unlocked(seed);
        if (rand_type == TYPE_0)
                int_arg_state[0] = rand_type;
        else
                int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
+       __random_unlock();
        return(ostate);
 }
 
@@ -418,6 +439,7 @@ setstate(char *arg_state /* pointer to state array */)
        uint32_t rear = new_state[0] / MAX_TYPES;
        char *ostate = (char *)(&state[-1]);
 
+       __random_lock();
        if (rand_type == TYPE_0)
                state[-1] = rand_type;
        else
@@ -442,6 +464,7 @@ setstate(char *arg_state /* pointer to state array */)
                fptr = &state[(rear + rand_sep) % rand_deg];
        }
        end_ptr = &state[rand_deg];             /* set end_ptr too */
+       __random_unlock();
        return(ostate);
 }
 
@@ -462,8 +485,8 @@ setstate(char *arg_state /* pointer to state array */)
  *
  * Returns a 31-bit random number.
  */
-long
-random()
+static long
+__random_unlocked()
 {
        uint32_t i;
        uint32_t *f, *r;
@@ -490,4 +513,16 @@ random()
        }
        return((long)i);
 }
+
+long
+random()
+{
+       long r;
+
+       __random_lock();
+       r = __random_unlocked();
+       __random_unlock();
+       return (r);
+}
+
 }
This page took 0.03346 seconds and 5 git commands to generate.