1 /*
  2  * Copyright (c) 2021, 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 by the default scheduler.
 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 blocked;    // true if executing blocker
 53 
 54     public CarrierThread(ForkJoinPool pool) {
 55         super(CARRIER_THREADGROUP, pool);
 56         U.putReference(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
 57         U.putReference(this, INHERITABLETHREADLOCALS, null);
 58         U.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);
 59     }
 60 
 61     /**
 62      * For use by {@link Blocker} to test if the thread is executing a blocking operation.
 63      */
 64     boolean blocked() {
 65         //assert JLA.currentCarrierThread() == this;
 66         return blocked;
 67     }
 68 
 69     /**
 70      * For use by {@link Blocker} to set whether the thread is executing a blocking operation.
 71      */
 72     void blocked(boolean b) {
 73         //assert JLA.currentCarrierThread() == this;
 74         this.blocked = b;
 75     }
 76 
 77     @Override
 78     public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) { }
 79 
 80     @Override
 81     public void setContextClassLoader(ClassLoader cl) {
 82         throw new SecurityException("setContextClassLoader");
 83     }
 84 
 85     /**
 86      * The thread group for the carrier threads.
 87      */
 88     @SuppressWarnings("removal")
 89     private static final ThreadGroup carrierThreadGroup() {
 90         return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
 91             public ThreadGroup run() {
 92                 @SuppressWarnings("deprecation")
 93                 ThreadGroup group = JLA.currentCarrierThread().getThreadGroup();
 94                 for (ThreadGroup p; (p = group.getParent()) != null; )
 95                     group = p;
 96                 @SuppressWarnings("deprecation")
 97                 var carrierThreadsGroup = new ThreadGroup(group, "CarrierThreads");
 98                 return carrierThreadsGroup;
 99             }
100         });
101     }
102 
103     /**
104      * Return an AccessControlContext that doesn't support any permissions.
105      */
106     @SuppressWarnings("removal")
107     private static AccessControlContext innocuousACC() {
108         return new AccessControlContext(new ProtectionDomain[] {
109                 new ProtectionDomain(null, null)
110         });
111     }
112 
113     static {
114         CONTEXTCLASSLOADER = U.objectFieldOffset(Thread.class,
115                 "contextClassLoader");
116         INHERITABLETHREADLOCALS = U.objectFieldOffset(Thread.class,
117                 "inheritableThreadLocals");
118         INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset(Thread.class,
119                 "inheritedAccessControlContext");
120     }
121 }