summaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorjb <jb@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-19 14:12:32 +0000
committerjb <jb@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-19 14:12:32 +0000
commitee0e163a21bb70f9fee44b1ab50bd7d6e81275bc (patch)
tree3dd25be020bc1f538120f175d6ec7627ccda7699 /libgfortran
parentfdabea44ff9c943fa0a0e77f8816043c74afe105 (diff)
Always initialize PRNG using random data from the OS.
libgfortran: 2016-08-16 Janne Blomqvist <jb@gcc.gnu.org> * intrinsics/random.c (master_init): New variable. (init_rand_state): Move below getosrandom (), maybe initialize master_state. (random_seed_i4): If called with no arguments, set master_init to false, and reinitialize. If called with PUT=, set master_init to true. (random_seed_i8): Likewise. testsuite: 2016-08-16 Janne Blomqvist <jb@gcc.gnu.org> * gfortran.dg/random_4.f90: Initialize seed before using, handle the last special seed value. * gfortran.dg/random_7.f90: Use size for last array member instead of hardcoded value. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239611 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog10
-rw-r--r--libgfortran/intrinsics/random.c57
2 files changed, 42 insertions, 25 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 0f9d629b4606..6fd12228645c 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,13 @@
+2016-08-16 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * intrinsics/random.c (master_init): New variable.
+ (init_rand_state): Move below getosrandom (), maybe initialize
+ master_state.
+ (random_seed_i4): If called with no arguments, set master_init to
+ false, and reinitialize. If called with PUT=, set master_init to
+ true.
+ (random_seed_i8): Likewise.
+
2016-08-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* intrinsics/random.c: Include <stdlib.h>.
diff --git a/libgfortran/intrinsics/random.c b/libgfortran/intrinsics/random.c
index 3b9138938177..35c76113b1a5 100644
--- a/libgfortran/intrinsics/random.c
+++ b/libgfortran/intrinsics/random.c
@@ -193,9 +193,10 @@ typedef struct
xorshift1024star_state;
-/* How many times we have jumped. This and master_state are the only
- variables protected by random_lock. */
-static unsigned njumps;
+/* master_init, njumps, and master_state are the only variables
+ protected by random_lock. */
+static bool master_init;
+static unsigned njumps; /* How many times we have jumped. */
static uint64_t master_state[] = {
0xad63fa1ed3b55f36ULL, 0xd94473e78978b497ULL, 0xbc60592a98172477ULL,
0xa3de7c6e81265301ULL, 0x586640c5e785af27ULL, 0x7a2a3f63b67ce5eaULL,
@@ -272,24 +273,6 @@ jump (xorshift1024star_state* rs)
}
-/* Initialize the random number generator for the current thread,
- using the master state and the number of times we must jump. */
-
-static void
-init_rand_state (xorshift1024star_state* rs, const bool locked)
-{
- if (!locked)
- __gthread_mutex_lock (&random_lock);
- memcpy (&rs->s, master_state, sizeof (master_state));
- unsigned n = njumps++;
- if (!locked)
- __gthread_mutex_unlock (&random_lock);
- for (unsigned i = 0; i < n; i++)
- jump (rs);
- rs->init = true;
-}
-
-
/* Super-simple LCG generator used in getosrandom () if /dev/urandom
doesn't exist. */
@@ -359,6 +342,30 @@ getosrandom (void *buf, size_t buflen)
}
+/* Initialize the random number generator for the current thread,
+ using the master state and the number of times we must jump. */
+
+static void
+init_rand_state (xorshift1024star_state* rs, const bool locked)
+{
+ if (!locked)
+ __gthread_mutex_lock (&random_lock);
+ if (!master_init)
+ {
+ getosrandom (master_state, sizeof (master_state));
+ njumps = 0;
+ master_init = true;
+ }
+ memcpy (&rs->s, master_state, sizeof (master_state));
+ unsigned n = njumps++;
+ if (!locked)
+ __gthread_mutex_unlock (&random_lock);
+ for (unsigned i = 0; i < n; i++)
+ jump (rs);
+ rs->init = true;
+}
+
+
/* This function produces a REAL(4) value from the uniform distribution
with range [0,1). */
@@ -791,8 +798,7 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
a processor-dependent value to the seed." */
if (size == NULL && put == NULL && get == NULL)
{
- getosrandom (master_state, sizeof (master_state));
- njumps = 0;
+ master_init = false;
init_rand_state (rs, true);
}
@@ -816,6 +822,7 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
provide seeds with quality only in the lower or upper part. */
scramble_seed ((unsigned char *) master_state, seed, sizeof seed);
njumps = 0;
+ master_init = true;
init_rand_state (rs, true);
rs->p = put->base_addr[SZ * GFC_DESCRIPTOR_STRIDE(put, 0)] & 15;
@@ -873,8 +880,7 @@ random_seed_i8 (GFC_INTEGER_8 *size, gfc_array_i8 *put, gfc_array_i8 *get)
a processor-dependent value to the seed." */
if (size == NULL && put == NULL && get == NULL)
{
- getosrandom (master_state, sizeof (master_state));
- njumps = 0;
+ master_init = false;
init_rand_state (rs, true);
}
@@ -894,6 +900,7 @@ random_seed_i8 (GFC_INTEGER_8 *size, gfc_array_i8 *put, gfc_array_i8 *get)
sizeof (GFC_UINTEGER_8));
njumps = 0;
+ master_init = true;
init_rand_state (rs, true);
rs->p = put->base_addr[SZ * GFC_DESCRIPTOR_STRIDE(put, 0)] & 15;
}