hotspot/src/share/vm/runtime/os.cpp
changeset 46587 6c97f34cb194
parent 46329 53ccc37bda19
child 46619 a3919f5e8d2b
--- a/hotspot/src/share/vm/runtime/os.cpp	Tue Jun 27 12:27:27 2017 +0000
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jun 28 16:14:20 2017 -0400
@@ -70,7 +70,7 @@
 address           os::_polling_page       = NULL;
 volatile int32_t* os::_mem_serialize_page = NULL;
 uintptr_t         os::_serialize_page_mask = 0;
-long              os::_rand_seed          = 1;
+volatile unsigned int os::_rand_seed      = 1;
 int               os::_processor_count    = 0;
 int               os::_initial_active_processor_count = 0;
 size_t            os::_page_sizes[os::page_sizes_max];
@@ -722,12 +722,12 @@
 #endif
 }
 
-void os::init_random(long initval) {
+void os::init_random(unsigned int initval) {
   _rand_seed = initval;
 }
 
 
-long os::random() {
+static int random_helper(unsigned int rand_seed) {
   /* standard, well-known linear congruential random generator with
    * next_rand = (16807*seed) mod (2**31-1)
    * see
@@ -736,14 +736,14 @@
    * (2) "Two Fast Implementations of the 'Minimal Standard' Random
    *     Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), pp. 87-88.
   */
-  const long a = 16807;
-  const unsigned long m = 2147483647;
-  const long q = m / a;        assert(q == 127773, "weird math");
-  const long r = m % a;        assert(r == 2836, "weird math");
+  const unsigned int a = 16807;
+  const unsigned int m = 2147483647;
+  const int q = m / a;        assert(q == 127773, "weird math");
+  const int r = m % a;        assert(r == 2836, "weird math");
 
   // compute az=2^31p+q
-  unsigned long lo = a * (long)(_rand_seed & 0xFFFF);
-  unsigned long hi = a * (long)((unsigned long)_rand_seed >> 16);
+  unsigned int lo = a * (rand_seed & 0xFFFF);
+  unsigned int hi = a * (rand_seed >> 16);
   lo += (hi & 0x7FFF) << 16;
 
   // if q overflowed, ignore the overflow and increment q
@@ -758,7 +758,18 @@
     lo &= m;
     ++lo;
   }
-  return (_rand_seed = lo);
+  return lo;
+}
+
+int os::random() {
+  // Make updating the random seed thread safe.
+  while (true) {
+    unsigned int seed = _rand_seed;
+    int rand = random_helper(seed);
+    if (Atomic::cmpxchg(rand, &_rand_seed, seed) == seed) {
+      return rand;
+    }
+  }
 }
 
 // The INITIALIZED state is distinguished from the SUSPENDED state because the
@@ -1130,39 +1141,6 @@
 #endif
 }
 
-#ifdef ASSERT
-extern "C" void test_random() {
-  const double m = 2147483647;
-  double mean = 0.0, variance = 0.0, t;
-  long reps = 10000;
-  unsigned long seed = 1;
-
-  tty->print_cr("seed %ld for %ld repeats...", seed, reps);
-  os::init_random(seed);
-  long num;
-  for (int k = 0; k < reps; k++) {
-    num = os::random();
-    double u = (double)num / m;
-    assert(u >= 0.0 && u <= 1.0, "bad random number!");
-
-    // calculate mean and variance of the random sequence
-    mean += u;
-    variance += (u*u);
-  }
-  mean /= reps;
-  variance /= (reps - 1);
-
-  assert(num == 1043618065, "bad seed");
-  tty->print_cr("mean of the 1st 10000 numbers: %f", mean);
-  tty->print_cr("variance of the 1st 10000 numbers: %f", variance);
-  const double eps = 0.0001;
-  t = fabsd(mean - 0.5018);
-  assert(t < eps, "bad mean");
-  t = (variance - 0.3355) < 0.0 ? -(variance - 0.3355) : variance - 0.3355;
-  assert(t < eps, "bad variance");
-}
-#endif
-
 
 // Set up the boot classpath.