< prev index next >

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

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
--- 1,7 ---
  /*
!  * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

*** 30,10 ***
--- 30,11 ---
  import java.security.PrivilegedAction;
  import java.security.ProtectionDomain;
  import java.util.concurrent.ForkJoinPool;
  import java.util.concurrent.ForkJoinWorkerThread;
  import jdk.internal.access.JavaLangAccess;
+ import jdk.internal.access.JavaUtilConcurrentFJPAccess;
  import jdk.internal.access.SharedSecrets;
  
  /**
   * A ForkJoinWorkerThread that can be used as a carrier thread.
   */

*** 47,42 ***
  
      private static final long CONTEXTCLASSLOADER;
      private static final long INHERITABLETHREADLOCALS;
      private static final long INHERITEDACCESSCONTROLCONTEXT;
  
!     private boolean blocking;    // true if in blocking op
  
      @SuppressWarnings("this-escape")
      public CarrierThread(ForkJoinPool pool) {
          super(CARRIER_THREADGROUP, pool, true);
          U.putReference(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
          U.putReference(this, INHERITABLETHREADLOCALS, null);
          U.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);
      }
  
      /**
!      * For use by {@link Blocker} to test if the thread is in a blocking operation.
       */
!     boolean inBlocking() {
!         //assert JLA.currentCarrierThread() == this;
!         return blocking;
!     }
  
!     /**
!      * For use by {@link Blocker} to mark the start of a blocking operation.
!      */
!     void beginBlocking() {
!         //assert JLA.currentCarrierThread() == this && !blocking;
!         blocking = true;
      }
  
      /**
!      * For use by {@link Blocker} to mark the end of a blocking operation.
       */
!     void endBlocking() {
!         //assert JLA.currentCarrierThread() == this && blocking;
!         blocking = false;
      }
  
      @Override
      public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) { }
  
--- 48,63 ---
  
      private static final long CONTEXTCLASSLOADER;
      private static final long INHERITABLETHREADLOCALS;
      private static final long INHERITEDACCESSCONTROLCONTEXT;
  
!     // compensating state
+     private static final int NOT_COMPENSATING = 0;
+     private static final int COMPENSATE_IN_PROGRESS = 1;
+     private static final int COMPENSATING = 2;
+     private int compensating;
+     private long compensateValue;   // FJP value to adjust release counts
  
      @SuppressWarnings("this-escape")
      public CarrierThread(ForkJoinPool pool) {
          super(CARRIER_THREADGROUP, pool, true);
          U.putReference(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
          U.putReference(this, INHERITABLETHREADLOCALS, null);
          U.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, INNOCUOUS_ACC);
      }
  
      /**
!      * Mark the start of a blocking operation.
       */
!     public void beginBlocking() {
!         assert Thread.currentThread().isVirtual() && JLA.currentCarrierThread() == this;
!         if (compensating == NOT_COMPENSATING) {
!             compensating = COMPENSATE_IN_PROGRESS;
  
!             // FJP.tryCompensate to create or re-activate a spare thread
!             long value;
!             try {
!                 value = ForkJoinPools.beginCompensatedBlock(getPool());
!             } catch (Throwable e) {
!                 if (compensating == COMPENSATE_IN_PROGRESS) {
+                     compensating = NOT_COMPENSATING;
+                 }
+                 throw e;
+             }
+ 
+             if (compensating == COMPENSATE_IN_PROGRESS) {
+                 compensateValue = value;
+                 compensating = COMPENSATING;
+             } else {
+                 // forced preemption or preempted when attempting to compensate
+                 ForkJoinPools.endCompensatedBlock(getPool(), value);
+             }
+         }
      }
  
      /**
!      * Mark the end of a blocking operation.
       */
!     public void endBlocking() {
!         assert Thread.currentThread() == this || JLA.currentCarrierThread() == this;
!         if (compensating == COMPENSATING) {
+             ForkJoinPools.endCompensatedBlock(getPool(), compensateValue);
+             compensating = NOT_COMPENSATING;
+         }
      }
  
      @Override
      public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) { }
  

*** 93,11 ***
  
      /**
       * The thread group for the carrier threads.
       */
      @SuppressWarnings("removal")
!     private static final ThreadGroup carrierThreadGroup() {
          return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
              public ThreadGroup run() {
                  ThreadGroup group = JLA.currentCarrierThread().getThreadGroup();
                  for (ThreadGroup p; (p = group.getParent()) != null; )
                      group = p;
--- 115,11 ---
  
      /**
       * The thread group for the carrier threads.
       */
      @SuppressWarnings("removal")
!     private static ThreadGroup carrierThreadGroup() {
          return AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
              public ThreadGroup run() {
                  ThreadGroup group = JLA.currentCarrierThread().getThreadGroup();
                  for (ThreadGroup p; (p = group.getParent()) != null; )
                      group = p;

*** 115,10 ***
--- 137,25 ---
          return new AccessControlContext(new ProtectionDomain[] {
                  new ProtectionDomain(null, null)
          });
      }
  
+     /**
+      * Defines static methods to invoke non-public ForkJoinPool methods via the
+      * shared secret support.
+      */
+     private static class ForkJoinPools {
+         private static final JavaUtilConcurrentFJPAccess FJP_ACCESS =
+                 SharedSecrets.getJavaUtilConcurrentFJPAccess();
+         static long beginCompensatedBlock(ForkJoinPool pool) {
+             return FJP_ACCESS.beginCompensatedBlock(pool);
+         }
+         static void endCompensatedBlock(ForkJoinPool pool, long post) {
+             FJP_ACCESS.endCompensatedBlock(pool, post);
+         }
+     }
+ 
      static {
          CONTEXTCLASSLOADER = U.objectFieldOffset(Thread.class,
                  "contextClassLoader");
          INHERITABLETHREADLOCALS = U.objectFieldOffset(Thread.class,
                  "inheritableThreadLocals");
< prev index next >