This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
Hmm, locking would seriously reduce the class of multithreading scenarious where random can work. If an interrupt tried to use it while it is already active, deadlock would result - similar to malloc. OTOH it should avoid all the issues in having to change our data structures to support random (3) reentrancy - allowing us to use the NetBSD version with just minor changes. And it should be good enough for gcc.c-torture/unsorted/udivmod4.c and its ilk.
I've tried an implementation; tested on x86_64-unknown-linux-gnu X sh-elf with gcc/testsuite/gcc.dg/vshift-{1,3}.c rolled back to revision 181613 .
Below is the diff to the NetBSD original, and the second attachment is the patch for newlib.
I'm not sure about random_r / srandom_r : should I add a dummy struct _reent * parameter so that the implementation could later/optionally be changed to work without locking?
--- libc/stdlib/random.c-ORIG 2012-03-28 00:48:12.280125217 +0200
+++ libc/stdlib/random.c 2012-03-28 02:11:42.344120901 +0200
@@ -39,32 +39,29 @@ __RCSID("$NetBSD: random.c,v 1.2 2005/12
#endif
#endif /* LIBC_SCCS and not lint */
-#include "namespace.h"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
-#include "reentrant.h"
-
-#ifdef __weak_alias
-__weak_alias(initstate,_initstate)
-__weak_alias(random,_random)
-__weak_alias(setstate,_setstate)
-__weak_alias(srandom,_srandom)
-#endif
-
+#include <reent.h>
+#include <sys/lock.h>
+#include <assert.h>
+#define _DIAGASSERT assert
-#ifdef _REENTRANT
-static mutex_t random_mutex = MUTEX_INITIALIZER;
-#endif
+#ifndef __SINGLE_THREAD__
+__LOCK_INIT(static, random_mutex);
+#define mutex_lock(a) __lock_acquire(a)
+#define mutex_unlock(a) __lock_release(a)
#else
-#include <lib/libkern/libkern.h>
#define mutex_lock(a) (void)0
#define mutex_unlock(a) (void)0
#endif
+#endif
-static void srandom_unlocked(unsigned int);
-static long random_unlocked(void);
+#ifdef _REENT_ONLY
+static
+#endif
+long random(void);
#define USE_BETTER_RANDOM
@@ -91,7 +88,7 @@ static long random_unlocked(void);
* state information, which will allow a degree seven polynomial. (Note:
* the zeroeth word of state information also has some other information
* stored in it -- see setstate() for details).
- *
+ *
* The random number generation technique is a linear feedback shift register
* approach, employing trinomials (since there are fewer terms to sum up that
* way). In this approach, the least significant bit of all the numbers in
@@ -262,8 +259,11 @@ static int *end_ptr = &randtbl[DEG_3 + 1
* introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
* for default usage relies on values produced by this routine.
*/
-static void
-srandom_unlocked(unsigned int x)
+#ifdef _REENT_ONLY
+static
+#endif
+void
+srandom(unsigned int x)
{
int i;
@@ -296,16 +296,16 @@ srandom_unlocked(unsigned int x)
fptr = &state[rand_sep];
rptr = &state[0];
for (i = 0; i < 10 * rand_deg; i++)
- (void)random_unlocked();
+ (void)random();
}
}
void
-srandom(unsigned long x)
+srandom_r(unsigned long x)
{
mutex_lock(&random_mutex);
- srandom_unlocked((unsigned int) x);
+ srandom((unsigned int) x);
mutex_unlock(&random_mutex);
}
@@ -317,12 +317,12 @@ srandom(unsigned long x)
* the break values for the different R.N.G.'s, we choose the best (largest)
* one we can and set things up for it. srandom() is then called to
* initialize the state information.
- *
+ *
* Note that on return from srandom(), we set state[-1] to be the type
* multiplexed with the current value of the rear pointer; this is so
* successive calls to initstate() won't lose this information and will be
* able to restart with setstate().
- *
+ *
* Note: the first thing we do is save the current state, if any, just like
* setstate() so that it doesn't matter when initstate is called.
*
@@ -376,7 +376,7 @@ initstate(
}
state = (int *) (int_arg_state + 1); /* first location */
end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
- srandom_unlocked((unsigned int) seed);
+ srandom((unsigned int) seed);
if (rand_type == TYPE_0)
int_arg_state[0] = rand_type;
else
@@ -464,8 +464,11 @@ setstate(char *arg_state) /* pointer to
*
* Returns a 31-bit random number.
*/
-static long
-random_unlocked(void)
+#ifdef _REENT_ONLY
+static
+#endif
+long
+random(void)
{
int i;
int *f, *r;
@@ -495,12 +498,12 @@ random_unlocked(void)
}
long
-random(void)
+random_r(void)
{
long r;
mutex_lock(&random_mutex);
- r = random_unlocked();
+ r = random();
mutex_unlock(&random_mutex);
return (r);
}
Attachment:
random-diff-20120327
Description: Text document
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |