< prev index next >

src/java.base/share/classes/java/lang/VirtualThread.java

Print this page

   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 package java.lang;
  26 

  27 import java.security.AccessController;
  28 import java.security.PrivilegedAction;
  29 import java.util.Locale;
  30 import java.util.Objects;
  31 import java.util.concurrent.Callable;
  32 import java.util.concurrent.CountDownLatch;
  33 import java.util.concurrent.Executor;
  34 import java.util.concurrent.Executors;
  35 import java.util.concurrent.ForkJoinPool;
  36 import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
  37 import java.util.concurrent.ForkJoinTask;
  38 import java.util.concurrent.ForkJoinWorkerThread;
  39 import java.util.concurrent.Future;
  40 import java.util.concurrent.RejectedExecutionException;
  41 import java.util.concurrent.ScheduledExecutorService;
  42 import java.util.concurrent.ScheduledThreadPoolExecutor;

  43 import jdk.internal.event.VirtualThreadEndEvent;
  44 import jdk.internal.event.VirtualThreadPinnedEvent;
  45 import jdk.internal.event.VirtualThreadStartEvent;
  46 import jdk.internal.event.VirtualThreadSubmitFailedEvent;
  47 import jdk.internal.misc.CarrierThread;
  48 import jdk.internal.misc.InnocuousThread;
  49 import jdk.internal.misc.Unsafe;
  50 import jdk.internal.vm.Continuation;
  51 import jdk.internal.vm.ContinuationScope;
  52 import jdk.internal.vm.StackableScope;
  53 import jdk.internal.vm.ThreadContainer;
  54 import jdk.internal.vm.ThreadContainers;
  55 import jdk.internal.vm.annotation.ChangesCurrentThread;
  56 import jdk.internal.vm.annotation.Hidden;
  57 import jdk.internal.vm.annotation.IntrinsicCandidate;
  58 import jdk.internal.vm.annotation.JvmtiMountTransition;
  59 import jdk.internal.vm.annotation.ReservedStackAccess;
  60 import sun.nio.ch.Interruptible;
  61 import sun.security.action.GetPropertyAction;
  62 import static java.util.concurrent.TimeUnit.*;
  63 
  64 /**
  65  * A thread that is scheduled by the Java virtual machine rather than the operating
  66  * system.
  67  */
  68 final class VirtualThread extends BaseVirtualThread {
  69     private static final Unsafe U = Unsafe.getUnsafe();
  70     private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
  71     private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler();
  72     private static final ScheduledExecutorService UNPARKER = createDelayedTaskScheduler();
  73     private static final int TRACE_PINNING_MODE = tracePinningMode();
  74 
  75     private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state");
  76     private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
  77     private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
  78     private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");

  79 
  80     // scheduler and continuation
  81     private final Executor scheduler;
  82     private final Continuation cont;
  83     private final Runnable runContinuation;
  84 
  85     // virtual thread state, accessed by VM
  86     private volatile int state;
  87 
  88     /*
  89      * Virtual thread state transitions:
  90      *
  91      *      NEW -> STARTED         // Thread.start, schedule to run
  92      *  STARTED -> TERMINATED      // failed to start
  93      *  STARTED -> RUNNING         // first run
  94      *  RUNNING -> TERMINATED      // done
  95      *
  96      *  RUNNING -> PARKING         // Thread parking with LockSupport.park
  97      *  PARKING -> PARKED          // cont.yield successful, parked indefinitely
  98      *  PARKING -> PINNED          // cont.yield failed, parked indefinitely on carrier
  99      *   PARKED -> UNPARKED        // unparked, may be scheduled to continue
 100      *   PINNED -> RUNNING         // unparked, continue execution on same carrier
 101      * UNPARKED -> RUNNING         // continue execution after park
 102      *
 103      *       RUNNING -> TIMED_PARKING   // Thread parking with LockSupport.parkNanos
 104      * TIMED_PARKING -> TIMED_PARKED    // cont.yield successful, timed-parked
 105      * TIMED_PARKING -> TIMED_PINNED    // cont.yield failed, timed-parked on carrier
 106      *  TIMED_PARKED -> UNPARKED        // unparked, may be scheduled to continue
 107      *  TIMED_PINNED -> RUNNING         // unparked, continue execution on same carrier
 108      *















 109      *  RUNNING -> YIELDING        // Thread.yield
 110      * YIELDING -> YIELDED         // cont.yield successful, may be scheduled to continue
 111      * YIELDING -> RUNNING         // cont.yield failed
 112      *  YIELDED -> RUNNING         // continue execution after Thread.yield
 113      */
 114     private static final int NEW      = 0;
 115     private static final int STARTED  = 1;
 116     private static final int RUNNING  = 2;     // runnable-mounted
 117 
 118     // untimed and timed parking
 119     private static final int PARKING       = 3;
 120     private static final int PARKED        = 4;     // unmounted
 121     private static final int PINNED        = 5;     // mounted
 122     private static final int TIMED_PARKING = 6;
 123     private static final int TIMED_PARKED  = 7;     // unmounted
 124     private static final int TIMED_PINNED  = 8;     // mounted
 125     private static final int UNPARKED      = 9;     // unmounted but runnable
 126 
 127     // Thread.yield
 128     private static final int YIELDING = 10;
 129     private static final int YIELDED  = 11;         // unmounted but runnable
 130 











 131     private static final int TERMINATED = 99;  // final state
 132 
 133     // can be suspended from scheduling when unmounted
 134     private static final int SUSPENDED = 1 << 8;
 135 
 136     // parking permit
 137     private volatile boolean parkPermit;
 138 











 139     // carrier thread when mounted, accessed by VM
 140     private volatile Thread carrierThread;
 141 
 142     // termination object when joining, created lazily if needed
 143     private volatile CountDownLatch termination;
 144 






 145     /**
 146      * Returns the continuation scope used for virtual threads.
 147      */
 148     static ContinuationScope continuationScope() {
 149         return VTHREAD_SCOPE;
 150     }
 151 
 152     /**
 153      * Creates a new {@code VirtualThread} to run the given task with the given
 154      * scheduler. If the given scheduler is {@code null} and the current thread
 155      * is a platform thread then the newly created virtual thread will use the
 156      * default scheduler. If given scheduler is {@code null} and the current
 157      * thread is a virtual thread then the current thread's scheduler is used.
 158      *
 159      * @param scheduler the scheduler or null
 160      * @param name thread name
 161      * @param characteristics characteristics
 162      * @param task the task to execute
 163      */
 164     VirtualThread(Executor scheduler, String name, int characteristics, Runnable task) {

 172                 scheduler = vparent.scheduler;
 173             } else {
 174                 scheduler = DEFAULT_SCHEDULER;
 175             }
 176         }
 177 
 178         this.scheduler = scheduler;
 179         this.cont = new VThreadContinuation(this, task);
 180         this.runContinuation = this::runContinuation;
 181     }
 182 
 183     /**
 184      * The continuation that a virtual thread executes.
 185      */
 186     private static class VThreadContinuation extends Continuation {
 187         VThreadContinuation(VirtualThread vthread, Runnable task) {
 188             super(VTHREAD_SCOPE, wrap(vthread, task));
 189         }
 190         @Override
 191         protected void onPinned(Continuation.Pinned reason) {
 192             if (TRACE_PINNING_MODE > 0) {
 193                 boolean printAll = (TRACE_PINNING_MODE == 1);
 194                 VirtualThread vthread = (VirtualThread) Thread.currentThread();
 195                 int oldState = vthread.state();
 196                 try {
 197                     // avoid printing when in transition states
 198                     vthread.setState(RUNNING);
 199                     PinnedThreadPrinter.printStackTrace(System.out, reason, printAll);
 200                 } finally {
 201                     vthread.setState(oldState);
 202                 }
 203             }
 204         }
 205         private static Runnable wrap(VirtualThread vthread, Runnable task) {
 206             return new Runnable() {
 207                 @Hidden
 208                 public void run() {
 209                     vthread.run(task);
 210                 }
 211             };
 212         }
 213     }
 214 
 215     /**
 216      * Runs or continues execution on the current thread. The virtual thread is mounted
 217      * on the current thread before the task runs or continues. It unmounts when the
 218      * task completes or yields.
 219      */
 220     @ChangesCurrentThread
 221     private void runContinuation() {
 222         // the carrier must be a platform thread
 223         if (Thread.currentThread().isVirtual()) {
 224             throw new WrongThreadException();
 225         }
 226 
 227         // set state to RUNNING
 228         int initialState = state();
 229         if (initialState == STARTED || initialState == UNPARKED || initialState == YIELDED) {

 230             // newly started or continue after parking/blocking/Thread.yield
 231             if (!compareAndSetState(initialState, RUNNING)) {
 232                 return;
 233             }
 234             // consume parking permit when continuing after parking
 235             if (initialState == UNPARKED) {
 236                 setParkPermit(false);
 237             }
 238         } else {
 239             // not runnable
 240             return;
 241         }
 242 
 243         mount();
 244         try {
 245             cont.run();
 246         } finally {
 247             unmount();
 248             if (cont.isDone()) {
 249                 afterDone();

 251                 afterYield();
 252             }
 253         }
 254     }
 255 
 256     /**
 257      * Submits the runContinuation task to the scheduler. For the default scheduler,
 258      * and calling it on a worker thread, the task will be pushed to the local queue,
 259      * otherwise it will be pushed to an external submission queue.
 260      * @throws RejectedExecutionException
 261      */
 262     private void submitRunContinuation() {
 263         try {
 264             scheduler.execute(runContinuation);
 265         } catch (RejectedExecutionException ree) {
 266             submitFailed(ree);
 267             throw ree;
 268         }
 269     }
 270 














 271     /**
 272      * Submits the runContinuation task to given scheduler with a lazy submit.
 273      * @throws RejectedExecutionException
 274      * @see ForkJoinPool#lazySubmit(ForkJoinTask)
 275      */
 276     private void lazySubmitRunContinuation(ForkJoinPool pool) {
 277         try {
 278             pool.lazySubmit(ForkJoinTask.adapt(runContinuation));
 279         } catch (RejectedExecutionException ree) {
 280             submitFailed(ree);
 281             throw ree;
 282         }
 283     }
 284 
 285     /**
 286      * Submits the runContinuation task to the given scheduler as an external submit.
 287      * @throws RejectedExecutionException
 288      * @see ForkJoinPool#externalSubmit(ForkJoinTask)
 289      */
 290     private void externalSubmitRunContinuation(ForkJoinPool pool) {

 368         } else if (carrier.isInterrupted()) {
 369             synchronized (interruptLock) {
 370                 // need to recheck interrupt status
 371                 if (!interrupted) {
 372                     carrier.clearInterrupt();
 373                 }
 374             }
 375         }
 376 
 377         // set Thread.currentThread() to return this virtual thread
 378         carrier.setCurrentThread(this);
 379     }
 380 
 381     /**
 382      * Unmounts this virtual thread from the carrier. On return, the
 383      * current thread is the current platform thread.
 384      */
 385     @ChangesCurrentThread
 386     @ReservedStackAccess
 387     private void unmount() {


 388         // set Thread.currentThread() to return the platform thread
 389         Thread carrier = this.carrierThread;
 390         carrier.setCurrentThread(carrier);
 391 
 392         // break connection to carrier thread, synchronized with interrupt
 393         synchronized (interruptLock) {
 394             setCarrierThread(null);
 395         }
 396         carrier.clearInterrupt();
 397 
 398         // notify JVMTI after unmount
 399         notifyJvmtiUnmount(/*hide*/false);
 400     }
 401 
 402     /**
 403      * Sets the current thread to the current carrier thread.
 404      */
 405     @ChangesCurrentThread
 406     @JvmtiMountTransition
 407     private void switchToCarrierThread() {
 408         notifyJvmtiHideFrames(true);
 409         Thread carrier = this.carrierThread;
 410         assert Thread.currentThread() == this
 411                 && carrier == Thread.currentCarrierThread();
 412         carrier.setCurrentThread(carrier);

 413     }
 414 
 415     /**
 416      * Sets the current thread to the given virtual thread.
 417      */
 418     @ChangesCurrentThread
 419     @JvmtiMountTransition
 420     private void switchToVirtualThread(VirtualThread vthread) {
 421         Thread carrier = vthread.carrierThread;
 422         assert carrier == Thread.currentCarrierThread();
 423         carrier.setCurrentThread(vthread);
 424         notifyJvmtiHideFrames(false);
 425     }
 426 
 427     /**
 428      * Executes the given value returning task on the current carrier thread.
 429      */
 430     @ChangesCurrentThread
 431     <V> V executeOnCarrierThread(Callable<V> task) throws Exception {
 432         assert Thread.currentThread() == this;

 481                     submitRunContinuation();
 482                 }
 483 
 484             }
 485             return;
 486         }
 487 
 488         // Thread.yield
 489         if (s == YIELDING) {
 490             setState(YIELDED);
 491 
 492             // external submit if there are no tasks in the local task queue
 493             if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
 494                 externalSubmitRunContinuation(ct.getPool());
 495             } else {
 496                 submitRunContinuation();
 497             }
 498             return;
 499         }
 500 
























































 501         assert false;
 502     }
 503 
 504     /**
 505      * Invoked after the continuation completes.
 506      */
 507     private void afterDone() {
 508         afterDone(true);
 509     }
 510 
 511     /**
 512      * Invoked after the continuation completes (or start failed). Sets the thread
 513      * state to TERMINATED and notifies anyone waiting for the thread to terminate.
 514      *
 515      * @param notifyContainer true if its container should be notified
 516      */
 517     private void afterDone(boolean notifyContainer) {
 518         assert carrierThread == null;
 519         setState(TERMINATED);
 520 

 544     @Override
 545     void start(ThreadContainer container) {
 546         if (!compareAndSetState(NEW, STARTED)) {
 547             throw new IllegalThreadStateException("Already started");
 548         }
 549 
 550         // bind thread to container
 551         assert threadContainer() == null;
 552         setThreadContainer(container);
 553 
 554         // start thread
 555         boolean addedToContainer = false;
 556         boolean started = false;
 557         try {
 558             container.onStart(this);  // may throw
 559             addedToContainer = true;
 560 
 561             // scoped values may be inherited
 562             inheritScopedValueBindings(container);
 563 
 564             // submit task to run thread
 565             submitRunContinuation();
 566             started = true;
 567         } finally {
 568             if (!started) {
 569                 afterDone(addedToContainer);
 570             }
 571         }
 572     }
 573 
 574     @Override
 575     public void start() {
 576         start(ThreadContainers.root());
 577     }
 578 
 579     @Override
 580     public void run() {
 581         // do nothing
 582     }
 583 
 584     /**
 585      * Parks until unparked or interrupted. If already unparked then the parking
 586      * permit is consumed and this method completes immediately (meaning it doesn't
 587      * yield). It also completes immediately if the interrupt status is set.
 588      */
 589     @Override
 590     void park() {
 591         assert Thread.currentThread() == this;
 592 
 593         // complete immediately if parking permit available or interrupted
 594         if (getAndSetParkPermit(false) || interrupted)
 595             return;
 596 
 597         // park the thread
 598         boolean yielded = false;
 599         setState(PARKING);
 600         try {
 601             yielded = yieldContinuation();  // may throw
 602         } finally {
 603             assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
 604             if (!yielded) {
 605                 assert state() == PARKING;

 648             }
 649 
 650             // park on carrier thread for remaining time when pinned
 651             if (!yielded) {
 652                 long remainingNanos = nanos - (System.nanoTime() - startTime);
 653                 parkOnCarrierThread(true, remainingNanos);
 654             }
 655         }
 656     }
 657 
 658     /**
 659      * Parks the current carrier thread up to the given waiting time or until
 660      * unparked or interrupted. If the virtual thread is interrupted then the
 661      * interrupt status will be propagated to the carrier thread.
 662      * @param timed true for a timed park, false for untimed
 663      * @param nanos the waiting time in nanoseconds
 664      */
 665     private void parkOnCarrierThread(boolean timed, long nanos) {
 666         assert state() == RUNNING;
 667 
 668         VirtualThreadPinnedEvent event;
 669         try {
 670             event = new VirtualThreadPinnedEvent();
 671             event.begin();
 672         } catch (OutOfMemoryError e) {
 673             event = null;
 674         }
 675 
 676         setState(timed ? TIMED_PINNED : PINNED);
 677         try {
 678             if (!parkPermit) {
 679                 if (!timed) {
 680                     U.park(false, 0);
 681                 } else if (nanos > 0) {
 682                     U.park(false, nanos);
 683                 }
 684             }
 685         } finally {
 686             setState(RUNNING);
 687         }
 688 
 689         // consume parking permit
 690         setParkPermit(false);
 691 
 692         if (event != null) {
 693             try {
 694                 event.commit();
 695             } catch (OutOfMemoryError e) {
 696                 // ignore
 697             }
 698         }
 699     }
 700 







 701     /**
 702      * Schedule this virtual thread to be unparked after a given delay.
 703      */
 704     @ChangesCurrentThread
 705     private Future<?> scheduleUnpark(long nanos) {
 706         assert Thread.currentThread() == this;
 707         // need to switch to current carrier thread to avoid nested parking
 708         switchToCarrierThread();
 709         try {
 710             return UNPARKER.schedule(this::unpark, nanos, NANOSECONDS);
 711         } finally {
 712             switchToVirtualThread(this);
 713         }
 714     }
 715 
 716     /**
 717      * Cancels a task if it has not completed.
 718      */
 719     @ChangesCurrentThread
 720     private void cancel(Future<?> future) {

 721         if (!future.isDone()) {
 722             // need to switch to current carrier thread to avoid nested parking
 723             switchToCarrierThread();
 724             try {
 725                 future.cancel(false);
 726             } finally {
 727                 switchToVirtualThread(this);
 728             }
 729         }
 730     }
 731 
 732     /**
 733      * Re-enables this virtual thread for scheduling. If the virtual thread was
 734      * {@link #park() parked} then it will be unblocked, otherwise its next call
 735      * to {@code park} or {@linkplain #parkNanos(long) parkNanos} is guaranteed
 736      * not to block.
 737      * @throws RejectedExecutionException if the scheduler cannot accept a task
 738      */
 739     @Override
 740     @ChangesCurrentThread
 741     void unpark() {
 742         Thread currentThread = Thread.currentThread();
 743         if (!getAndSetParkPermit(true) && currentThread != this) {
 744             int s = state();
 745             boolean parked = (s == PARKED) || (s == TIMED_PARKED);
 746             if (parked && compareAndSetState(s, UNPARKED)) {

 747                 if (currentThread instanceof VirtualThread vthread) {
 748                     vthread.switchToCarrierThread();
 749                     try {
 750                         submitRunContinuation();
 751                     } finally {
 752                         switchToVirtualThread(vthread);
 753                     }
 754                 } else {
 755                     submitRunContinuation();
 756                 }
 757             } else if ((s == PINNED) || (s == TIMED_PINNED)) {




 758                 // unpark carrier thread when pinned
 759                 notifyJvmtiDisableSuspend(true);
 760                 try {
 761                     synchronized (carrierThreadAccessLock()) {
 762                         Thread carrier = carrierThread;
 763                         if (carrier != null && ((s = state()) == PINNED || s == TIMED_PINNED)) {
 764                             U.unpark(carrier);
 765                         }
 766                     }
 767                 } finally {
 768                     notifyJvmtiDisableSuspend(false);





























 769                 }






 770             }
 771         }
 772     }
 773 











 774     /**
 775      * Attempts to yield the current virtual thread (Thread.yield).
 776      */
 777     void tryYield() {
 778         assert Thread.currentThread() == this;
 779         setState(YIELDING);
 780         boolean yielded = false;
 781         try {
 782             yielded = yieldContinuation();  // may throw
 783         } finally {
 784             assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
 785             if (!yielded) {
 786                 assert state() == YIELDING;
 787                 setState(RUNNING);
 788             }
 789         }
 790     }
 791 
 792     /**
 793      * Sleep the current thread for the given sleep time (in nanoseconds). If

 842         CountDownLatch termination = getTermination();
 843         if (state() == TERMINATED)
 844             return true;
 845 
 846         // wait for virtual thread to terminate
 847         if (nanos == 0) {
 848             termination.await();
 849         } else {
 850             boolean terminated = termination.await(nanos, NANOSECONDS);
 851             if (!terminated) {
 852                 // waiting time elapsed
 853                 return false;
 854             }
 855         }
 856         assert state() == TERMINATED;
 857         return true;
 858     }
 859 
 860     @Override
 861     void blockedOn(Interruptible b) {
 862         notifyJvmtiDisableSuspend(true);
 863         try {
 864             super.blockedOn(b);
 865         } finally {
 866             notifyJvmtiDisableSuspend(false);
 867         }
 868     }
 869 
 870     @Override
 871     @SuppressWarnings("removal")
 872     public void interrupt() {
 873         if (Thread.currentThread() != this) {
 874             checkAccess();
 875 
 876             // if current thread is a virtual thread then prevent it from being
 877             // suspended when entering or holding interruptLock
 878             Interruptible blocker;
 879             notifyJvmtiDisableSuspend(true);
 880             try {
 881                 synchronized (interruptLock) {
 882                     interrupted = true;
 883                     blocker = nioBlocker();
 884                     if (blocker != null) {
 885                         blocker.interrupt(this);
 886                     }
 887 
 888                     // interrupt carrier thread if mounted
 889                     Thread carrier = carrierThread;
 890                     if (carrier != null) carrier.setInterrupt();
 891                 }
 892             } finally {
 893                 notifyJvmtiDisableSuspend(false);
 894             }
 895 
 896             // notify blocker after releasing interruptLock
 897             if (blocker != null) {
 898                 blocker.postInterrupt();
 899             }










 900         } else {
 901             interrupted = true;
 902             carrierThread.setInterrupt();

 903         }
 904         unpark();
 905     }
 906 
 907     @Override
 908     public boolean isInterrupted() {
 909         return interrupted;
 910     }
 911 
 912     @Override
 913     boolean getAndClearInterrupt() {
 914         assert Thread.currentThread() == this;
 915         boolean oldValue = interrupted;
 916         if (oldValue) {
 917             notifyJvmtiDisableSuspend(true);
 918             try {
 919                 synchronized (interruptLock) {
 920                     interrupted = false;
 921                     carrierThread.clearInterrupt();
 922                 }
 923             } finally {
 924                 notifyJvmtiDisableSuspend(false);
 925             }
 926         }
 927         return oldValue;
 928     }
 929 
 930     @Override
 931     Thread.State threadState() {
 932         int s = state();
 933         switch (s & ~SUSPENDED) {
 934             case NEW:
 935                 return Thread.State.NEW;
 936             case STARTED:
 937                 // return NEW if thread container not yet set
 938                 if (threadContainer() == null) {
 939                     return Thread.State.NEW;
 940                 } else {
 941                     return Thread.State.RUNNABLE;
 942                 }
 943             case UNPARKED:
 944             case YIELDED:
 945                 // runnable, not mounted
 946                 return Thread.State.RUNNABLE;







 947             case RUNNING:




 948                 // if mounted then return state of carrier thread
 949                 notifyJvmtiDisableSuspend(true);
 950                 try {
 951                     synchronized (carrierThreadAccessLock()) {
 952                         Thread carrierThread = this.carrierThread;
 953                         if (carrierThread != null) {
 954                             return carrierThread.threadState();


 955                         }


 956                     }
 957                 } finally {
 958                     notifyJvmtiDisableSuspend(false);
 959                 }
 960                 // runnable, mounted
 961                 return Thread.State.RUNNABLE;
 962             case PARKING:
 963             case TIMED_PARKING:
 964             case YIELDING:


 965                 // runnable, in transition
 966                 return Thread.State.RUNNABLE;
 967             case PARKED:
 968             case PINNED:

 969                 return State.WAITING;
 970             case TIMED_PARKED:
 971             case TIMED_PINNED:

 972                 return State.TIMED_WAITING;



 973             case TERMINATED:
 974                 return Thread.State.TERMINATED;
 975             default:
 976                 throw new InternalError();
 977         }
 978     }
 979 








 980     @Override
 981     boolean alive() {
 982         int s = state;
 983         return (s != NEW && s != TERMINATED);
 984     }
 985 
 986     @Override
 987     boolean isTerminated() {
 988         return (state == TERMINATED);
 989     }
 990 
 991     @Override
 992     StackTraceElement[] asyncGetStackTrace() {
 993         StackTraceElement[] stackTrace;
 994         do {
 995             stackTrace = (carrierThread != null)
 996                     ? super.asyncGetStackTrace()  // mounted
 997                     : tryGetStackTrace();         // unmounted
 998             if (stackTrace == null) {
 999                 Thread.yield();
1000             }
1001         } while (stackTrace == null);
1002         return stackTrace;
1003     }
1004 
1005     /**
1006      * Returns the stack trace for this virtual thread if it is unmounted.
1007      * Returns null if the thread is mounted or in transition.
1008      */
1009     private StackTraceElement[] tryGetStackTrace() {
1010         int initialState = state() & ~SUSPENDED;
1011         switch (initialState) {
1012             case NEW, STARTED, TERMINATED -> {
1013                 return new StackTraceElement[0];  // unmounted, empty stack
1014             }
1015             case RUNNING, PINNED, TIMED_PINNED -> {
1016                 return null;   // mounted
1017             }
1018             case PARKED, TIMED_PARKED -> {
1019                 // unmounted, not runnable
1020             }
1021             case UNPARKED, YIELDED -> {
1022                 // unmounted, runnable
1023             }
1024             case PARKING, TIMED_PARKING, YIELDING -> {
1025                 return null;  // in transition
1026             }
1027             default -> throw new InternalError("" + initialState);
1028         }
1029 
1030         // thread is unmounted, prevent it from continuing
1031         int suspendedState = initialState | SUSPENDED;
1032         if (!compareAndSetState(initialState, suspendedState)) {
1033             return null;
1034         }
1035 
1036         // get stack trace and restore state
1037         StackTraceElement[] stack;
1038         try {
1039             stack = cont.getStackTrace();
1040         } finally {
1041             assert state == suspendedState;
1042             setState(initialState);
1043         }
1044         boolean resubmit = switch (initialState) {
1045             case UNPARKED, YIELDED -> {
1046                 // resubmit as task may have run while suspended
1047                 yield true;
1048             }
1049             case PARKED, TIMED_PARKED -> {
1050                 // resubmit if unparked while suspended
1051                 yield parkPermit && compareAndSetState(initialState, UNPARKED);
1052             }








1053             default -> throw new InternalError();
1054         };
1055         if (resubmit) {
1056             submitRunContinuation();
1057         }
1058         return stack;
1059     }
1060 
1061     @Override
1062     public String toString() {
1063         StringBuilder sb = new StringBuilder("VirtualThread[#");
1064         sb.append(threadId());
1065         String name = getName();
1066         if (!name.isEmpty()) {
1067             sb.append(",");
1068             sb.append(name);
1069         }
1070         sb.append("]/");
1071         Thread carrier = carrierThread;
1072         if (carrier != null) {
1073             // include the carrier thread state and name when mounted
1074             notifyJvmtiDisableSuspend(true);



1075             try {
1076                 synchronized (carrierThreadAccessLock()) {
1077                     carrier = carrierThread;
1078                     if (carrier != null) {
1079                         String stateAsString = carrier.threadState().toString();
1080                         sb.append(stateAsString.toLowerCase(Locale.ROOT));
1081                         sb.append('@');
1082                         sb.append(carrier.getName());
1083                     }
1084                 }
1085             } finally {
1086                 notifyJvmtiDisableSuspend(false);
1087             }
1088         }
1089         // include virtual thread state when not mounted
1090         if (carrier == null) {

1091             String stateAsString = threadState().toString();
1092             sb.append(stateAsString.toLowerCase(Locale.ROOT));
1093         }

1094         return sb.toString();
1095     }
1096 


















1097     @Override
1098     public int hashCode() {
1099         return (int) threadId();
1100     }
1101 
1102     @Override
1103     public boolean equals(Object obj) {
1104         return obj == this;
1105     }
1106 
1107     /**
1108      * Returns the termination object, creating it if needed.
1109      */
1110     private CountDownLatch getTermination() {
1111         CountDownLatch termination = this.termination;
1112         if (termination == null) {
1113             termination = new CountDownLatch(1);
1114             if (!U.compareAndSetReference(this, TERMINATION, null, termination)) {
1115                 termination = this.termination;
1116             }
1117         }
1118         return termination;
1119     }
1120 
1121     /**
1122      * Returns the lock object to synchronize on when accessing carrierThread.
1123      * The lock prevents carrierThread from being reset to null during unmount.
1124      */
1125     private Object carrierThreadAccessLock() {
1126         // return interruptLock as unmount has to coordinate with interrupt
1127         return interruptLock;
1128     }
1129 
















1130     // -- wrappers for get/set of state, parking permit, and carrier thread --
1131 
1132     private int state() {
1133         return state;  // volatile read
1134     }
1135 
1136     private void setState(int newValue) {
1137         state = newValue;  // volatile write
1138     }
1139 
1140     private boolean compareAndSetState(int expectedValue, int newValue) {
1141         return U.compareAndSetInt(this, STATE, expectedValue, newValue);
1142     }
1143 




1144     private void setParkPermit(boolean newValue) {
1145         if (parkPermit != newValue) {
1146             parkPermit = newValue;
1147         }
1148     }
1149 
1150     private boolean getAndSetParkPermit(boolean newValue) {
1151         if (parkPermit != newValue) {
1152             return U.getAndSetBoolean(this, PARK_PERMIT, newValue);
1153         } else {
1154             return newValue;
1155         }
1156     }
1157 
1158     private void setCarrierThread(Thread carrier) {
1159         // U.putReferenceRelease(this, CARRIER_THREAD, carrier);
1160         this.carrierThread = carrier;
1161     }
1162 



1163     // -- JVM TI support --
1164 
1165     @IntrinsicCandidate
1166     @JvmtiMountTransition
1167     private native void notifyJvmtiStart();
1168 
1169     @IntrinsicCandidate
1170     @JvmtiMountTransition
1171     private native void notifyJvmtiEnd();
1172 
1173     @IntrinsicCandidate
1174     @JvmtiMountTransition
1175     private native void notifyJvmtiMount(boolean hide);
1176 
1177     @IntrinsicCandidate
1178     @JvmtiMountTransition
1179     private native void notifyJvmtiUnmount(boolean hide);
1180 
1181     @IntrinsicCandidate
1182     @JvmtiMountTransition

1212             if (maxPoolSizeValue != null) {
1213                 maxPoolSize = Integer.parseInt(maxPoolSizeValue);
1214                 parallelism = Integer.min(parallelism, maxPoolSize);
1215             } else {
1216                 maxPoolSize = Integer.max(parallelism, 256);
1217             }
1218             if (minRunnableValue != null) {
1219                 minRunnable = Integer.parseInt(minRunnableValue);
1220             } else {
1221                 minRunnable = Integer.max(parallelism / 2, 1);
1222             }
1223             Thread.UncaughtExceptionHandler handler = (t, e) -> { };
1224             boolean asyncMode = true; // FIFO
1225             return new ForkJoinPool(parallelism, factory, handler, asyncMode,
1226                          0, maxPoolSize, minRunnable, pool -> true, 30, SECONDS);
1227         };
1228         return AccessController.doPrivileged(pa);
1229     }
1230 
1231     /**
1232      * Creates the ScheduledThreadPoolExecutor used for timed unpark.

















1233      */
1234     private static ScheduledExecutorService createDelayedTaskScheduler() {
1235         String propValue = GetPropertyAction.privilegedGetProperty("jdk.unparker.maxPoolSize");
1236         int poolSize;

1237         if (propValue != null) {
1238             poolSize = Integer.parseInt(propValue);



1239         } else {
1240             poolSize = 1;












1241         }
1242         ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor)
1243             Executors.newScheduledThreadPool(poolSize, task -> {
1244                 return InnocuousThread.newThread("VirtualThread-unparker", task);
1245             });
1246         stpe.setRemoveOnCancelPolicy(true);
1247         return stpe;
1248     }
1249 
1250     /**
1251      * Reads the value of the jdk.tracePinnedThreads property to determine if stack
1252      * traces should be printed when a carrier thread is pinned when a virtual thread
1253      * attempts to park.
1254      */
1255     private static int tracePinningMode() {
1256         String propValue = GetPropertyAction.privilegedGetProperty("jdk.tracePinnedThreads");
1257         if (propValue != null) {
1258             if (propValue.length() == 0 || "full".equalsIgnoreCase(propValue))
1259                 return 1;
1260             if ("short".equalsIgnoreCase(propValue))
1261                 return 2;








1262         }
1263         return 0;












1264     }
1265 }

   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 package java.lang;
  26 
  27 import java.nio.charset.StandardCharsets;
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.util.Locale;
  31 import java.util.Objects;
  32 import java.util.concurrent.Callable;
  33 import java.util.concurrent.CountDownLatch;
  34 import java.util.concurrent.Executor;
  35 import java.util.concurrent.Executors;
  36 import java.util.concurrent.ForkJoinPool;
  37 import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
  38 import java.util.concurrent.ForkJoinTask;
  39 import java.util.concurrent.ForkJoinWorkerThread;
  40 import java.util.concurrent.Future;
  41 import java.util.concurrent.RejectedExecutionException;
  42 import java.util.concurrent.ScheduledExecutorService;
  43 import java.util.concurrent.ScheduledThreadPoolExecutor;
  44 import java.util.concurrent.TimeUnit;
  45 import jdk.internal.event.VirtualThreadEndEvent;

  46 import jdk.internal.event.VirtualThreadStartEvent;
  47 import jdk.internal.event.VirtualThreadSubmitFailedEvent;
  48 import jdk.internal.misc.CarrierThread;
  49 import jdk.internal.misc.InnocuousThread;
  50 import jdk.internal.misc.Unsafe;
  51 import jdk.internal.vm.Continuation;
  52 import jdk.internal.vm.ContinuationScope;
  53 import jdk.internal.vm.StackableScope;
  54 import jdk.internal.vm.ThreadContainer;
  55 import jdk.internal.vm.ThreadContainers;
  56 import jdk.internal.vm.annotation.ChangesCurrentThread;
  57 import jdk.internal.vm.annotation.Hidden;
  58 import jdk.internal.vm.annotation.IntrinsicCandidate;
  59 import jdk.internal.vm.annotation.JvmtiMountTransition;
  60 import jdk.internal.vm.annotation.ReservedStackAccess;
  61 import sun.nio.ch.Interruptible;
  62 import sun.security.action.GetPropertyAction;
  63 import static java.util.concurrent.TimeUnit.*;
  64 
  65 /**
  66  * A thread that is scheduled by the Java virtual machine rather than the operating
  67  * system.
  68  */
  69 final class VirtualThread extends BaseVirtualThread {
  70     private static final Unsafe U = Unsafe.getUnsafe();
  71     private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
  72     private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler();
  73     private static final ScheduledExecutorService[] DELAYED_TASK_SCHEDULERS = createDelayedTaskSchedulers();

  74 
  75     private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state");
  76     private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
  77     private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
  78     private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");
  79     private static final long ON_WAITING_LIST = U.objectFieldOffset(VirtualThread.class, "onWaitingList");
  80 
  81     // scheduler and continuation
  82     private final Executor scheduler;
  83     private final Continuation cont;
  84     private final Runnable runContinuation;
  85 
  86     // virtual thread state, accessed by VM
  87     private volatile int state;
  88 
  89     /*
  90      * Virtual thread state transitions:
  91      *
  92      *      NEW -> STARTED         // Thread.start, schedule to run
  93      *  STARTED -> TERMINATED      // failed to start
  94      *  STARTED -> RUNNING         // first run
  95      *  RUNNING -> TERMINATED      // done
  96      *
  97      *  RUNNING -> PARKING         // Thread parking with LockSupport.park
  98      *  PARKING -> PARKED          // cont.yield successful, parked indefinitely
  99      *  PARKING -> PINNED          // cont.yield failed, parked indefinitely on carrier
 100      *   PARKED -> UNPARKED        // unparked, may be scheduled to continue
 101      *   PINNED -> RUNNING         // unparked, continue execution on same carrier
 102      * UNPARKED -> RUNNING         // continue execution after park
 103      *
 104      *       RUNNING -> TIMED_PARKING   // Thread parking with LockSupport.parkNanos
 105      * TIMED_PARKING -> TIMED_PARKED    // cont.yield successful, timed-parked
 106      * TIMED_PARKING -> TIMED_PINNED    // cont.yield failed, timed-parked on carrier
 107      *  TIMED_PARKED -> UNPARKED        // unparked, may be scheduled to continue
 108      *  TIMED_PINNED -> RUNNING         // unparked, continue execution on same carrier
 109      *
 110      *   RUNNING -> BLOCKING       // blocking on monitor enter
 111      *  BLOCKING -> BLOCKED        // blocked on monitor enter
 112      *   BLOCKED -> UNBLOCKED      // unblocked, may be scheduled to continue
 113      * UNBLOCKED -> RUNNING        // continue execution after blocked on monitor enter
 114      *
 115      *   RUNNING -> WAITING        // transitional state during wait on monitor
 116      *   WAITING -> WAITED         // waiting on monitor
 117      *    WAITED -> BLOCKED        // notified, waiting to be unblocked by monitor owner
 118      *    WAITED -> UNBLOCKED      // timed-out/interrupted
 119      *
 120      *       RUNNING -> TIMED_WAITING   // transition state during timed-waiting on monitor
 121      * TIMED_WAITING -> TIMED_WAITED    // timed-waiting on monitor
 122      *  TIMED_WAITED -> BLOCKED         // notified, waiting to be unblocked by monitor owner
 123      *  TIMED_WAITED -> UNBLOCKED       // timed-out/interrupted
 124      *
 125      *  RUNNING -> YIELDING        // Thread.yield
 126      * YIELDING -> YIELDED         // cont.yield successful, may be scheduled to continue
 127      * YIELDING -> RUNNING         // cont.yield failed
 128      *  YIELDED -> RUNNING         // continue execution after Thread.yield
 129      */
 130     private static final int NEW      = 0;
 131     private static final int STARTED  = 1;
 132     private static final int RUNNING  = 2;     // runnable-mounted
 133 
 134     // untimed and timed parking
 135     private static final int PARKING       = 3;
 136     private static final int PARKED        = 4;     // unmounted
 137     private static final int PINNED        = 5;     // mounted
 138     private static final int TIMED_PARKING = 6;
 139     private static final int TIMED_PARKED  = 7;     // unmounted
 140     private static final int TIMED_PINNED  = 8;     // mounted
 141     private static final int UNPARKED      = 9;     // unmounted but runnable
 142 
 143     // Thread.yield
 144     private static final int YIELDING = 10;
 145     private static final int YIELDED  = 11;         // unmounted but runnable
 146 
 147     // monitor enter
 148     private static final int BLOCKING  = 12;
 149     private static final int BLOCKED   = 13;        // unmounted
 150     private static final int UNBLOCKED = 14;        // unmounted but runnable
 151 
 152     // monitor wait/timed-wait
 153     private static final int WAITING       = 15;
 154     private static final int WAIT          = 16;    // waiting in Object.wait
 155     private static final int TIMED_WAITING = 17;
 156     private static final int TIMED_WAIT    = 18;    // waiting in timed-Object.wait
 157 
 158     private static final int TERMINATED = 99;  // final state
 159 
 160     // can be suspended from scheduling when unmounted
 161     private static final int SUSPENDED = 1 << 8;
 162 
 163     // parking permit
 164     private volatile boolean parkPermit;
 165 
 166     // used to mark thread as ready to be unblocked
 167     private volatile boolean unblocked;
 168 
 169     // used for Object.wait/notify
 170     private volatile boolean notified;
 171     private long waitTimeout;
 172     private volatile Future<?> waitTimeoutTask;
 173 
 174     // a positive value if "responsible thread" blocked on monitor enter, accessed by VM
 175     private volatile byte recheckInterval;
 176 
 177     // carrier thread when mounted, accessed by VM
 178     private volatile Thread carrierThread;
 179 
 180     // termination object when joining, created lazily if needed
 181     private volatile CountDownLatch termination;
 182 
 183     // has the value 1 when on the list of virtual threads waiting to be unblocked
 184     private volatile byte onWaitingList;
 185 
 186     // next virtual thread on the list of virtual threads waiting to be unblocked
 187     private volatile VirtualThread next;
 188 
 189     /**
 190      * Returns the continuation scope used for virtual threads.
 191      */
 192     static ContinuationScope continuationScope() {
 193         return VTHREAD_SCOPE;
 194     }
 195 
 196     /**
 197      * Creates a new {@code VirtualThread} to run the given task with the given
 198      * scheduler. If the given scheduler is {@code null} and the current thread
 199      * is a platform thread then the newly created virtual thread will use the
 200      * default scheduler. If given scheduler is {@code null} and the current
 201      * thread is a virtual thread then the current thread's scheduler is used.
 202      *
 203      * @param scheduler the scheduler or null
 204      * @param name thread name
 205      * @param characteristics characteristics
 206      * @param task the task to execute
 207      */
 208     VirtualThread(Executor scheduler, String name, int characteristics, Runnable task) {

 216                 scheduler = vparent.scheduler;
 217             } else {
 218                 scheduler = DEFAULT_SCHEDULER;
 219             }
 220         }
 221 
 222         this.scheduler = scheduler;
 223         this.cont = new VThreadContinuation(this, task);
 224         this.runContinuation = this::runContinuation;
 225     }
 226 
 227     /**
 228      * The continuation that a virtual thread executes.
 229      */
 230     private static class VThreadContinuation extends Continuation {
 231         VThreadContinuation(VirtualThread vthread, Runnable task) {
 232             super(VTHREAD_SCOPE, wrap(vthread, task));
 233         }
 234         @Override
 235         protected void onPinned(Continuation.Pinned reason) {
 236             // emit JFR event
 237             virtualThreadPinnedEvent(reason.reasonCode(), reason.reasonString());










 238         }
 239         private static Runnable wrap(VirtualThread vthread, Runnable task) {
 240             return new Runnable() {
 241                 @Hidden
 242                 public void run() {
 243                     vthread.run(task);
 244                 }
 245             };
 246         }
 247     }
 248 
 249     /**
 250      * Runs or continues execution on the current thread. The virtual thread is mounted
 251      * on the current thread before the task runs or continues. It unmounts when the
 252      * task completes or yields.
 253      */
 254     @ChangesCurrentThread
 255     private void runContinuation() {
 256         // the carrier must be a platform thread
 257         if (Thread.currentThread().isVirtual()) {
 258             throw new WrongThreadException();
 259         }
 260 
 261         // set state to RUNNING
 262         int initialState = state();
 263         if (initialState == STARTED || initialState == UNPARKED
 264                 || initialState == UNBLOCKED || initialState == YIELDED) {
 265             // newly started or continue after parking/blocking/Thread.yield
 266             if (!compareAndSetState(initialState, RUNNING)) {
 267                 return;
 268             }
 269             // consume parking permit when continuing after parking
 270             if (initialState == UNPARKED) {
 271                 setParkPermit(false);
 272             }
 273         } else {
 274             // not runnable
 275             return;
 276         }
 277 
 278         mount();
 279         try {
 280             cont.run();
 281         } finally {
 282             unmount();
 283             if (cont.isDone()) {
 284                 afterDone();

 286                 afterYield();
 287             }
 288         }
 289     }
 290 
 291     /**
 292      * Submits the runContinuation task to the scheduler. For the default scheduler,
 293      * and calling it on a worker thread, the task will be pushed to the local queue,
 294      * otherwise it will be pushed to an external submission queue.
 295      * @throws RejectedExecutionException
 296      */
 297     private void submitRunContinuation() {
 298         try {
 299             scheduler.execute(runContinuation);
 300         } catch (RejectedExecutionException ree) {
 301             submitFailed(ree);
 302             throw ree;
 303         }
 304     }
 305 
 306     /**
 307      * Submits the runContinuation task the scheduler. For the default scheduler, the task
 308      * will be pushed to an external submission queue.
 309      * @throws RejectedExecutionException
 310      */
 311     private void externalSubmitRunContinuation() {
 312         if (scheduler == DEFAULT_SCHEDULER
 313                 && currentCarrierThread() instanceof CarrierThread ct) {
 314             externalSubmitRunContinuation(ct.getPool());
 315         } else {
 316             submitRunContinuation();
 317         }
 318     }
 319 
 320     /**
 321      * Submits the runContinuation task to given scheduler with a lazy submit.
 322      * @throws RejectedExecutionException
 323      * @see ForkJoinPool#lazySubmit(ForkJoinTask)
 324      */
 325     private void lazySubmitRunContinuation(ForkJoinPool pool) {
 326         try {
 327             pool.lazySubmit(ForkJoinTask.adapt(runContinuation));
 328         } catch (RejectedExecutionException ree) {
 329             submitFailed(ree);
 330             throw ree;
 331         }
 332     }
 333 
 334     /**
 335      * Submits the runContinuation task to the given scheduler as an external submit.
 336      * @throws RejectedExecutionException
 337      * @see ForkJoinPool#externalSubmit(ForkJoinTask)
 338      */
 339     private void externalSubmitRunContinuation(ForkJoinPool pool) {

 417         } else if (carrier.isInterrupted()) {
 418             synchronized (interruptLock) {
 419                 // need to recheck interrupt status
 420                 if (!interrupted) {
 421                     carrier.clearInterrupt();
 422                 }
 423             }
 424         }
 425 
 426         // set Thread.currentThread() to return this virtual thread
 427         carrier.setCurrentThread(this);
 428     }
 429 
 430     /**
 431      * Unmounts this virtual thread from the carrier. On return, the
 432      * current thread is the current platform thread.
 433      */
 434     @ChangesCurrentThread
 435     @ReservedStackAccess
 436     private void unmount() {
 437         assert !Thread.holdsLock(interruptLock);
 438 
 439         // set Thread.currentThread() to return the platform thread
 440         Thread carrier = this.carrierThread;
 441         carrier.setCurrentThread(carrier);
 442 
 443         // break connection to carrier thread, synchronized with interrupt
 444         synchronized (interruptLock) {
 445             setCarrierThread(null);
 446         }
 447         carrier.clearInterrupt();
 448 
 449         // notify JVMTI after unmount
 450         notifyJvmtiUnmount(/*hide*/false);
 451     }
 452 
 453     /**
 454      * Sets the current thread to the current carrier thread.
 455      */
 456     @ChangesCurrentThread
 457     @JvmtiMountTransition
 458     private void switchToCarrierThread() {
 459         notifyJvmtiHideFrames(true);
 460         Thread carrier = this.carrierThread;
 461         assert Thread.currentThread() == this
 462                 && carrier == Thread.currentCarrierThread();
 463         carrier.setCurrentThread(carrier);
 464         setLockId(this.threadId()); // keep lockid of vthread
 465     }
 466 
 467     /**
 468      * Sets the current thread to the given virtual thread.
 469      */
 470     @ChangesCurrentThread
 471     @JvmtiMountTransition
 472     private void switchToVirtualThread(VirtualThread vthread) {
 473         Thread carrier = vthread.carrierThread;
 474         assert carrier == Thread.currentCarrierThread();
 475         carrier.setCurrentThread(vthread);
 476         notifyJvmtiHideFrames(false);
 477     }
 478 
 479     /**
 480      * Executes the given value returning task on the current carrier thread.
 481      */
 482     @ChangesCurrentThread
 483     <V> V executeOnCarrierThread(Callable<V> task) throws Exception {
 484         assert Thread.currentThread() == this;

 533                     submitRunContinuation();
 534                 }
 535 
 536             }
 537             return;
 538         }
 539 
 540         // Thread.yield
 541         if (s == YIELDING) {
 542             setState(YIELDED);
 543 
 544             // external submit if there are no tasks in the local task queue
 545             if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
 546                 externalSubmitRunContinuation(ct.getPool());
 547             } else {
 548                 submitRunContinuation();
 549             }
 550             return;
 551         }
 552 
 553         // blocking on monitorenter
 554         if (s == BLOCKING) {
 555             setState(BLOCKED);
 556 
 557             // may have been unblocked while blocking
 558             if (unblocked && compareAndSetState(BLOCKED, UNBLOCKED)) {
 559                 unblocked = false;
 560                 submitRunContinuation();
 561                 return;
 562             }
 563 
 564             // if thread is the designated responsible thread for a monitor then schedule
 565             // it to wakeup so that it can check and recover. See objectMonitor.cpp.
 566             int recheckInterval = this.recheckInterval;
 567             if (recheckInterval > 0 && state() == BLOCKED) {
 568                 assert recheckInterval >= 1 && recheckInterval <= 6;
 569                 // 4 ^ (recheckInterval - 1) = 1, 4, 16, ... 1024
 570                 long delay = 1 << (recheckInterval - 1) << (recheckInterval - 1);
 571                 Future<?> unblocker = schedule(this::unblock, delay, MILLISECONDS);
 572                 // cancel if unblocked while scheduling the unblock
 573                 if (state() != BLOCKED) {
 574                     unblocker.cancel(false);
 575                 }
 576             }
 577             return;
 578         }
 579 
 580         // Object.wait
 581         if (s == WAITING || s == TIMED_WAITING) {
 582             int newState = (s == WAITING) ? WAIT : TIMED_WAIT;
 583             setState(newState);
 584 
 585             // may have been notified while in transition to wait state
 586             if (notified && compareAndSetState(newState, BLOCKED)) {
 587                 // may have even been unblocked already
 588                 if (unblocked && compareAndSetState(BLOCKED, UNBLOCKED)) {
 589                     unblocked = false;
 590                     submitRunContinuation();
 591                 }
 592                 return;
 593             }
 594 
 595             // may have been interrupted while in transition to wait state
 596             if (interrupted && compareAndSetState(newState, UNBLOCKED)) {
 597                 submitRunContinuation();
 598                 return;
 599             }
 600 
 601             // for timed-wait need to schedule wakeup
 602             if (newState == TIMED_WAIT) {
 603                 assert waitTimeout > 0;
 604                 waitTimeoutTask = schedule(this::waitTimeoutExpired, waitTimeout, MILLISECONDS);
 605             }
 606             return;
 607         }
 608 
 609         assert false;
 610     }
 611 
 612     /**
 613      * Invoked after the continuation completes.
 614      */
 615     private void afterDone() {
 616         afterDone(true);
 617     }
 618 
 619     /**
 620      * Invoked after the continuation completes (or start failed). Sets the thread
 621      * state to TERMINATED and notifies anyone waiting for the thread to terminate.
 622      *
 623      * @param notifyContainer true if its container should be notified
 624      */
 625     private void afterDone(boolean notifyContainer) {
 626         assert carrierThread == null;
 627         setState(TERMINATED);
 628 

 652     @Override
 653     void start(ThreadContainer container) {
 654         if (!compareAndSetState(NEW, STARTED)) {
 655             throw new IllegalThreadStateException("Already started");
 656         }
 657 
 658         // bind thread to container
 659         assert threadContainer() == null;
 660         setThreadContainer(container);
 661 
 662         // start thread
 663         boolean addedToContainer = false;
 664         boolean started = false;
 665         try {
 666             container.onStart(this);  // may throw
 667             addedToContainer = true;
 668 
 669             // scoped values may be inherited
 670             inheritScopedValueBindings(container);
 671 
 672             // submit task to run thread, using externalSubmit if possible
 673             externalSubmitRunContinuation();
 674             started = true;
 675         } finally {
 676             if (!started) {
 677                 afterDone(addedToContainer);
 678             }
 679         }
 680     }
 681 
 682     @Override
 683     public void start() {
 684         start(ThreadContainers.root());
 685     }
 686 
 687     @Override
 688     public void run() {
 689         // do nothing
 690     }
 691 
 692     /**
 693      * Parks unless unparked or interrupted. If already unparked then the parking
 694      * permit is consumed and this method completes immediately (meaning it doesn't
 695      * yield). It also completes immediately if the interrupt status is set.
 696      */
 697     @Override
 698     void park() {
 699         assert Thread.currentThread() == this;
 700 
 701         // complete immediately if parking permit available or interrupted
 702         if (getAndSetParkPermit(false) || interrupted)
 703             return;
 704 
 705         // park the thread
 706         boolean yielded = false;
 707         setState(PARKING);
 708         try {
 709             yielded = yieldContinuation();  // may throw
 710         } finally {
 711             assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
 712             if (!yielded) {
 713                 assert state() == PARKING;

 756             }
 757 
 758             // park on carrier thread for remaining time when pinned
 759             if (!yielded) {
 760                 long remainingNanos = nanos - (System.nanoTime() - startTime);
 761                 parkOnCarrierThread(true, remainingNanos);
 762             }
 763         }
 764     }
 765 
 766     /**
 767      * Parks the current carrier thread up to the given waiting time or until
 768      * unparked or interrupted. If the virtual thread is interrupted then the
 769      * interrupt status will be propagated to the carrier thread.
 770      * @param timed true for a timed park, false for untimed
 771      * @param nanos the waiting time in nanoseconds
 772      */
 773     private void parkOnCarrierThread(boolean timed, long nanos) {
 774         assert state() == RUNNING;
 775 








 776         setState(timed ? TIMED_PINNED : PINNED);
 777         try {
 778             if (!parkPermit) {
 779                 if (!timed) {
 780                     U.park(false, 0);
 781                 } else if (nanos > 0) {
 782                     U.park(false, nanos);
 783                 }
 784             }
 785         } finally {
 786             setState(RUNNING);
 787         }
 788 
 789         // consume parking permit
 790         setParkPermit(false);








 791     }
 792 
 793     /**
 794      * jdk.VirtualThreadPinned is emitted by HotSpot VM when pinned. Call into VM to
 795      * emit event to avoid having a JFR event in Java with the same name (but different ID)
 796      * to events emitted by the VM.
 797      */
 798     private static native void virtualThreadPinnedEvent(int reason, String reasonString);
 799 
 800     /**
 801      * Schedule this virtual thread to be unparked after a given delay.
 802      */
 803     @ChangesCurrentThread
 804     private Future<?> scheduleUnpark(long nanos) {
 805         assert Thread.currentThread() == this;
 806         // need to switch to current carrier thread to avoid nested parking
 807         switchToCarrierThread();
 808         try {
 809             return schedule(this::unpark, nanos, NANOSECONDS);
 810         } finally {
 811             switchToVirtualThread(this);
 812         }
 813     }
 814 
 815     /**
 816      * Cancels a task if it has not completed.
 817      */
 818     @ChangesCurrentThread
 819     private void cancel(Future<?> future) {
 820         assert Thread.currentThread() == this;
 821         if (!future.isDone()) {
 822             // need to switch to current carrier thread to avoid nested parking
 823             switchToCarrierThread();
 824             try {
 825                 future.cancel(false);
 826             } finally {
 827                 switchToVirtualThread(this);
 828             }
 829         }
 830     }
 831 
 832     /**
 833      * Re-enables this virtual thread for scheduling. If this virtual thread is parked
 834      * then its task is scheduled to continue, otherwise its next call to {@code park} or
 835      * {@linkplain #parkNanos(long) parkNanos} is guaranteed not to block.

 836      * @throws RejectedExecutionException if the scheduler cannot accept a task
 837      */
 838     @Override
 839     @ChangesCurrentThread
 840     void unpark() {
 841         Thread currentThread = Thread.currentThread();
 842         if (!getAndSetParkPermit(true) && currentThread != this) {
 843             int s = state();
 844 
 845             // unparked while parked
 846             if ((s == PARKED || s == TIMED_PARKED) && compareAndSetState(s, UNPARKED)) {
 847                 if (currentThread instanceof VirtualThread vthread) {
 848                     vthread.switchToCarrierThread();
 849                     try {
 850                         submitRunContinuation();
 851                     } finally {
 852                         switchToVirtualThread(vthread);
 853                     }
 854                 } else {
 855                     submitRunContinuation();
 856                 }
 857                 return;
 858             }
 859 
 860             // unparked while parked when pinned
 861             if (s == PINNED || s == TIMED_PINNED) {
 862                 // unpark carrier thread when pinned
 863                 disableSuspendAndPreempt();
 864                 try {
 865                     synchronized (carrierThreadAccessLock()) {
 866                         Thread carrier = carrierThread;
 867                         if (carrier != null && ((s = state()) == PINNED || s == TIMED_PINNED)) {
 868                             U.unpark(carrier);
 869                         }
 870                     }
 871                 } finally {
 872                     enableSuspendAndPreempt();
 873                 }
 874                 return;
 875             }
 876         }
 877     }
 878 
 879     /**
 880      * Invoked by unblocker thread to unblock this virtual thread.
 881      */
 882     private void unblock() {
 883         assert !Thread.currentThread().isVirtual();
 884         unblocked = true;
 885         if (state() == BLOCKED && compareAndSetState(BLOCKED, UNBLOCKED)) {
 886             unblocked = false;
 887             submitRunContinuation();
 888         }
 889     }
 890 
 891     /**
 892      * Invoked by timer thread when wait timeout for virtual thread has expired.
 893      */
 894     private void waitTimeoutExpired() {
 895         assert !Thread.currentThread().isVirtual();
 896         for (;;) {
 897             int s = state();
 898             if (s == TIMED_WAIT) {
 899                 if (compareAndSetState(TIMED_WAIT, UNBLOCKED)) {
 900                     submitRunContinuation();
 901                     return;
 902                 }
 903             } else if (s == (TIMED_WAIT | SUSPENDED)) {
 904                 // need to retry when thread is resumed
 905                 Thread.yield();
 906             } else {
 907                 // notified or interrupted
 908                 return;
 909             }
 910         }
 911     }
 912 
 913     /**
 914      * Invoked by Object.wait to cancel wait timer.
 915      */
 916     void cancelWaitTimeout() {
 917         assert Thread.currentThread() == this;
 918         Future<?> timeoutTask = this.waitTimeoutTask;
 919         if (timeoutTask != null) {
 920             timeoutTask.cancel(false);
 921         }
 922     }
 923 
 924     /**
 925      * Attempts to yield the current virtual thread (Thread.yield).
 926      */
 927     void tryYield() {
 928         assert Thread.currentThread() == this;
 929         setState(YIELDING);
 930         boolean yielded = false;
 931         try {
 932             yielded = yieldContinuation();  // may throw
 933         } finally {
 934             assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
 935             if (!yielded) {
 936                 assert state() == YIELDING;
 937                 setState(RUNNING);
 938             }
 939         }
 940     }
 941 
 942     /**
 943      * Sleep the current thread for the given sleep time (in nanoseconds). If

 992         CountDownLatch termination = getTermination();
 993         if (state() == TERMINATED)
 994             return true;
 995 
 996         // wait for virtual thread to terminate
 997         if (nanos == 0) {
 998             termination.await();
 999         } else {
1000             boolean terminated = termination.await(nanos, NANOSECONDS);
1001             if (!terminated) {
1002                 // waiting time elapsed
1003                 return false;
1004             }
1005         }
1006         assert state() == TERMINATED;
1007         return true;
1008     }
1009 
1010     @Override
1011     void blockedOn(Interruptible b) {
1012         disableSuspendAndPreempt();
1013         try {
1014             super.blockedOn(b);
1015         } finally {
1016             enableSuspendAndPreempt();
1017         }
1018     }
1019 
1020     @Override
1021     @SuppressWarnings("removal")
1022     public void interrupt() {
1023         if (Thread.currentThread() != this) {
1024             checkAccess();
1025 
1026             // if current thread is a virtual thread then prevent it from being
1027             // suspended or unmounted when entering or holding interruptLock
1028             Interruptible blocker;
1029             disableSuspendAndPreempt();
1030             try {
1031                 synchronized (interruptLock) {
1032                     interrupted = true;
1033                     blocker = nioBlocker();
1034                     if (blocker != null) {
1035                         blocker.interrupt(this);
1036                     }
1037 
1038                     // interrupt carrier thread if mounted
1039                     Thread carrier = carrierThread;
1040                     if (carrier != null) carrier.setInterrupt();
1041                 }
1042             } finally {
1043                 enableSuspendAndPreempt();
1044             }
1045 
1046             // notify blocker after releasing interruptLock
1047             if (blocker != null) {
1048                 blocker.postInterrupt();
1049             }
1050 
1051             // make available parking permit, unpark thread if parked
1052             unpark();
1053 
1054             // if thread is waiting in Object.wait then schedule to try to reenter
1055             int s = state();
1056             if ((s == WAIT || s == TIMED_WAIT) && compareAndSetState(s, UNBLOCKED)) {
1057                 submitRunContinuation();
1058             }
1059 
1060         } else {
1061             interrupted = true;
1062             carrierThread.setInterrupt();
1063             setParkPermit(true);
1064         }

1065     }
1066 
1067     @Override
1068     public boolean isInterrupted() {
1069         return interrupted;
1070     }
1071 
1072     @Override
1073     boolean getAndClearInterrupt() {
1074         assert Thread.currentThread() == this;
1075         boolean oldValue = interrupted;
1076         if (oldValue) {
1077             disableSuspendAndPreempt();
1078             try {
1079                 synchronized (interruptLock) {
1080                     interrupted = false;
1081                     carrierThread.clearInterrupt();
1082                 }
1083             } finally {
1084                 enableSuspendAndPreempt();
1085             }
1086         }
1087         return oldValue;
1088     }
1089 
1090     @Override
1091     Thread.State threadState() {
1092         int s = state();
1093         switch (s & ~SUSPENDED) {
1094             case NEW:
1095                 return Thread.State.NEW;
1096             case STARTED:
1097                 // return NEW if thread container not yet set
1098                 if (threadContainer() == null) {
1099                     return Thread.State.NEW;
1100                 } else {
1101                     return Thread.State.RUNNABLE;
1102                 }
1103             case UNPARKED:
1104             case YIELDED:
1105                 // runnable, not mounted
1106                 return Thread.State.RUNNABLE;
1107             case UNBLOCKED:
1108                 // if designated responsible thread for monitor then thread is blocked
1109                 if (isResponsibleForMonitor()) {
1110                     return Thread.State.BLOCKED;
1111                 } else {
1112                     return Thread.State.RUNNABLE;
1113                 }
1114             case RUNNING:
1115                 // if designated responsible thread for monitor then thread is blocked
1116                 if (isResponsibleForMonitor()) {
1117                     return Thread.State.BLOCKED;
1118                 }
1119                 // if mounted then return state of carrier thread
1120                 if (Thread.currentThread() != this) {
1121                     disableSuspendAndPreempt();
1122                     try {
1123                         synchronized (carrierThreadAccessLock()) {
1124                             Thread carrierThread = this.carrierThread;
1125                             if (carrierThread != null) {
1126                                 return carrierThread.threadState();
1127                             }
1128                         }
1129                     } finally {
1130                         enableSuspendAndPreempt();
1131                     }


1132                 }
1133                 // runnable, mounted
1134                 return Thread.State.RUNNABLE;
1135             case PARKING:
1136             case TIMED_PARKING:
1137             case YIELDING:
1138             case WAITING:
1139             case TIMED_WAITING:
1140                 // runnable, in transition
1141                 return Thread.State.RUNNABLE;
1142             case PARKED:
1143             case PINNED:
1144             case WAIT:
1145                 return State.WAITING;
1146             case TIMED_PARKED:
1147             case TIMED_PINNED:
1148             case TIMED_WAIT:
1149                 return State.TIMED_WAITING;
1150             case BLOCKING:
1151             case BLOCKED:
1152                 return State.BLOCKED;
1153             case TERMINATED:
1154                 return Thread.State.TERMINATED;
1155             default:
1156                 throw new InternalError();
1157         }
1158     }
1159 
1160     /**
1161      * Returns true if thread is the designated responsible thread for a monitor.
1162      * See objectMonitor.cpp for details.
1163      */
1164     private boolean isResponsibleForMonitor() {
1165         return (recheckInterval > 0);
1166     }
1167 
1168     @Override
1169     boolean alive() {
1170         int s = state;
1171         return (s != NEW && s != TERMINATED);
1172     }
1173 
1174     @Override
1175     boolean isTerminated() {
1176         return (state == TERMINATED);
1177     }
1178 
1179     @Override
1180     StackTraceElement[] asyncGetStackTrace() {
1181         StackTraceElement[] stackTrace;
1182         do {
1183             stackTrace = (carrierThread != null)
1184                     ? super.asyncGetStackTrace()  // mounted
1185                     : tryGetStackTrace();         // unmounted
1186             if (stackTrace == null) {
1187                 Thread.yield();
1188             }
1189         } while (stackTrace == null);
1190         return stackTrace;
1191     }
1192 
1193     /**
1194      * Returns the stack trace for this virtual thread if it is unmounted.
1195      * Returns null if the thread is mounted or in transition.
1196      */
1197     private StackTraceElement[] tryGetStackTrace() {
1198         int initialState = state() & ~SUSPENDED;
1199         switch (initialState) {
1200             case NEW, STARTED, TERMINATED -> {
1201                 return new StackTraceElement[0];  // unmounted, empty stack
1202             }
1203             case RUNNING, PINNED, TIMED_PINNED -> {
1204                 return null;   // mounted
1205             }
1206             case PARKED, TIMED_PARKED, BLOCKED, WAIT, TIMED_WAIT -> {
1207                 // unmounted, not runnable
1208             }
1209             case UNPARKED, UNBLOCKED, YIELDED -> {
1210                 // unmounted, runnable
1211             }
1212             case PARKING, TIMED_PARKING, BLOCKING, YIELDING, WAITING, TIMED_WAITING -> {
1213                 return null;  // in transition
1214             }
1215             default -> throw new InternalError("" + initialState);
1216         }
1217 
1218         // thread is unmounted, prevent it from continuing
1219         int suspendedState = initialState | SUSPENDED;
1220         if (!compareAndSetState(initialState, suspendedState)) {
1221             return null;
1222         }
1223 
1224         // get stack trace and restore state
1225         StackTraceElement[] stack;
1226         try {
1227             stack = cont.getStackTrace();
1228         } finally {
1229             assert state == suspendedState;
1230             setState(initialState);
1231         }
1232         boolean resubmit = switch (initialState) {
1233             case UNPARKED, UNBLOCKED, YIELDED -> {
1234                 // resubmit as task may have run while suspended
1235                 yield true;
1236             }
1237             case PARKED, TIMED_PARKED -> {
1238                 // resubmit if unparked while suspended
1239                 yield parkPermit && compareAndSetState(initialState, UNPARKED);
1240             }
1241             case BLOCKED -> {
1242                 // resubmit if unblocked while suspended
1243                 yield unblocked && compareAndSetState(BLOCKED, UNBLOCKED);
1244             }
1245             case WAIT, TIMED_WAIT -> {
1246                 // resubmit if notified or interrupted while waiting (Object.wait)
1247                 yield (notified || interrupted) && compareAndSetState(initialState, UNBLOCKED);
1248             }
1249             default -> throw new InternalError();
1250         };
1251         if (resubmit) {
1252             submitRunContinuation();
1253         }
1254         return stack;
1255     }
1256 
1257     @Override
1258     public String toString() {
1259         StringBuilder sb = new StringBuilder("VirtualThread[#");
1260         sb.append(threadId());
1261         String name = getName();
1262         if (!name.isEmpty()) {
1263             sb.append(",");
1264             sb.append(name);
1265         }
1266         sb.append("]/");
1267 
1268         // add the carrier state and thread name when mounted
1269         boolean mounted;
1270         if (Thread.currentThread() == this) {
1271             mounted = appendCarrierInfo(sb);
1272         } else {
1273             disableSuspendAndPreempt();
1274             try {
1275                 synchronized (carrierThreadAccessLock()) {
1276                     mounted = appendCarrierInfo(sb);






1277                 }
1278             } finally {
1279                 enableSuspendAndPreempt();
1280             }
1281         }
1282 
1283         // add virtual thread state when not mounted
1284         if (!mounted) {
1285             String stateAsString = threadState().toString();
1286             sb.append(stateAsString.toLowerCase(Locale.ROOT));
1287         }
1288 
1289         return sb.toString();
1290     }
1291 
1292     /**
1293      * Appends the carrier state and thread name to the string buffer if mounted.
1294      * @return true if mounted, false if not mounted
1295      */
1296     private boolean appendCarrierInfo(StringBuilder sb) {
1297         assert Thread.currentThread() == this || Thread.holdsLock(carrierThreadAccessLock());
1298         Thread carrier = carrierThread;
1299         if (carrier != null) {
1300             String stateAsString = carrier.threadState().toString();
1301             sb.append(stateAsString.toLowerCase(Locale.ROOT));
1302             sb.append('@');
1303             sb.append(carrier.getName());
1304             return true;
1305         } else {
1306             return false;
1307         }
1308     }
1309 
1310     @Override
1311     public int hashCode() {
1312         return (int) threadId();
1313     }
1314 
1315     @Override
1316     public boolean equals(Object obj) {
1317         return obj == this;
1318     }
1319 
1320     /**
1321      * Returns the termination object, creating it if needed.
1322      */
1323     private CountDownLatch getTermination() {
1324         CountDownLatch termination = this.termination;
1325         if (termination == null) {
1326             termination = new CountDownLatch(1);
1327             if (!U.compareAndSetReference(this, TERMINATION, null, termination)) {
1328                 termination = this.termination;
1329             }
1330         }
1331         return termination;
1332     }
1333 
1334     /**
1335      * Returns the lock object to synchronize on when accessing carrierThread.
1336      * The lock prevents carrierThread from being reset to null during unmount.
1337      */
1338     private Object carrierThreadAccessLock() {
1339         // return interruptLock as unmount has to coordinate with interrupt
1340         return interruptLock;
1341     }
1342 
1343     /**
1344      * Disallow the current thread be suspended or preempted.
1345      */
1346     private void disableSuspendAndPreempt() {
1347         notifyJvmtiDisableSuspend(true);
1348         Continuation.pin();
1349     }
1350 
1351     /**
1352      * Allow the current thread be suspended or preempted.
1353      */
1354     private void enableSuspendAndPreempt() {
1355         Continuation.unpin();
1356         notifyJvmtiDisableSuspend(false);
1357     }
1358 
1359     // -- wrappers for get/set of state, parking permit, and carrier thread --
1360 
1361     private int state() {
1362         return state;  // volatile read
1363     }
1364 
1365     private void setState(int newValue) {
1366         state = newValue;  // volatile write
1367     }
1368 
1369     private boolean compareAndSetState(int expectedValue, int newValue) {
1370         return U.compareAndSetInt(this, STATE, expectedValue, newValue);
1371     }
1372 
1373     private boolean compareAndSetOnWaitingList(byte expectedValue, byte newValue) {
1374         return U.compareAndSetByte(this, ON_WAITING_LIST, expectedValue, newValue);
1375     }
1376 
1377     private void setParkPermit(boolean newValue) {
1378         if (parkPermit != newValue) {
1379             parkPermit = newValue;
1380         }
1381     }
1382 
1383     private boolean getAndSetParkPermit(boolean newValue) {
1384         if (parkPermit != newValue) {
1385             return U.getAndSetBoolean(this, PARK_PERMIT, newValue);
1386         } else {
1387             return newValue;
1388         }
1389     }
1390 
1391     private void setCarrierThread(Thread carrier) {
1392         // U.putReferenceRelease(this, CARRIER_THREAD, carrier);
1393         this.carrierThread = carrier;
1394     }
1395 
1396     @IntrinsicCandidate
1397     private static native void setLockId(long tid);
1398 
1399     // -- JVM TI support --
1400 
1401     @IntrinsicCandidate
1402     @JvmtiMountTransition
1403     private native void notifyJvmtiStart();
1404 
1405     @IntrinsicCandidate
1406     @JvmtiMountTransition
1407     private native void notifyJvmtiEnd();
1408 
1409     @IntrinsicCandidate
1410     @JvmtiMountTransition
1411     private native void notifyJvmtiMount(boolean hide);
1412 
1413     @IntrinsicCandidate
1414     @JvmtiMountTransition
1415     private native void notifyJvmtiUnmount(boolean hide);
1416 
1417     @IntrinsicCandidate
1418     @JvmtiMountTransition

1448             if (maxPoolSizeValue != null) {
1449                 maxPoolSize = Integer.parseInt(maxPoolSizeValue);
1450                 parallelism = Integer.min(parallelism, maxPoolSize);
1451             } else {
1452                 maxPoolSize = Integer.max(parallelism, 256);
1453             }
1454             if (minRunnableValue != null) {
1455                 minRunnable = Integer.parseInt(minRunnableValue);
1456             } else {
1457                 minRunnable = Integer.max(parallelism / 2, 1);
1458             }
1459             Thread.UncaughtExceptionHandler handler = (t, e) -> { };
1460             boolean asyncMode = true; // FIFO
1461             return new ForkJoinPool(parallelism, factory, handler, asyncMode,
1462                          0, maxPoolSize, minRunnable, pool -> true, 30, SECONDS);
1463         };
1464         return AccessController.doPrivileged(pa);
1465     }
1466 
1467     /**
1468      * Invoked by the VM for the Thread.vthread_scheduler diagnostic command.
1469      */
1470     private static byte[] printDefaultScheduler() {
1471         return String.format("%s%n", DEFAULT_SCHEDULER.toString())
1472                 .getBytes(StandardCharsets.UTF_8);
1473     }
1474 
1475     /**
1476      * Schedule a runnable task to run after a delay.
1477      */
1478     private static Future<?> schedule(Runnable command, long delay, TimeUnit unit) {
1479         long tid = Thread.currentThread().threadId();
1480         int index = (int) tid & (DELAYED_TASK_SCHEDULERS.length - 1);
1481         return DELAYED_TASK_SCHEDULERS[index].schedule(command, delay, unit);
1482     }
1483 
1484     /**
1485      * Creates the ScheduledThreadPoolExecutors used to execute delayed tasks.
1486      */
1487     private static ScheduledExecutorService[] createDelayedTaskSchedulers() {
1488         String propName = "jdk.virtualThreadScheduler.timerQueues";
1489         String propValue = GetPropertyAction.privilegedGetProperty(propName);
1490         int queueCount;
1491         if (propValue != null) {
1492             queueCount = Integer.parseInt(propValue);
1493             if (queueCount != Integer.highestOneBit(queueCount)) {
1494                 throw new RuntimeException("Value of " + propName + " must be power of 2");
1495             }
1496         } else {
1497             int ncpus = Runtime.getRuntime().availableProcessors();
1498             queueCount = Math.max(Integer.highestOneBit(ncpus / 4), 1);
1499         }
1500         var schedulers = new ScheduledExecutorService[queueCount];
1501         for (int i = 0; i < queueCount; i++) {
1502             ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor)
1503                 Executors.newScheduledThreadPool(1, task -> {
1504                     Thread t = InnocuousThread.newThread("VirtualThread-unparker", task);
1505                     t.setDaemon(true);
1506                     return t;
1507                 });
1508             stpe.setRemoveOnCancelPolicy(true);
1509             schedulers[i] = stpe;
1510         }
1511         return schedulers;





1512     }
1513 
1514     /**
1515      * Schedule virtual threads that are ready to be scheduled after they blocked on
1516      * monitor enter.

1517      */
1518     private static void unblockVirtualThreads() {
1519         while (true) {
1520             VirtualThread vthread = takeVirtualThreadListToUnblock();
1521             while (vthread != null) {
1522                 assert vthread.onWaitingList == 1;
1523                 VirtualThread nextThread = vthread.next;
1524 
1525                 // remove from list and unblock
1526                 vthread.next = null;
1527                 boolean changed = vthread.compareAndSetOnWaitingList((byte) 1, (byte) 0);
1528                 assert changed;
1529                 vthread.unblock();
1530 
1531                 vthread = nextThread;
1532             }
1533         }
1534     }
1535 
1536     /**
1537      * Retrieves the list of virtual threads that are waiting to be unblocked, waiting
1538      * if necessary until a list of one or more threads becomes available.
1539      */
1540     private static native VirtualThread takeVirtualThreadListToUnblock();
1541 
1542     static {
1543         var unblocker = InnocuousThread.newThread("VirtualThread-unblocker",
1544                 VirtualThread::unblockVirtualThreads);
1545         unblocker.setDaemon(true);
1546         unblocker.start();
1547     }
1548 }
< prev index next >