mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8344773: SM cleanup in ForkJoinPool
Reviewed-by: alanb
This commit is contained in:
parent
6da3ecd65d
commit
3e509c8bd1
2 changed files with 49 additions and 131 deletions
|
@ -37,12 +37,6 @@ package java.util.concurrent;
|
|||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.AccessController;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.Permission;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -811,9 +805,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
* initialization. Since it (or any other created pool) need
|
||||
* never be used, we minimize initial construction overhead and
|
||||
* footprint to the setup of about a dozen fields, although with
|
||||
* some System property parsing and security processing that takes
|
||||
* far longer than the actual construction when SecurityManagers
|
||||
* are used or properties are set. The common pool is
|
||||
* some System property parsing properties are set. The common pool is
|
||||
* distinguished by having a null workerNamePrefix (which is an
|
||||
* odd convention, but avoids the need to decode status in factory
|
||||
* classes). It also has PRESET_SIZE config set if parallelism
|
||||
|
@ -839,13 +831,12 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
*
|
||||
* As a more appropriate default in managed environments, unless
|
||||
* overridden by system properties, we use workers of subclass
|
||||
* InnocuousForkJoinWorkerThread when there is a SecurityManager
|
||||
* present. These workers have no permissions set, do not belong
|
||||
* to any user-defined ThreadGroup, and clear all ThreadLocals and
|
||||
* reset the ContextClassLoader before (re)activating to execute
|
||||
* top-level task. The associated mechanics may be JVM-dependent
|
||||
* and must access particular Thread class fields to achieve this
|
||||
* effect.
|
||||
* InnocuousForkJoinWorkerThread for the commonPool. These
|
||||
* workers do not belong to any user-defined ThreadGroup, and
|
||||
* clear all ThreadLocals and reset the ContextClassLoader before
|
||||
* (re)activating to execute top-level tasks. The associated
|
||||
* mechanics may be JVM-dependent and must access particular
|
||||
* Thread class fields to achieve this effect.
|
||||
*
|
||||
* InterruptibleTasks
|
||||
* ====================
|
||||
|
@ -917,9 +908,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
* shorts would suffice. For class WorkQueue, an
|
||||
* embedded @Contended region segregates fields most heavily
|
||||
* updated by owners from those most commonly read by stealers or
|
||||
* other management. For class WorkQueue, an embedded padded
|
||||
* region segregates fields (all declared as "int") most heavily
|
||||
* updated by owners from those most commonly read by stealers or
|
||||
* other management.
|
||||
*
|
||||
* Initial sizing and resizing of WorkQueue arrays is an even more
|
||||
|
@ -929,8 +917,10 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
* direct false-sharing and indirect cases due to GC bookkeeping
|
||||
* (cardmarks etc), and reduce the number of resizes, which are
|
||||
* not especially fast because they require atomic transfers.
|
||||
* Currently, arrays are initialized to be just large enough to
|
||||
* avoid resizing in most tree-structured tasks. (Maintenance note:
|
||||
* Currently, arrays for workers are initialized to be just large
|
||||
* enough to avoid resizing in most tree-structured tasks, but
|
||||
* larger for external queues where both false-sharing problems
|
||||
* and the need for resizing are more common. (Maintenance note:
|
||||
* any changes in fields, queues, or their uses, or JVM layout
|
||||
* policies, must be accompanied by re-evaluation of these
|
||||
* placement and sizing decisions.)
|
||||
|
@ -1019,6 +1009,12 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
*/
|
||||
static final int INITIAL_QUEUE_CAPACITY = 1 << 6;
|
||||
|
||||
/**
|
||||
* Initial capacity of work-stealing queue array for external queues.
|
||||
* Must be a power of two, at least 2. See above.
|
||||
*/
|
||||
static final int INITIAL_EXTERNAL_QUEUE_CAPACITY = 1 << 9;
|
||||
|
||||
// conversions among short, int, long
|
||||
static final int SMASK = 0xffff; // (unsigned) short bits
|
||||
static final long LMASK = 0xffffffffL; // lower 32 bits of long
|
||||
|
@ -1097,21 +1093,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
return ((long)index << ASHIFT) + ABASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a security manager, makes sure caller has
|
||||
* permission to modify threads.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
private static void checkPermission() {
|
||||
SecurityManager security; RuntimePermission perm;
|
||||
if ((security = System.getSecurityManager()) != null) {
|
||||
if ((perm = modifyThreadPermission) == null)
|
||||
modifyThreadPermission = perm = // races OK
|
||||
new RuntimePermission("modifyThread");
|
||||
security.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
|
||||
// Nested classes
|
||||
|
||||
/**
|
||||
|
@ -1147,64 +1128,9 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
static final class DefaultForkJoinWorkerThreadFactory
|
||||
implements ForkJoinWorkerThreadFactory {
|
||||
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
|
||||
boolean isCommon = (pool.workerNamePrefix == null);
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null && isCommon)
|
||||
return newCommonWithACC(pool);
|
||||
else
|
||||
return newRegularWithACC(pool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and use static AccessControlContexts only if there
|
||||
* is a SecurityManager. (These can be removed if/when
|
||||
* SecurityManagers are removed from platform.) The ACCs are
|
||||
* immutable and equivalent even when racily initialized, so
|
||||
* they don't require locking, although with the chance of
|
||||
* needlessly duplicate construction.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
static volatile AccessControlContext regularACC, commonACC;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
static ForkJoinWorkerThread newRegularWithACC(ForkJoinPool pool) {
|
||||
AccessControlContext acc = regularACC;
|
||||
if (acc == null) {
|
||||
Permissions ps = new Permissions();
|
||||
ps.add(new RuntimePermission("getClassLoader"));
|
||||
ps.add(new RuntimePermission("setContextClassLoader"));
|
||||
regularACC = acc =
|
||||
new AccessControlContext(new ProtectionDomain[] {
|
||||
new ProtectionDomain(null, ps) });
|
||||
}
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<>() {
|
||||
public ForkJoinWorkerThread run() {
|
||||
return new ForkJoinWorkerThread(null, pool, true, false);
|
||||
}}, acc);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
static ForkJoinWorkerThread newCommonWithACC(ForkJoinPool pool) {
|
||||
AccessControlContext acc = commonACC;
|
||||
if (acc == null) {
|
||||
Permissions ps = new Permissions();
|
||||
ps.add(new RuntimePermission("getClassLoader"));
|
||||
ps.add(new RuntimePermission("setContextClassLoader"));
|
||||
ps.add(new RuntimePermission("modifyThread"));
|
||||
ps.add(new RuntimePermission("enableContextClassLoaderOverride"));
|
||||
ps.add(new RuntimePermission("modifyThreadGroup"));
|
||||
commonACC = acc =
|
||||
new AccessControlContext(new ProtectionDomain[] {
|
||||
new ProtectionDomain(null, ps) });
|
||||
}
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<>() {
|
||||
public ForkJoinWorkerThread run() {
|
||||
return new ForkJoinWorkerThread.
|
||||
InnocuousForkJoinWorkerThread(pool);
|
||||
}}, acc);
|
||||
return ((pool.workerNamePrefix == null) ? // is commonPool
|
||||
new ForkJoinWorkerThread.InnocuousForkJoinWorkerThread(pool) :
|
||||
new ForkJoinWorkerThread(null, pool, true, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1264,7 +1190,9 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
*/
|
||||
WorkQueue(ForkJoinWorkerThread owner, int id, int cfg,
|
||||
boolean clearThreadLocals) {
|
||||
array = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
|
||||
array = new ForkJoinTask<?>[owner == null ?
|
||||
INITIAL_EXTERNAL_QUEUE_CAPACITY :
|
||||
INITIAL_QUEUE_CAPACITY];
|
||||
this.owner = owner;
|
||||
this.config = (clearThreadLocals) ? cfg | CLEAR_TLS : cfg;
|
||||
}
|
||||
|
@ -3024,7 +2952,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
Predicate<? super ForkJoinPool> saturate,
|
||||
long keepAliveTime,
|
||||
TimeUnit unit) {
|
||||
checkPermission();
|
||||
int p = parallelism;
|
||||
if (p <= 0 || p > MAX_CAP || p > maximumPoolSize || keepAliveTime <= 0L)
|
||||
throw new IllegalArgumentException();
|
||||
|
@ -3312,7 +3239,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
throw new IllegalArgumentException();
|
||||
if ((config & PRESET_SIZE) != 0)
|
||||
throw new UnsupportedOperationException("Cannot override System property");
|
||||
checkPermission();
|
||||
return getAndSetParallelism(size);
|
||||
}
|
||||
|
||||
|
@ -3710,7 +3636,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
* may not be rejected.
|
||||
*/
|
||||
public void shutdown() {
|
||||
checkPermission();
|
||||
if (workerNamePrefix != null) // not common pool
|
||||
tryTerminate(false, true);
|
||||
}
|
||||
|
@ -3730,7 +3655,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
* @return an empty list
|
||||
*/
|
||||
public List<Runnable> shutdownNow() {
|
||||
checkPermission();
|
||||
if (workerNamePrefix != null) // not common pool
|
||||
tryTerminate(true, true);
|
||||
return Collections.emptyList();
|
||||
|
@ -3837,7 +3761,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
@Override
|
||||
public void close() {
|
||||
if (workerNamePrefix != null) {
|
||||
checkPermission();
|
||||
CountDownLatch done = null;
|
||||
boolean interrupted = false;
|
||||
while ((tryTerminate(interrupted, true) & TERMINATED) == 0) {
|
||||
|
@ -4075,11 +3998,6 @@ public class ForkJoinPool extends AbstractExecutorService {
|
|||
});
|
||||
defaultForkJoinWorkerThreadFactory =
|
||||
new DefaultForkJoinWorkerThreadFactory();
|
||||
@SuppressWarnings("removal")
|
||||
ForkJoinPool p = common = (System.getSecurityManager() == null) ?
|
||||
new ForkJoinPool((byte)0) :
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public ForkJoinPool run() {
|
||||
return new ForkJoinPool((byte)0); }});
|
||||
common = new ForkJoinPool((byte)0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue