< prev index next >

src/java.base/share/classes/jdk/internal/misc/CarrierThread.java

Print this page

  1 /*
  2  * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.misc;
 27 
 28 import java.security.AccessControlContext;
 29 import java.security.AccessController;
 30 import java.security.PrivilegedAction;
 31 import java.security.ProtectionDomain;
 32 import java.util.concurrent.ForkJoinPool;
 33 import java.util.concurrent.ForkJoinWorkerThread;
 34 import jdk.internal.access.JavaLangAccess;

 35 import jdk.internal.access.SharedSecrets;
 36 
 37 /**
 38  * A ForkJoinWorkerThread that can be used as a carrier thread.
 39  */
 40 public class CarrierThread extends ForkJoinWorkerThread {
 41     private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
 42     private static final Unsafe U = Unsafe.getUnsafe();
 43 
 44     private static final ThreadGroup CARRIER_THREADGROUP = carrierThreadGroup();
 45     @SuppressWarnings("removal")
 46     private static final AccessControlContext INNOCUOUS_ACC = innocuousACC();
 47 
 48     private static final long CONTEXTCLASSLOADER;
 49     private static final long INHERITABLETHREADLOCALS;
 50     private static final long INHERITEDACCESSCONTROLCONTEXT;
 51 
 52     private boolean blocking;    // true if in blocking op





 53 
 54     @SuppressWarnings("this-escape")
 55     public CarrierThread(ForkJoinPool pool) {
 56         super(CARRIER_THREADGROUP, pool, true);
 57         U.putReference(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
 58         U.putReference(this, INHERITABLETHREADLOCALS, null);
 59         U.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);
 60     }
 61 
 62     /**
 63      * For use by {@link Blocker} to test if the thread is in a blocking operation.
 64      */
 65     boolean inBlocking() {
 66         //assert JLA.currentCarrierThread() == this;
 67         return blocking;
 68     }
 69 
 70     /**
 71      * For use by {@link Blocker} to mark the start of a blocking operation.
 72      */
 73     void beginBlocking() {
 74         //assert JLA.currentCarrierThread() == this && !blocking;
 75         blocking = true;













 76     }
 77 
 78     /**
 79      * For use by {@link Blocker} to mark the end of a blocking operation.
 80      */
 81     void endBlocking() {
 82         //assert JLA.currentCarrierThread() == this && blocking;
 83         blocking = false;



 84     }
 85 
 86     @Override
 87     public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) { }
 88 
 89     @Override
 90     public void setContextClassLoader(ClassLoader cl) {
 91         throw new SecurityException("setContextClassLoader");
 92     }
 93 
 94     /**
 95      * The thread group for the carrier threads.
 96      */
 97     @SuppressWarnings("removal")
 98     private static final ThreadGroup carrierThreadGroup() {
 99         return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
100             public ThreadGroup run() {
101                 ThreadGroup group = JLA.currentCarrierThread().getThreadGroup();
102                 for (ThreadGroup p; (p = group.getParent()) != null; )
103                     group = p;
104                 var carrierThreadsGroup = new ThreadGroup(group, "CarrierThreads");
105                 return carrierThreadsGroup;
106             }
107         });
108     }
109 
110     /**
111      * Return an AccessControlContext that doesn't support any permissions.
112      */
113     @SuppressWarnings("removal")
114     private static AccessControlContext innocuousACC() {
115         return new AccessControlContext(new ProtectionDomain[] {
116                 new ProtectionDomain(null, null)
117         });
118     }
119 















120     static {
121         CONTEXTCLASSLOADER = U.objectFieldOffset(Thread.class,
122                 "contextClassLoader");
123         INHERITABLETHREADLOCALS = U.objectFieldOffset(Thread.class,
124                 "inheritableThreadLocals");
125         INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset(Thread.class,
126                 "inheritedAccessControlContext");
127     }
128 }

  1 /*
  2  * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.internal.misc;
 27 
 28 import java.security.AccessControlContext;
 29 import java.security.AccessController;
 30 import java.security.PrivilegedAction;
 31 import java.security.ProtectionDomain;
 32 import java.util.concurrent.ForkJoinPool;
 33 import java.util.concurrent.ForkJoinWorkerThread;
 34 import jdk.internal.access.JavaLangAccess;
 35 import jdk.internal.access.JavaUtilConcurrentFJPAccess;
 36 import jdk.internal.access.SharedSecrets;
 37 
 38 /**
 39  * A ForkJoinWorkerThread that can be used as a carrier thread.
 40  */
 41 public class CarrierThread extends ForkJoinWorkerThread {
 42     private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
 43     private static final Unsafe U = Unsafe.getUnsafe();
 44 
 45     private static final ThreadGroup CARRIER_THREADGROUP = carrierThreadGroup();
 46     @SuppressWarnings("removal")
 47     private static final AccessControlContext INNOCUOUS_ACC = innocuousACC();
 48 
 49     private static final long CONTEXTCLASSLOADER;
 50     private static final long INHERITABLETHREADLOCALS;
 51     private static final long INHERITEDACCESSCONTROLCONTEXT;
 52 
 53     // compensating state
 54     private static final int NOT_COMPENSATING = 0;
 55     private static final int COMPENSATE_IN_PROGRESS = 1;
 56     private static final int COMPENSATING = 2;
 57     private int compensating;
 58     private long compensateValue;   // FJP value to adjust release counts
 59 
 60     @SuppressWarnings("this-escape")
 61     public CarrierThread(ForkJoinPool pool) {
 62         super(CARRIER_THREADGROUP, pool, true);
 63         U.putReference(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
 64         U.putReference(this, INHERITABLETHREADLOCALS, null);
 65         U.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);
 66     }
 67 
 68     /**
 69      * Mark the start of a blocking operation.
 70      */
 71     public void beginBlocking() {
 72         assert Thread.currentThread().isVirtual() && JLA.currentCarrierThread() == this;
 73         if (compensating == NOT_COMPENSATING) {
 74             compensating = COMPENSATE_IN_PROGRESS;
 75 
 76             // FJP.tryCompensate to create or re-activate a spare thread
 77             long value;
 78             try {
 79                 value = ForkJoinPools.beginCompensatedBlock(getPool());
 80             } catch (Throwable e) {
 81                 if (compensating == COMPENSATE_IN_PROGRESS) {
 82                     compensating = NOT_COMPENSATING;
 83                 }
 84                 throw e;
 85             }
 86 
 87             if (compensating == COMPENSATE_IN_PROGRESS) {
 88                 compensateValue = value;
 89                 compensating = COMPENSATING;
 90             } else {
 91                 // forced preemption or preempted when attempting to compensate
 92                 ForkJoinPools.endCompensatedBlock(getPool(), value);
 93             }
 94         }
 95     }
 96 
 97     /**
 98      * Mark the end of a blocking operation.
 99      */
100     public void endBlocking() {
101         assert Thread.currentThread() == this || JLA.currentCarrierThread() == this;
102         if (compensating == COMPENSATING) {
103             ForkJoinPools.endCompensatedBlock(getPool(), compensateValue);
104             compensating = NOT_COMPENSATING;
105         }
106     }
107 
108     @Override
109     public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) { }
110 
111     @Override
112     public void setContextClassLoader(ClassLoader cl) {
113         throw new SecurityException("setContextClassLoader");
114     }
115 
116     /**
117      * The thread group for the carrier threads.
118      */
119     @SuppressWarnings("removal")
120     private static ThreadGroup carrierThreadGroup() {
121         return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
122             public ThreadGroup run() {
123                 ThreadGroup group = JLA.currentCarrierThread().getThreadGroup();
124                 for (ThreadGroup p; (p = group.getParent()) != null; )
125                     group = p;
126                 var carrierThreadsGroup = new ThreadGroup(group, "CarrierThreads");
127                 return carrierThreadsGroup;
128             }
129         });
130     }
131 
132     /**
133      * Return an AccessControlContext that doesn't support any permissions.
134      */
135     @SuppressWarnings("removal")
136     private static AccessControlContext innocuousACC() {
137         return new AccessControlContext(new ProtectionDomain[] {
138                 new ProtectionDomain(null, null)
139         });
140     }
141 
142     /**
143      * Defines static methods to invoke non-public ForkJoinPool methods via the
144      * shared secret support.
145      */
146     private static class ForkJoinPools {
147         private static final JavaUtilConcurrentFJPAccess FJP_ACCESS =
148                 SharedSecrets.getJavaUtilConcurrentFJPAccess();
149         static long beginCompensatedBlock(ForkJoinPool pool) {
150             return FJP_ACCESS.beginCompensatedBlock(pool);
151         }
152         static void endCompensatedBlock(ForkJoinPool pool, long post) {
153             FJP_ACCESS.endCompensatedBlock(pool, post);
154         }
155     }
156 
157     static {
158         CONTEXTCLASSLOADER = U.objectFieldOffset(Thread.class,
159                 "contextClassLoader");
160         INHERITABLETHREADLOCALS = U.objectFieldOffset(Thread.class,
161                 "inheritableThreadLocals");
162         INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset(Thread.class,
163                 "inheritedAccessControlContext");
164     }
165 }
< prev index next >