From eb6ab98ebcbf837b1ed052b46b1c022a3d79e34e Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Tue, 16 Feb 2016 09:52:49 -0800 Subject: [PATCH] 8145485: Miscellaneous changes imported from jsr166 CVS 2016-02 Reviewed-by: martin, psandoz, chegar --- .../classes/java/util/SplittableRandom.java | 11 +++-- .../java/util/concurrent/Exchanger.java | 7 ++-- .../java/util/concurrent/ForkJoinPool.java | 5 ++- .../java/util/concurrent/ForkJoinTask.java | 40 ++++++++----------- .../util/concurrent/ThreadLocalRandom.java | 11 +++-- .../util/concurrent/atomic/Striped64.java | 14 +++---- .../ConcurrentQueues/RemovePollRace.java | 12 ++++-- .../ExecutorCompletionServiceLoops.java | 4 +- 8 files changed, 50 insertions(+), 54 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java index 2e08a4ddb87..cf71c91e8da 100644 --- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java +++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java @@ -225,14 +225,13 @@ public final class SplittableRandom { private static final AtomicLong defaultGen = new AtomicLong(initialSeed()); private static long initialSeed() { - String pp = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "java.util.secureRandomSeed")); - if (pp != null && pp.equalsIgnoreCase("true")) { + java.security.PrivilegedAction action = + () -> Boolean.getBoolean("java.util.secureRandomSeed"); + if (java.security.AccessController.doPrivileged(action)) { byte[] seedBytes = java.security.SecureRandom.getSeed(8); - long s = (long)(seedBytes[0]) & 0xffL; + long s = (long)seedBytes[0] & 0xffL; for (int i = 1; i < 8; ++i) - s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); + s = (s << 8) | ((long)seedBytes[i] & 0xffL); return s; } return (mix64(System.currentTimeMillis()) ^ diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java index b8260d7102b..3f5ce5e371d 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java @@ -155,8 +155,8 @@ public class Exchanger { * a value that is enough for common platforms. Additionally, * extra care elsewhere is taken to avoid other false/unintended * sharing and to enhance locality, including adding padding (via - * jdk.internal.vm.annotation.Contended) to Nodes, embedding "bound" as an Exchanger - * field, and reworking some park/unpark mechanics compared to + * @Contended) to Nodes, embedding "bound" as an Exchanger field, + * and reworking some park/unpark mechanics compared to * LockSupport versions. * * The arena starts out with only one used slot. We expand the @@ -304,8 +304,7 @@ public class Exchanger { /** * Nodes hold partially exchanged data, plus other per-thread - * bookkeeping. Padded via @jdk.internal.vm.annotation.Contended to reduce memory - * contention. + * bookkeeping. Padded via @Contended to reduce memory contention. */ @jdk.internal.vm.annotation.Contended static final class Node { int index; // Arena index diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index 3dac70a4310..3a7c0ab4eb8 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -818,8 +818,9 @@ public class ForkJoinPool extends AbstractExecutorService { final ForkJoinPool pool; // the containing pool (may be null) final ForkJoinWorkerThread owner; // owning thread or null if shared volatile Thread parker; // == owner during call to park; else null - volatile ForkJoinTask currentJoin; // task being joined in awaitJoin - @jdk.internal.vm.annotation.Contended("group2") // separate from other fields + volatile ForkJoinTask currentJoin; // task being joined in awaitJoin + + @jdk.internal.vm.annotation.Contended("group2") // segregate volatile ForkJoinTask currentSteal; // nonnull when running some task WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index 888794e8e40..fa14cbf984a 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -541,16 +541,16 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Returns a rethrowable exception for the given task, if - * available. To provide accurate stack traces, if the exception - * was not thrown by the current thread, we try to create a new - * exception of the same type as the one thrown, but with the - * recorded exception as its cause. If there is no such - * constructor, we instead try to use a no-arg constructor, - * followed by initCause, to the same effect. If none of these - * apply, or any fail due to other exceptions, we return the - * recorded exception, which is still correct, although it may - * contain a misleading stack trace. + * Returns a rethrowable exception for this task, if available. + * To provide accurate stack traces, if the exception was not + * thrown by the current thread, we try to create a new exception + * of the same type as the one thrown, but with the recorded + * exception as its cause. If there is no such constructor, we + * instead try to use a no-arg constructor, followed by initCause, + * to the same effect. If none of these apply, or any fail due to + * other exceptions, we return the recorded exception, which is + * still correct, although it may contain a misleading stack + * trace. * * @return the exception, or null if none */ @@ -572,26 +572,20 @@ public abstract class ForkJoinTask implements Future, Serializable { if (e == null || (ex = e.ex) == null) return null; if (e.thrower != Thread.currentThread().getId()) { - Class ec = ex.getClass(); try { Constructor noArgCtor = null; - Constructor[] cs = ec.getConstructors();// public ctors only - for (int i = 0; i < cs.length; ++i) { - Constructor c = cs[i]; + // public ctors only + for (Constructor c : ex.getClass().getConstructors()) { Class[] ps = c.getParameterTypes(); if (ps.length == 0) noArgCtor = c; - else if (ps.length == 1 && ps[0] == Throwable.class) { - Throwable wx = (Throwable)c.newInstance(ex); - return (wx == null) ? ex : wx; - } + else if (ps.length == 1 && ps[0] == Throwable.class) + return (Throwable)c.newInstance(ex); } if (noArgCtor != null) { - Throwable wx = (Throwable)(noArgCtor.newInstance()); - if (wx != null) { - wx.initCause(ex); - return wx; - } + Throwable wx = (Throwable)noArgCtor.newInstance(); + wx.initCause(ex); + return wx; } } catch (Exception ignore) { } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index f4bf5a4fef2..90fb6cf054f 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -134,14 +134,13 @@ public class ThreadLocalRandom extends Random { private static final AtomicLong seeder = new AtomicLong(initialSeed()); private static long initialSeed() { - String pp = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "java.util.secureRandomSeed")); - if (pp != null && pp.equalsIgnoreCase("true")) { + java.security.PrivilegedAction action = + () -> Boolean.getBoolean("java.util.secureRandomSeed"); + if (java.security.AccessController.doPrivileged(action)) { byte[] seedBytes = java.security.SecureRandom.getSeed(8); - long s = (long)(seedBytes[0]) & 0xffL; + long s = (long)seedBytes[0] & 0xffL; for (int i = 1; i < 8; ++i) - s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); + s = (s << 8) | ((long)seedBytes[i] & 0xffL); return s; } return (mix64(System.currentTimeMillis()) ^ diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java index dad7db6bd77..77ee89a614b 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java @@ -55,13 +55,13 @@ abstract class Striped64 extends Number { * accessed directly by subclasses. * * Table entries are of class Cell; a variant of AtomicLong padded - * (via @jdk.internal.vm.annotation.Contended) to reduce cache contention. Padding - * is overkill for most Atomics because they are usually - * irregularly scattered in memory and thus don't interfere much - * with each other. But Atomic objects residing in arrays will - * tend to be placed adjacent to each other, and so will most - * often share cache lines (with a huge negative performance - * impact) without this precaution. + * (via @Contended) to reduce cache contention. Padding is + * overkill for most Atomics because they are usually irregularly + * scattered in memory and thus don't interfere much with each + * other. But Atomic objects residing in arrays will tend to be + * placed adjacent to each other, and so will most often share + * cache lines (with a huge negative performance impact) without + * this precaution. * * In part because Cells are relatively large, we avoid creating * them until they are needed. When there is no contention, all diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java index 4fe26337092..abcae1d398a 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java @@ -121,12 +121,16 @@ public class RemovePollRace { final int SPINS = 5; final AtomicLong removes = new AtomicLong(0); final AtomicLong polls = new AtomicLong(0); - final int adderCount = - Math.max(1, Runtime.getRuntime().availableProcessors() / 4); - final int removerCount = - Math.max(1, Runtime.getRuntime().availableProcessors() / 4); + + // We need at least 3 threads, but we don't want to use too + // many on massively multi-core systems. + final int cpus = Runtime.getRuntime().availableProcessors(); + final int threadsToUse = Math.max(3, Math.min(cpus, 16)); + final int adderCount = threadsToUse / 3; + final int removerCount = adderCount; final int pollerCount = removerCount; final int threadCount = adderCount + removerCount + pollerCount; + final CountDownLatch startingGate = new CountDownLatch(1); final CountDownLatch addersDone = new CountDownLatch(adderCount); final Runnable remover = new Runnable() { diff --git a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java index e5afd0a4dfc..1da7f2335c7 100644 --- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java +++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java @@ -61,13 +61,13 @@ public class ExecutorCompletionServiceLoops { max = Integer.parseInt(args[0]); System.out.println("Warmup..."); - oneTest( base ); + oneTest(base); Thread.sleep(100); print = true; for (int i = 1; i <= max; i += (i+1) >>> 1) { System.out.print("n: " + i * base); - oneTest(i * base ); + oneTest(i * base); Thread.sleep(100); } pool.shutdown();