1 /*
   2  * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.lang;
  26 
  27 import java.lang.reflect.Constructor;
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.util.Arrays;
  31 import java.util.Locale;
  32 import java.util.Objects;
  33 import java.util.concurrent.Callable;
  34 import java.util.concurrent.CountDownLatch;
  35 import java.util.concurrent.Executor;
  36 import java.util.concurrent.Executors;
  37 import java.util.concurrent.ForkJoinPool;
  38 import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
  39 import java.util.concurrent.ForkJoinTask;
  40 import java.util.concurrent.ForkJoinWorkerThread;
  41 import java.util.concurrent.Future;
  42 import java.util.concurrent.RejectedExecutionException;
  43 import java.util.concurrent.ScheduledExecutorService;
  44 import java.util.concurrent.ScheduledThreadPoolExecutor;
  45 import java.util.concurrent.TimeUnit;
  46 import java.util.stream.Stream;
  47 import jdk.internal.event.VirtualThreadEndEvent;
  48 import jdk.internal.event.VirtualThreadStartEvent;
  49 import jdk.internal.event.VirtualThreadSubmitFailedEvent;
  50 import jdk.internal.misc.CarrierThread;
  51 import jdk.internal.misc.InnocuousThread;
  52 import jdk.internal.misc.Unsafe;
  53 import jdk.internal.vm.Continuation;
  54 import jdk.internal.vm.ContinuationScope;
  55 import jdk.internal.vm.StackableScope;
  56 import jdk.internal.vm.ThreadContainer;
  57 import jdk.internal.vm.ThreadContainers;
  58 import jdk.internal.vm.annotation.ChangesCurrentThread;
  59 import jdk.internal.vm.annotation.Hidden;
  60 import jdk.internal.vm.annotation.IntrinsicCandidate;
  61 import jdk.internal.vm.annotation.JvmtiMountTransition;
  62 import jdk.internal.vm.annotation.ReservedStackAccess;
  63 import sun.nio.ch.Interruptible;
  64 import sun.security.action.GetPropertyAction;
  65 import static java.util.concurrent.TimeUnit.*;
  66 
  67 /**
  68  * A thread that is scheduled by the Java virtual machine rather than the operating system.
  69  */
  70 final class VirtualThread extends BaseVirtualThread {
  71     private static final Unsafe U = Unsafe.getUnsafe();
  72     private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
  73     private static final Executor DEFAULT_SCHEDULER = createDefaultScheduler();
  74     private static final ScheduledExecutorService[] DELAYED_TASK_SCHEDULERS = createDelayedTaskSchedulers();
  75 
  76     private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state");
  77     private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
  78     private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
  79     private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");
  80     private static final long ON_WAITING_LIST = U.objectFieldOffset(VirtualThread.class, "onWaitingList");
  81 
  82     // scheduler and continuation
  83     private final Executor scheduler;
  84     private final Continuation cont;
  85     private final Runnable runContinuation;
  86 
  87     // virtual thread state, accessed by VM
  88     private volatile int state;
  89 
  90     /*
  91      * Virtual thread state transitions:
  92      *
  93      *      NEW -> STARTED         // Thread.start, schedule to run
  94      *  STARTED -> TERMINATED      // failed to start
  95      *  STARTED -> RUNNING         // first run
  96      *  RUNNING -> TERMINATED      // done
  97      *
  98      *  RUNNING -> PARKING         // Thread parking with LockSupport.park
  99      *  PARKING -> PARKED          // cont.yield successful, parked indefinitely
 100      *  PARKING -> PINNED          // cont.yield failed, parked indefinitely on carrier
 101      *   PARKED -> UNPARKED        // unparked, may be scheduled to continue
 102      *   PINNED -> RUNNING         // unparked, continue execution on same carrier
 103      * UNPARKED -> RUNNING         // continue execution after park
 104      *
 105      *       RUNNING -> TIMED_PARKING   // Thread parking with LockSupport.parkNanos
 106      * TIMED_PARKING -> TIMED_PARKED    // cont.yield successful, timed-parked
 107      * TIMED_PARKING -> TIMED_PINNED    // cont.yield failed, timed-parked on carrier
 108      *  TIMED_PARKED -> UNPARKED        // unparked, may be scheduled to continue
 109      *  TIMED_PINNED -> RUNNING         // unparked, continue execution on same carrier
 110      *
 111      *   RUNNING -> BLOCKING       // blocking on monitor enter
 112      *  BLOCKING -> BLOCKED        // blocked on monitor enter
 113      *   BLOCKED -> UNBLOCKED      // unblocked, may be scheduled to continue
 114      * UNBLOCKED -> RUNNING        // continue execution after blocked on monitor enter
 115      *
 116      *   RUNNING -> WAITING        // transitional state during wait on monitor
 117      *   WAITING -> WAITED         // waiting on monitor
 118      *    WAITED -> BLOCKED        // notified, waiting to be unblocked by monitor owner
 119      *    WAITED -> UNBLOCKED      // timed-out/interrupted
 120      *
 121      *       RUNNING -> TIMED_WAITING   // transition state during timed-waiting on monitor
 122      * TIMED_WAITING -> TIMED_WAITED    // timed-waiting on monitor
 123      *  TIMED_WAITED -> BLOCKED         // notified, waiting to be unblocked by monitor owner
 124      *  TIMED_WAITED -> UNBLOCKED       // timed-out/interrupted
 125      *
 126      *  RUNNING -> YIELDING        // Thread.yield
 127      * YIELDING -> YIELDED         // cont.yield successful, may be scheduled to continue
 128      * YIELDING -> RUNNING         // cont.yield failed
 129      *  YIELDED -> RUNNING         // continue execution after Thread.yield
 130      */
 131     private static final int NEW      = 0;
 132     private static final int STARTED  = 1;
 133     private static final int RUNNING  = 2;     // runnable-mounted
 134 
 135     // untimed and timed parking
 136     private static final int PARKING       = 3;
 137     private static final int PARKED        = 4;     // unmounted
 138     private static final int PINNED        = 5;     // mounted
 139     private static final int TIMED_PARKING = 6;
 140     private static final int TIMED_PARKED  = 7;     // unmounted
 141     private static final int TIMED_PINNED  = 8;     // mounted
 142     private static final int UNPARKED      = 9;     // unmounted but runnable
 143 
 144     // Thread.yield
 145     private static final int YIELDING = 10;
 146     private static final int YIELDED  = 11;         // unmounted but runnable
 147 
 148     // monitor enter
 149     private static final int BLOCKING  = 12;
 150     private static final int BLOCKED   = 13;        // unmounted
 151     private static final int UNBLOCKED = 14;        // unmounted but runnable
 152 
 153     // monitor wait/timed-wait
 154     private static final int WAITING       = 15;
 155     private static final int WAIT          = 16;    // waiting in Object.wait
 156     private static final int TIMED_WAITING = 17;
 157     private static final int TIMED_WAIT    = 18;    // waiting in timed-Object.wait
 158 
 159     private static final int TERMINATED = 99;  // final state
 160 
 161     // can be suspended from scheduling when unmounted
 162     private static final int SUSPENDED = 1 << 8;
 163 
 164     // parking permit
 165     private volatile boolean parkPermit;
 166 
 167     // used to mark thread as ready to be unblocked
 168     private volatile boolean unblocked;
 169 
 170     // notified by Object.notify/notifyAll while waiting in Object.wait
 171     private volatile boolean notified;
 172 
 173     // timed-wait support
 174     private long waitTimeout;
 175     private byte timedWaitNonce;
 176     private volatile Future<?> waitTimeoutTask;
 177 
 178     // a positive value if "responsible thread" blocked on monitor enter, accessed by VM
 179     private volatile byte recheckInterval;
 180 
 181     // carrier thread when mounted, accessed by VM
 182     private volatile Thread carrierThread;
 183 
 184     // termination object when joining, created lazily if needed
 185     private volatile CountDownLatch termination;
 186 
 187     // has the value 1 when on the list of virtual threads waiting to be unblocked
 188     private volatile byte onWaitingList;
 189 
 190     // next virtual thread on the list of virtual threads waiting to be unblocked
 191     private volatile VirtualThread next;
 192 
 193     /**
 194      * Returns the default scheduler.
 195      */
 196     static Executor defaultScheduler() {
 197         return DEFAULT_SCHEDULER;
 198     }
 199 
 200     /**
 201      * Returns a stream of the delayed task schedulers used to support timed operations.
 202      */
 203     static Stream<ScheduledExecutorService> delayedTaskSchedulers() {
 204         return Arrays.stream(DELAYED_TASK_SCHEDULERS);
 205     }
 206 
 207     /**
 208      * Returns the continuation scope used for virtual threads.
 209      */
 210     static ContinuationScope continuationScope() {
 211         return VTHREAD_SCOPE;
 212     }
 213 
 214     /**
 215      * Creates a new {@code VirtualThread} to run the given task with the given
 216      * scheduler. If the given scheduler is {@code null} and the current thread
 217      * is a platform thread then the newly created virtual thread will use the
 218      * default scheduler. If given scheduler is {@code null} and the current
 219      * thread is a virtual thread then the current thread's scheduler is used.
 220      *
 221      * @param scheduler the scheduler or null
 222      * @param name thread name
 223      * @param characteristics characteristics
 224      * @param task the task to execute
 225      */
 226     VirtualThread(Executor scheduler, String name, int characteristics, Runnable task) {
 227         super(name, characteristics, /*bound*/ false);
 228         Objects.requireNonNull(task);
 229 
 230         // choose scheduler if not specified
 231         if (scheduler == null) {
 232             Thread parent = Thread.currentThread();
 233             if (parent instanceof VirtualThread vparent) {
 234                 scheduler = vparent.scheduler;
 235             } else {
 236                 scheduler = DEFAULT_SCHEDULER;
 237             }
 238         }
 239 
 240         this.scheduler = scheduler;
 241         this.cont = new VThreadContinuation(this, task);
 242         this.runContinuation = this::runContinuation;
 243     }
 244 
 245     /**
 246      * The continuation that a virtual thread executes.
 247      */
 248     private static class VThreadContinuation extends Continuation {
 249         VThreadContinuation(VirtualThread vthread, Runnable task) {
 250             super(VTHREAD_SCOPE, wrap(vthread, task));
 251         }
 252         @Override
 253         protected void onPinned(Continuation.Pinned reason) {
 254             // emit JFR event
 255             virtualThreadPinnedEvent(reason.reasonCode(), reason.reasonString());
 256         }
 257         private static Runnable wrap(VirtualThread vthread, Runnable task) {
 258             return new Runnable() {
 259                 @Hidden
 260                 public void run() {
 261                     vthread.run(task);
 262                 }
 263             };
 264         }
 265     }
 266 
 267     /**
 268      * Runs or continues execution on the current thread. The virtual thread is mounted
 269      * on the current thread before the task runs or continues. It unmounts when the
 270      * task completes or yields.
 271      */
 272     @ChangesCurrentThread // allow mount/unmount to be inlined
 273     private void runContinuation() {
 274         // the carrier must be a platform thread
 275         if (Thread.currentThread().isVirtual()) {
 276             throw new WrongThreadException();
 277         }
 278 
 279         // set state to RUNNING
 280         int initialState = state();
 281         if (initialState == STARTED || initialState == UNPARKED
 282                 || initialState == UNBLOCKED || initialState == YIELDED) {
 283             // newly started or continue after parking/blocking/Thread.yield
 284             if (!compareAndSetState(initialState, RUNNING)) {
 285                 return;
 286             }
 287             // consume parking permit when continuing after parking
 288             if (initialState == UNPARKED) {
 289                 setParkPermit(false);
 290             }
 291         } else {
 292             // not runnable
 293             return;
 294         }
 295 
 296         mount();
 297         try {
 298             cont.run();
 299         } finally {
 300             unmount();
 301             if (cont.isDone()) {
 302                 afterDone();
 303             } else {
 304                 afterYield();
 305             }
 306         }
 307     }
 308 
 309     /**
 310      * Submits the runContinuation task to the scheduler. For the default scheduler,
 311      * and calling it on a worker thread, the task will be pushed to the local queue,
 312      * otherwise it will be pushed to an external submission queue.
 313      * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
 314      * @param retryOnOOME to retry indefinitely if OutOfMemoryError is thrown
 315      * @throws RejectedExecutionException
 316      */
 317     @ChangesCurrentThread
 318     private void submitRunContinuation(boolean retryOnOOME) {
 319         boolean done = false;
 320         while (!done) {
 321             try {
 322                 // The scheduler's execute method is invoked in the context of the
 323                 // carrier thread. For the default scheduler this ensures that the
 324                 // current thread is a ForkJoinWorkerThread so the task will be pushed
 325                 // to the local queue. For other schedulers, it avoids deadlock that
 326                 // would arise due to platform and virtual threads contenting for a
 327                 // lock on the scheduler's submission queue.
 328                 if (currentThread() instanceof VirtualThread vthread) {
 329                     vthread.switchToCarrierThread();
 330                     try {
 331                         scheduler.execute(runContinuation);
 332                     } finally {
 333                         switchToVirtualThread(vthread);
 334                     }
 335                 } else {
 336                     scheduler.execute(runContinuation);
 337                 }
 338                 done = true;
 339             } catch (RejectedExecutionException ree) {
 340                 submitFailed(ree);
 341                 throw ree;
 342             } catch (OutOfMemoryError e) {
 343                 if (retryOnOOME) {
 344                     U.park(false, 100_000_000); // 100ms
 345                 } else {
 346                     throw e;
 347                 }
 348             }
 349         }
 350     }
 351 
 352     /**
 353      * Submits the runContinuation task to given scheduler with a lazy submit.
 354      * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
 355      * @throws RejectedExecutionException
 356      * @see ForkJoinPool#lazySubmit(ForkJoinTask)
 357      */
 358     private void lazySubmitRunContinuation(ForkJoinPool pool) {
 359         assert Thread.currentThread() instanceof CarrierThread;
 360         try {
 361             pool.lazySubmit(ForkJoinTask.adapt(runContinuation));
 362         } catch (RejectedExecutionException ree) {
 363             submitFailed(ree);
 364             throw ree;
 365         } catch (OutOfMemoryError e) {
 366             submitRunContinuation();
 367         }
 368     }
 369 
 370     /**
 371      * Submits the runContinuation task to the given scheduler as an external submit.
 372      * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
 373      * @throws RejectedExecutionException
 374      * @see ForkJoinPool#externalSubmit(ForkJoinTask)
 375      */
 376     private void externalSubmitRunContinuation(ForkJoinPool pool) {
 377         assert Thread.currentThread() instanceof CarrierThread;
 378         try {
 379             pool.externalSubmit(ForkJoinTask.adapt(runContinuation));
 380         } catch (RejectedExecutionException ree) {
 381             submitFailed(ree);
 382             throw ree;
 383         } catch (OutOfMemoryError e) {
 384             submitRunContinuation();
 385         }
 386     }
 387 
 388     /**
 389      * Submits the runContinuation task to the scheduler. For the default scheduler,
 390      * and calling it on a worker thread, the task will be pushed to the local queue,
 391      * otherwise it will be pushed to an external submission queue.
 392      * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
 393      * @throws RejectedExecutionException
 394      */
 395     private void submitRunContinuation() {
 396         submitRunContinuation(true);
 397     }
 398 
 399     /**
 400      * Submits the runContinuation task the scheduler. For the default scheduler, and
 401      * calling it a virtual thread that uses the default scheduler, the task will be
 402      * pushed to an external submission queue. This method may throw OutOfMemoryError.
 403      * @throws RejectedExecutionException
 404      * @throws OutOfMemoryError
 405      */
 406     private void externalSubmitRunContinuationOrThrow() {
 407         if (scheduler == DEFAULT_SCHEDULER
 408                 && currentCarrierThread() instanceof CarrierThread ct) {
 409             try {
 410                 ct.getPool().externalSubmit(ForkJoinTask.adapt(runContinuation));
 411             } catch (RejectedExecutionException ree) {
 412                 submitFailed(ree);
 413                 throw ree;
 414             }
 415         } else {
 416             submitRunContinuation(false);
 417         }
 418     }
 419 
 420     /**
 421      * If enabled, emits a JFR VirtualThreadSubmitFailedEvent.
 422      */
 423     private void submitFailed(RejectedExecutionException ree) {
 424         var event = new VirtualThreadSubmitFailedEvent();
 425         if (event.isEnabled()) {
 426             event.javaThreadId = threadId();
 427             event.exceptionMessage = ree.getMessage();
 428             event.commit();
 429         }
 430     }
 431 
 432     /**
 433      * Runs a task in the context of this virtual thread.
 434      */
 435     private void run(Runnable task) {
 436         assert Thread.currentThread() == this && state == RUNNING;
 437 
 438         // notify JVMTI, may post VirtualThreadStart event
 439         notifyJvmtiStart();
 440 
 441         // emit JFR event if enabled
 442         if (VirtualThreadStartEvent.isTurnedOn()) {
 443             var event = new VirtualThreadStartEvent();
 444             event.javaThreadId = threadId();
 445             event.commit();
 446         }
 447 
 448         Object bindings = Thread.scopedValueBindings();
 449         try {
 450             runWith(bindings, task);
 451         } catch (Throwable exc) {
 452             dispatchUncaughtException(exc);
 453         } finally {
 454             try {
 455                 // pop any remaining scopes from the stack, this may block
 456                 StackableScope.popAll();
 457 
 458                 // emit JFR event if enabled
 459                 if (VirtualThreadEndEvent.isTurnedOn()) {
 460                     var event = new VirtualThreadEndEvent();
 461                     event.javaThreadId = threadId();
 462                     event.commit();
 463                 }
 464 
 465             } finally {
 466                 // notify JVMTI, may post VirtualThreadEnd event
 467                 notifyJvmtiEnd();
 468             }
 469         }
 470     }
 471 
 472     /**
 473      * Mounts this virtual thread onto the current platform thread. On
 474      * return, the current thread is the virtual thread.
 475      */
 476     @ChangesCurrentThread
 477     @ReservedStackAccess
 478     private void mount() {
 479         // notify JVMTI before mount
 480         notifyJvmtiMount(/*hide*/true);
 481 
 482         // sets the carrier thread
 483         Thread carrier = Thread.currentCarrierThread();
 484         setCarrierThread(carrier);
 485 
 486         // sync up carrier thread interrupt status if needed
 487         if (interrupted) {
 488             carrier.setInterrupt();
 489         } else if (carrier.isInterrupted()) {
 490             synchronized (interruptLock) {
 491                 // need to recheck interrupt status
 492                 if (!interrupted) {
 493                     carrier.clearInterrupt();
 494                 }
 495             }
 496         }
 497 
 498         // set Thread.currentThread() to return this virtual thread
 499         carrier.setCurrentThread(this);
 500     }
 501 
 502     /**
 503      * Unmounts this virtual thread from the carrier. On return, the
 504      * current thread is the current platform thread.
 505      */
 506     @ChangesCurrentThread
 507     @ReservedStackAccess
 508     private void unmount() {
 509         assert !Thread.holdsLock(interruptLock);
 510 
 511         // set Thread.currentThread() to return the platform thread
 512         Thread carrier = this.carrierThread;
 513         carrier.setCurrentThread(carrier);
 514 
 515         // break connection to carrier thread, synchronized with interrupt
 516         synchronized (interruptLock) {
 517             setCarrierThread(null);
 518         }
 519         carrier.clearInterrupt();
 520 
 521         // notify JVMTI after unmount
 522         notifyJvmtiUnmount(/*hide*/false);
 523     }
 524 
 525     /**
 526      * Sets the current thread to the current carrier thread.
 527      */
 528     @ChangesCurrentThread
 529     @JvmtiMountTransition
 530     private void switchToCarrierThread() {
 531         notifyJvmtiHideFrames(true);
 532         Thread carrier = this.carrierThread;
 533         assert Thread.currentThread() == this
 534                 && carrier == Thread.currentCarrierThread();
 535         carrier.setCurrentThread(carrier);
 536         setLockId(this.threadId()); // keep lockid of vthread
 537     }
 538 
 539     /**
 540      * Sets the current thread to the given virtual thread.
 541      */
 542     @ChangesCurrentThread
 543     @JvmtiMountTransition
 544     private static void switchToVirtualThread(VirtualThread vthread) {
 545         Thread carrier = vthread.carrierThread;
 546         assert carrier == Thread.currentCarrierThread();
 547         carrier.setCurrentThread(vthread);
 548         notifyJvmtiHideFrames(false);
 549     }
 550 
 551     /**
 552      * Executes the given value returning task on the current carrier thread.
 553      */
 554     @ChangesCurrentThread
 555     <V> V executeOnCarrierThread(Callable<V> task) throws Exception {
 556         assert Thread.currentThread() == this;
 557         switchToCarrierThread();
 558         try {
 559             return task.call();
 560         } finally {
 561             switchToVirtualThread(this);
 562         }
 563      }
 564 
 565     /**
 566      * Invokes Continuation.yield, notifying JVMTI (if enabled) to hide frames until
 567      * the continuation continues.
 568      */
 569     @Hidden
 570     private boolean yieldContinuation() {
 571         notifyJvmtiUnmount(/*hide*/true);
 572         try {
 573             return Continuation.yield(VTHREAD_SCOPE);
 574         } finally {
 575             notifyJvmtiMount(/*hide*/false);
 576         }
 577     }
 578 
 579     /**
 580      * Invoked after the continuation yields. If parking then it sets the state
 581      * and also re-submits the task to continue if unparked while parking.
 582      * If yielding due to Thread.yield then it just submits the task to continue.
 583      */
 584     private void afterYield() {
 585         assert carrierThread == null;
 586 
 587         // re-adjust parallelism if the virtual thread yielded when compensating
 588         if (currentThread() instanceof CarrierThread ct) {
 589             ct.endBlocking();
 590         }
 591 
 592         int s = state();
 593 
 594         // LockSupport.park/parkNanos
 595         if (s == PARKING || s == TIMED_PARKING) {
 596             int newState = (s == PARKING) ? PARKED : TIMED_PARKED;
 597             setState(newState);
 598 
 599             // may have been unparked while parking
 600             if (parkPermit && compareAndSetState(newState, UNPARKED)) {
 601                 // lazy submit to continue on the current thread as carrier if possible
 602                 if (currentThread() instanceof CarrierThread ct) {
 603                     lazySubmitRunContinuation(ct.getPool());
 604                 } else {
 605                     submitRunContinuation();
 606                 }
 607             }
 608             return;
 609         }
 610 
 611         // Thread.yield
 612         if (s == YIELDING) {
 613             setState(YIELDED);
 614 
 615             // external submit if there are no tasks in the local task queue
 616             if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
 617                 externalSubmitRunContinuation(ct.getPool());
 618             } else {
 619                 submitRunContinuation();
 620             }
 621             return;
 622         }
 623 
 624         // blocking on monitorenter
 625         if (s == BLOCKING) {
 626             setState(BLOCKED);
 627 
 628             // may have been unblocked while blocking
 629             if (unblocked && compareAndSetState(BLOCKED, UNBLOCKED)) {
 630                 unblocked = false;
 631                 submitRunContinuation();
 632                 return;
 633             }
 634 
 635             // if thread is the designated responsible thread for a monitor then schedule
 636             // it to wakeup so that it can check and recover. See objectMonitor.cpp.
 637             int recheckInterval = this.recheckInterval;
 638             if (recheckInterval > 0) {
 639                 assert recheckInterval >= 1 && recheckInterval <= 6;
 640                 // 4 ^ (recheckInterval - 1) = 1, 4, 16, ... 1024
 641                 long delay = 1 << (recheckInterval - 1) << (recheckInterval - 1);
 642                 schedule(this::unblock, delay, MILLISECONDS);
 643             }
 644             return;
 645         }
 646 
 647         // Object.wait
 648         if (s == WAITING || s == TIMED_WAITING) {
 649             byte nonce;
 650             int newState;
 651             if (s == WAITING) {
 652                 nonce = 0;  // not used
 653                 setState(newState = WAIT);
 654             } else {
 655                 // synchronize with timeout task (previous timed-wait may be running)
 656                 synchronized (timedWaitLock()) {
 657                     nonce = ++timedWaitNonce;
 658                     setState(newState = TIMED_WAIT);
 659                 }
 660             }
 661 
 662             // may have been notified while in transition to wait state
 663             if (notified && compareAndSetState(newState, BLOCKED)) {
 664                 // may have even been unblocked already
 665                 if (unblocked && compareAndSetState(BLOCKED, UNBLOCKED)) {
 666                     unblocked = false;
 667                     submitRunContinuation();
 668                 }
 669                 return;
 670             }
 671 
 672             // may have been interrupted while in transition to wait state
 673             if (interrupted && compareAndSetState(newState, UNBLOCKED)) {
 674                 submitRunContinuation();
 675                 return;
 676             }
 677 
 678             // schedule wakeup
 679             if (newState == TIMED_WAIT) {
 680                 assert waitTimeout > 0;
 681                 waitTimeoutTask = schedule(() -> waitTimeoutExpired(nonce), waitTimeout, MILLISECONDS);
 682             }
 683             return;
 684         }
 685 
 686         assert false;
 687     }
 688 
 689     /**
 690      * Invoked after the continuation completes.
 691      */
 692     private void afterDone() {
 693         afterDone(true);
 694     }
 695 
 696     /**
 697      * Invoked after the continuation completes (or start failed). Sets the thread
 698      * state to TERMINATED and notifies anyone waiting for the thread to terminate.
 699      *
 700      * @param notifyContainer true if its container should be notified
 701      */
 702     private void afterDone(boolean notifyContainer) {
 703         assert carrierThread == null;
 704         setState(TERMINATED);
 705 
 706         // notify anyone waiting for this virtual thread to terminate
 707         CountDownLatch termination = this.termination;
 708         if (termination != null) {
 709             assert termination.getCount() == 1;
 710             termination.countDown();
 711         }
 712 
 713         // notify container
 714         if (notifyContainer) {
 715             threadContainer().onExit(this);
 716         }
 717 
 718         // clear references to thread locals
 719         clearReferences();
 720     }
 721 
 722     /**
 723      * Schedules this {@code VirtualThread} to execute.
 724      *
 725      * @throws IllegalStateException if the container is shutdown or closed
 726      * @throws IllegalThreadStateException if the thread has already been started
 727      * @throws RejectedExecutionException if the scheduler cannot accept a task
 728      */
 729     @Override
 730     void start(ThreadContainer container) {
 731         if (!compareAndSetState(NEW, STARTED)) {
 732             throw new IllegalThreadStateException("Already started");
 733         }
 734 
 735         // bind thread to container
 736         assert threadContainer() == null;
 737         setThreadContainer(container);
 738 
 739         // start thread
 740         boolean addedToContainer = false;
 741         boolean started = false;
 742         try {
 743             container.onStart(this);  // may throw
 744             addedToContainer = true;
 745 
 746             // scoped values may be inherited
 747             inheritScopedValueBindings(container);
 748 
 749             // submit task to run thread, using externalSubmit if possible
 750             externalSubmitRunContinuationOrThrow();
 751             started = true;
 752         } finally {
 753             if (!started) {
 754                 afterDone(addedToContainer);
 755             }
 756         }
 757     }
 758 
 759     @Override
 760     public void start() {
 761         start(ThreadContainers.root());
 762     }
 763 
 764     @Override
 765     public void run() {
 766         // do nothing
 767     }
 768 
 769     /**
 770      * Parks unless unparked or interrupted. If already unparked then the parking
 771      * permit is consumed and this method completes immediately (meaning it doesn't
 772      * yield). It also completes immediately if the interrupt status is set.
 773      */
 774     @Override
 775     void park() {
 776         assert Thread.currentThread() == this;
 777 
 778         // complete immediately if parking permit available or interrupted
 779         if (getAndSetParkPermit(false) || interrupted)
 780             return;
 781 
 782         // park the thread
 783         boolean yielded = false;
 784         setState(PARKING);
 785         try {
 786             yielded = yieldContinuation();  // may throw
 787         } finally {
 788             assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
 789             if (!yielded) {
 790                 assert state() == PARKING;
 791                 setState(RUNNING);
 792             }
 793         }
 794 
 795         // park on the carrier thread when pinned
 796         if (!yielded) {
 797             parkOnCarrierThread(false, 0);
 798         }
 799     }
 800 
 801     /**
 802      * Parks up to the given waiting time or until unparked or interrupted.
 803      * If already unparked then the parking permit is consumed and this method
 804      * completes immediately (meaning it doesn't yield). It also completes immediately
 805      * if the interrupt status is set or the waiting time is {@code <= 0}.
 806      *
 807      * @param nanos the maximum number of nanoseconds to wait.
 808      */
 809     @Override
 810     void parkNanos(long nanos) {
 811         assert Thread.currentThread() == this;
 812 
 813         // complete immediately if parking permit available or interrupted
 814         if (getAndSetParkPermit(false) || interrupted)
 815             return;
 816 
 817         // park the thread for the waiting time
 818         if (nanos > 0) {
 819             long startTime = System.nanoTime();
 820 
 821             boolean yielded = false;
 822             Future<?> unparker = scheduleUnpark(nanos);  // may throw OOME
 823             setState(TIMED_PARKING);
 824             try {
 825                 yielded = yieldContinuation();  // may throw
 826             } finally {
 827                 assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
 828                 if (!yielded) {
 829                     assert state() == TIMED_PARKING;
 830                     setState(RUNNING);
 831                 }
 832                 cancel(unparker);
 833             }
 834 
 835             // park on carrier thread for remaining time when pinned
 836             if (!yielded) {
 837                 long remainingNanos = nanos - (System.nanoTime() - startTime);
 838                 parkOnCarrierThread(true, remainingNanos);
 839             }
 840         }
 841     }
 842 
 843     /**
 844      * Parks the current carrier thread up to the given waiting time or until
 845      * unparked or interrupted. If the virtual thread is interrupted then the
 846      * interrupt status will be propagated to the carrier thread.
 847      * @param timed true for a timed park, false for untimed
 848      * @param nanos the waiting time in nanoseconds
 849      */
 850     private void parkOnCarrierThread(boolean timed, long nanos) {
 851         assert state() == RUNNING;
 852 
 853         setState(timed ? TIMED_PINNED : PINNED);
 854         try {
 855             if (!parkPermit) {
 856                 if (!timed) {
 857                     U.park(false, 0);
 858                 } else if (nanos > 0) {
 859                     U.park(false, nanos);
 860                 }
 861             }
 862         } finally {
 863             setState(RUNNING);
 864         }
 865 
 866         // consume parking permit
 867         setParkPermit(false);
 868     }
 869 
 870     /**
 871      * jdk.VirtualThreadPinned is emitted by HotSpot VM when pinned. Call into VM to
 872      * emit event to avoid having a JFR event in Java with the same name (but different ID)
 873      * to events emitted by the VM.
 874      */
 875     private static native void virtualThreadPinnedEvent(int reason, String reasonString);
 876 
 877     /**
 878      * Schedule this virtual thread to be unparked after a given delay.
 879      */
 880     @ChangesCurrentThread
 881     private Future<?> scheduleUnpark(long nanos) {
 882         assert Thread.currentThread() == this;
 883         // need to switch to current carrier thread to avoid nested parking
 884         switchToCarrierThread();
 885         try {
 886             return schedule(this::unpark, nanos, NANOSECONDS);
 887         } finally {
 888             switchToVirtualThread(this);
 889         }
 890     }
 891 
 892     /**
 893      * Cancels a task if it has not completed.
 894      */
 895     @ChangesCurrentThread
 896     private void cancel(Future<?> future) {
 897         assert Thread.currentThread() == this;
 898         if (!future.isDone()) {
 899             // need to switch to current carrier thread to avoid nested parking
 900             switchToCarrierThread();
 901             try {
 902                 future.cancel(false);
 903             } finally {
 904                 switchToVirtualThread(this);
 905             }
 906         }
 907     }
 908 
 909     /**
 910      * Re-enables this virtual thread for scheduling. If this virtual thread is parked
 911      * then its task is scheduled to continue, otherwise its next call to {@code park} or
 912      * {@linkplain #parkNanos(long) parkNanos} is guaranteed not to block.
 913      * @throws RejectedExecutionException if the scheduler cannot accept a task
 914      */
 915     @Override
 916     void unpark() {
 917         if (!getAndSetParkPermit(true) && currentThread() != this) {
 918             int s = state();
 919 
 920             // unparked while parked
 921             if ((s == PARKED || s == TIMED_PARKED) && compareAndSetState(s, UNPARKED)) {
 922                 submitRunContinuation();
 923                 return;
 924             }
 925 
 926             // unparked while parked when pinned
 927             if (s == PINNED || s == TIMED_PINNED) {
 928                 // unpark carrier thread when pinned
 929                 disableSuspendAndPreempt();
 930                 try {
 931                     synchronized (carrierThreadAccessLock()) {
 932                         Thread carrier = carrierThread;
 933                         if (carrier != null && ((s = state()) == PINNED || s == TIMED_PINNED)) {
 934                             U.unpark(carrier);
 935                         }
 936                     }
 937                 } finally {
 938                     enableSuspendAndPreempt();
 939                 }
 940                 return;
 941             }
 942         }
 943     }
 944 
 945     /**
 946      * Invoked by unblocker thread to unblock this virtual thread.
 947      */
 948     private void unblock() {
 949         assert !Thread.currentThread().isVirtual();
 950         unblocked = true;
 951         if (state() == BLOCKED && compareAndSetState(BLOCKED, UNBLOCKED)) {
 952             unblocked = false;
 953             submitRunContinuation();
 954         }
 955     }
 956 
 957     /**
 958      * Invoked by timer thread when wait timeout for virtual thread has expired.
 959      * If the virtual thread is in timed-wait then this method will unblock the thread
 960      * and submit its task so that it continues and attempts to reenter the monitor.
 961      * This method does nothing if the thread has been woken by notify or interrupt.
 962      */
 963     private void waitTimeoutExpired(byte nounce) {
 964         assert !Thread.currentThread().isVirtual();
 965         for (;;) {
 966             boolean unblocked = false;
 967             synchronized (timedWaitLock()) {
 968                 if (nounce != timedWaitNonce) {
 969                     // this timeout task is for a past timed-wait
 970                     return;
 971                 }
 972                 int s = state();
 973                 if (s == TIMED_WAIT) {
 974                     unblocked = compareAndSetState(TIMED_WAIT, UNBLOCKED);
 975                 } else if (s != (TIMED_WAIT | SUSPENDED)) {
 976                     // notified or interrupted, no longer waiting
 977                     return;
 978                 }
 979             }
 980             if (unblocked) {
 981                 submitRunContinuation();
 982                 return;
 983             }
 984             // need to retry when thread is suspended in time-wait
 985             Thread.yield();
 986         }
 987     }
 988 
 989     /**
 990      * Invoked by Object.wait to cancel wait timer.
 991      */
 992     void cancelWaitTimeout() {
 993         assert Thread.currentThread() == this;
 994         Future<?> timeoutTask = this.waitTimeoutTask;
 995         if (timeoutTask != null) {
 996             timeoutTask.cancel(false);
 997         }
 998     }
 999 
1000     /**
1001      * Attempts to yield the current virtual thread (Thread.yield).
1002      */
1003     void tryYield() {
1004         assert Thread.currentThread() == this;
1005         setState(YIELDING);
1006         boolean yielded = false;
1007         try {
1008             yielded = yieldContinuation();  // may throw
1009         } finally {
1010             assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
1011             if (!yielded) {
1012                 assert state() == YIELDING;
1013                 setState(RUNNING);
1014             }
1015         }
1016     }
1017 
1018     /**
1019      * Sleep the current thread for the given sleep time (in nanoseconds). If
1020      * nanos is 0 then the thread will attempt to yield.
1021      *
1022      * @implNote This implementation parks the thread for the given sleeping time
1023      * and will therefore be observed in PARKED state during the sleep. Parking
1024      * will consume the parking permit so this method makes available the parking
1025      * permit after the sleep. This may be observed as a spurious, but benign,
1026      * wakeup when the thread subsequently attempts to park.
1027      *
1028      * @param nanos the maximum number of nanoseconds to sleep
1029      * @throws InterruptedException if interrupted while sleeping
1030      */
1031     void sleepNanos(long nanos) throws InterruptedException {
1032         assert Thread.currentThread() == this && nanos >= 0;
1033         if (getAndClearInterrupt())
1034             throw new InterruptedException();
1035         if (nanos == 0) {
1036             tryYield();
1037         } else {
1038             // park for the sleep time
1039             try {
1040                 long remainingNanos = nanos;
1041                 long startNanos = System.nanoTime();
1042                 while (remainingNanos > 0) {
1043                     parkNanos(remainingNanos);
1044                     if (getAndClearInterrupt()) {
1045                         throw new InterruptedException();
1046                     }
1047                     remainingNanos = nanos - (System.nanoTime() - startNanos);
1048                 }
1049             } finally {
1050                 // may have been unparked while sleeping
1051                 setParkPermit(true);
1052             }
1053         }
1054     }
1055 
1056     /**
1057      * Waits up to {@code nanos} nanoseconds for this virtual thread to terminate.
1058      * A timeout of {@code 0} means to wait forever.
1059      *
1060      * @throws InterruptedException if interrupted while waiting
1061      * @return true if the thread has terminated
1062      */
1063     boolean joinNanos(long nanos) throws InterruptedException {
1064         if (state() == TERMINATED)
1065             return true;
1066 
1067         // ensure termination object exists, then re-check state
1068         CountDownLatch termination = getTermination();
1069         if (state() == TERMINATED)
1070             return true;
1071 
1072         // wait for virtual thread to terminate
1073         if (nanos == 0) {
1074             termination.await();
1075         } else {
1076             boolean terminated = termination.await(nanos, NANOSECONDS);
1077             if (!terminated) {
1078                 // waiting time elapsed
1079                 return false;
1080             }
1081         }
1082         assert state() == TERMINATED;
1083         return true;
1084     }
1085 
1086     @Override
1087     void blockedOn(Interruptible b) {
1088         disableSuspendAndPreempt();
1089         try {
1090             super.blockedOn(b);
1091         } finally {
1092             enableSuspendAndPreempt();
1093         }
1094     }
1095 
1096     @Override
1097     @SuppressWarnings("removal")
1098     public void interrupt() {
1099         if (Thread.currentThread() != this) {
1100             checkAccess();
1101 
1102             // if current thread is a virtual thread then prevent it from being
1103             // suspended or unmounted when entering or holding interruptLock
1104             Interruptible blocker;
1105             disableSuspendAndPreempt();
1106             try {
1107                 synchronized (interruptLock) {
1108                     interrupted = true;
1109                     blocker = nioBlocker();
1110                     if (blocker != null) {
1111                         blocker.interrupt(this);
1112                     }
1113 
1114                     // interrupt carrier thread if mounted
1115                     Thread carrier = carrierThread;
1116                     if (carrier != null) carrier.setInterrupt();
1117                 }
1118             } finally {
1119                 enableSuspendAndPreempt();
1120             }
1121 
1122             // notify blocker after releasing interruptLock
1123             if (blocker != null) {
1124                 blocker.postInterrupt();
1125             }
1126 
1127             // make available parking permit, unpark thread if parked
1128             unpark();
1129 
1130             // if thread is waiting in Object.wait then schedule to try to reenter
1131             int s = state();
1132             if ((s == WAIT || s == TIMED_WAIT) && compareAndSetState(s, UNBLOCKED)) {
1133                 submitRunContinuation();
1134             }
1135 
1136         } else {
1137             interrupted = true;
1138             carrierThread.setInterrupt();
1139             setParkPermit(true);
1140         }
1141     }
1142 
1143     @Override
1144     public boolean isInterrupted() {
1145         return interrupted;
1146     }
1147 
1148     @Override
1149     boolean getAndClearInterrupt() {
1150         assert Thread.currentThread() == this;
1151         boolean oldValue = interrupted;
1152         if (oldValue) {
1153             disableSuspendAndPreempt();
1154             try {
1155                 synchronized (interruptLock) {
1156                     interrupted = false;
1157                     carrierThread.clearInterrupt();
1158                 }
1159             } finally {
1160                 enableSuspendAndPreempt();
1161             }
1162         }
1163         return oldValue;
1164     }
1165 
1166     @Override
1167     Thread.State threadState() {
1168         int s = state();
1169         switch (s & ~SUSPENDED) {
1170             case NEW:
1171                 return Thread.State.NEW;
1172             case STARTED:
1173                 // return NEW if thread container not yet set
1174                 if (threadContainer() == null) {
1175                     return Thread.State.NEW;
1176                 } else {
1177                     return Thread.State.RUNNABLE;
1178                 }
1179             case UNPARKED:
1180             case YIELDED:
1181                 // runnable, not mounted
1182                 return Thread.State.RUNNABLE;
1183             case UNBLOCKED:
1184                 // if designated responsible thread for monitor then thread is blocked
1185                 if (isResponsibleForMonitor()) {
1186                     return Thread.State.BLOCKED;
1187                 } else {
1188                     return Thread.State.RUNNABLE;
1189                 }
1190             case RUNNING:
1191                 // if designated responsible thread for monitor then thread is blocked
1192                 if (isResponsibleForMonitor()) {
1193                     return Thread.State.BLOCKED;
1194                 }
1195                 // if mounted then return state of carrier thread
1196                 if (Thread.currentThread() != this) {
1197                     disableSuspendAndPreempt();
1198                     try {
1199                         synchronized (carrierThreadAccessLock()) {
1200                             Thread carrierThread = this.carrierThread;
1201                             if (carrierThread != null) {
1202                                 return carrierThread.threadState();
1203                             }
1204                         }
1205                     } finally {
1206                         enableSuspendAndPreempt();
1207                     }
1208                 }
1209                 // runnable, mounted
1210                 return Thread.State.RUNNABLE;
1211             case PARKING:
1212             case TIMED_PARKING:
1213             case YIELDING:
1214             case WAITING:
1215             case TIMED_WAITING:
1216                 // runnable, in transition
1217                 return Thread.State.RUNNABLE;
1218             case PARKED:
1219             case PINNED:
1220             case WAIT:
1221                 return State.WAITING;
1222             case TIMED_PARKED:
1223             case TIMED_PINNED:
1224             case TIMED_WAIT:
1225                 return State.TIMED_WAITING;
1226             case BLOCKING:
1227             case BLOCKED:
1228                 return State.BLOCKED;
1229             case TERMINATED:
1230                 return Thread.State.TERMINATED;
1231             default:
1232                 throw new InternalError();
1233         }
1234     }
1235 
1236     /**
1237      * Returns true if thread is the designated responsible thread for a monitor.
1238      * See objectMonitor.cpp for details.
1239      */
1240     private boolean isResponsibleForMonitor() {
1241         return (recheckInterval > 0);
1242     }
1243 
1244     @Override
1245     boolean alive() {
1246         int s = state;
1247         return (s != NEW && s != TERMINATED);
1248     }
1249 
1250     @Override
1251     boolean isTerminated() {
1252         return (state == TERMINATED);
1253     }
1254 
1255     @Override
1256     StackTraceElement[] asyncGetStackTrace() {
1257         StackTraceElement[] stackTrace;
1258         do {
1259             stackTrace = (carrierThread != null)
1260                     ? super.asyncGetStackTrace()  // mounted
1261                     : tryGetStackTrace();         // unmounted
1262             if (stackTrace == null) {
1263                 Thread.yield();
1264             }
1265         } while (stackTrace == null);
1266         return stackTrace;
1267     }
1268 
1269     /**
1270      * Returns the stack trace for this virtual thread if it is unmounted.
1271      * Returns null if the thread is mounted or in transition.
1272      */
1273     private StackTraceElement[] tryGetStackTrace() {
1274         int initialState = state() & ~SUSPENDED;
1275         switch (initialState) {
1276             case NEW, STARTED, TERMINATED -> {
1277                 return new StackTraceElement[0];  // unmounted, empty stack
1278             }
1279             case RUNNING, PINNED, TIMED_PINNED -> {
1280                 return null;   // mounted
1281             }
1282             case PARKED, TIMED_PARKED, BLOCKED, WAIT, TIMED_WAIT -> {
1283                 // unmounted, not runnable
1284             }
1285             case UNPARKED, UNBLOCKED, YIELDED -> {
1286                 // unmounted, runnable
1287             }
1288             case PARKING, TIMED_PARKING, BLOCKING, YIELDING, WAITING, TIMED_WAITING -> {
1289                 return null;  // in transition
1290             }
1291             default -> throw new InternalError("" + initialState);
1292         }
1293 
1294         // thread is unmounted, prevent it from continuing
1295         int suspendedState = initialState | SUSPENDED;
1296         if (!compareAndSetState(initialState, suspendedState)) {
1297             return null;
1298         }
1299 
1300         // get stack trace and restore state
1301         StackTraceElement[] stack;
1302         try {
1303             stack = cont.getStackTrace();
1304         } finally {
1305             assert state == suspendedState;
1306             setState(initialState);
1307         }
1308         boolean resubmit = switch (initialState) {
1309             case UNPARKED, UNBLOCKED, YIELDED -> {
1310                 // resubmit as task may have run while suspended
1311                 yield true;
1312             }
1313             case PARKED, TIMED_PARKED -> {
1314                 // resubmit if unparked while suspended
1315                 yield parkPermit && compareAndSetState(initialState, UNPARKED);
1316             }
1317             case BLOCKED -> {
1318                 // resubmit if unblocked while suspended
1319                 yield unblocked && compareAndSetState(BLOCKED, UNBLOCKED);
1320             }
1321             case WAIT, TIMED_WAIT -> {
1322                 // resubmit if notified or interrupted while waiting (Object.wait)
1323                 // waitTimeoutExpired will retry if the timed expired when suspended
1324                 yield (notified || interrupted) && compareAndSetState(initialState, UNBLOCKED);
1325             }
1326             default -> throw new InternalError();
1327         };
1328         if (resubmit) {
1329             submitRunContinuation();
1330         }
1331         return stack;
1332     }
1333 
1334     @Override
1335     public String toString() {
1336         StringBuilder sb = new StringBuilder("VirtualThread[#");
1337         sb.append(threadId());
1338         String name = getName();
1339         if (!name.isEmpty()) {
1340             sb.append(",");
1341             sb.append(name);
1342         }
1343         sb.append("]/");
1344 
1345         // add the carrier state and thread name when mounted
1346         boolean mounted;
1347         if (Thread.currentThread() == this) {
1348             mounted = appendCarrierInfo(sb);
1349         } else {
1350             disableSuspendAndPreempt();
1351             try {
1352                 synchronized (carrierThreadAccessLock()) {
1353                     mounted = appendCarrierInfo(sb);
1354                 }
1355             } finally {
1356                 enableSuspendAndPreempt();
1357             }
1358         }
1359 
1360         // add virtual thread state when not mounted
1361         if (!mounted) {
1362             String stateAsString = threadState().toString();
1363             sb.append(stateAsString.toLowerCase(Locale.ROOT));
1364         }
1365 
1366         return sb.toString();
1367     }
1368 
1369     /**
1370      * Appends the carrier state and thread name to the string buffer if mounted.
1371      * @return true if mounted, false if not mounted
1372      */
1373     private boolean appendCarrierInfo(StringBuilder sb) {
1374         assert Thread.currentThread() == this || Thread.holdsLock(carrierThreadAccessLock());
1375         Thread carrier = carrierThread;
1376         if (carrier != null) {
1377             String stateAsString = carrier.threadState().toString();
1378             sb.append(stateAsString.toLowerCase(Locale.ROOT));
1379             sb.append('@');
1380             sb.append(carrier.getName());
1381             return true;
1382         } else {
1383             return false;
1384         }
1385     }
1386 
1387     @Override
1388     public int hashCode() {
1389         return (int) threadId();
1390     }
1391 
1392     @Override
1393     public boolean equals(Object obj) {
1394         return obj == this;
1395     }
1396 
1397     /**
1398      * Returns the termination object, creating it if needed.
1399      */
1400     private CountDownLatch getTermination() {
1401         CountDownLatch termination = this.termination;
1402         if (termination == null) {
1403             termination = new CountDownLatch(1);
1404             if (!U.compareAndSetReference(this, TERMINATION, null, termination)) {
1405                 termination = this.termination;
1406             }
1407         }
1408         return termination;
1409     }
1410 
1411     /**
1412      * Returns the lock object to synchronize on when accessing carrierThread.
1413      * The lock prevents carrierThread from being reset to null during unmount.
1414      */
1415     private Object carrierThreadAccessLock() {
1416         // return interruptLock as unmount has to coordinate with interrupt
1417         return interruptLock;
1418     }
1419 
1420     /**
1421      * Returns a lock object to coordinating timed-wait setup and timeout handling.
1422      */
1423     private Object timedWaitLock() {
1424         // use this object for now to avoid the overhead of introducing another lock
1425         return runContinuation;
1426     }
1427 
1428     /**
1429      * Disallow the current thread be suspended or preempted.
1430      */
1431     private void disableSuspendAndPreempt() {
1432         notifyJvmtiDisableSuspend(true);
1433         Continuation.pin();
1434     }
1435 
1436     /**
1437      * Allow the current thread be suspended or preempted.
1438      */
1439     private void enableSuspendAndPreempt() {
1440         Continuation.unpin();
1441         notifyJvmtiDisableSuspend(false);
1442     }
1443 
1444     // -- wrappers for get/set of state, parking permit, and carrier thread --
1445 
1446     private int state() {
1447         return state;  // volatile read
1448     }
1449 
1450     private void setState(int newValue) {
1451         state = newValue;  // volatile write
1452     }
1453 
1454     private boolean compareAndSetState(int expectedValue, int newValue) {
1455         return U.compareAndSetInt(this, STATE, expectedValue, newValue);
1456     }
1457 
1458     private boolean compareAndSetOnWaitingList(byte expectedValue, byte newValue) {
1459         return U.compareAndSetByte(this, ON_WAITING_LIST, expectedValue, newValue);
1460     }
1461 
1462     private void setParkPermit(boolean newValue) {
1463         if (parkPermit != newValue) {
1464             parkPermit = newValue;
1465         }
1466     }
1467 
1468     private boolean getAndSetParkPermit(boolean newValue) {
1469         if (parkPermit != newValue) {
1470             return U.getAndSetBoolean(this, PARK_PERMIT, newValue);
1471         } else {
1472             return newValue;
1473         }
1474     }
1475 
1476     private void setCarrierThread(Thread carrier) {
1477         // U.putReferenceRelease(this, CARRIER_THREAD, carrier);
1478         this.carrierThread = carrier;
1479     }
1480 
1481     @IntrinsicCandidate
1482     private static native void setLockId(long tid);
1483 
1484     // -- JVM TI support --
1485 
1486     @IntrinsicCandidate
1487     @JvmtiMountTransition
1488     private native void notifyJvmtiStart();
1489 
1490     @IntrinsicCandidate
1491     @JvmtiMountTransition
1492     private native void notifyJvmtiEnd();
1493 
1494     @IntrinsicCandidate
1495     @JvmtiMountTransition
1496     private native void notifyJvmtiMount(boolean hide);
1497 
1498     @IntrinsicCandidate
1499     @JvmtiMountTransition
1500     private native void notifyJvmtiUnmount(boolean hide);
1501 
1502     @IntrinsicCandidate
1503     @JvmtiMountTransition
1504     private static native void notifyJvmtiHideFrames(boolean hide);
1505 
1506     @IntrinsicCandidate
1507     private static native void notifyJvmtiDisableSuspend(boolean enter);
1508 
1509     private static native void registerNatives();
1510     static {
1511         registerNatives();
1512 
1513         // ensure VTHREAD_GROUP is created, may be accessed by JVMTI
1514         var group = Thread.virtualThreadGroup();
1515     }
1516 
1517     /**
1518      * Creates the default scheduler.
1519      * If the system property {@code jdk.virtualThreadScheduler.implClass} is set then
1520      * its value is the name of a class that implements java.util.concurrent.Executor.
1521      * The class is public in an exported package, has a public no-arg constructor,
1522      * and is visible to the system class loader.
1523      * If the system property is not set then the default scheduler will be a
1524      * ForkJoinPool instance.
1525      */
1526     private static Executor createDefaultScheduler() {
1527         String propName = "jdk.virtualThreadScheduler.implClass";
1528         String propValue = GetPropertyAction.privilegedGetProperty(propName);
1529         if (propValue != null) {
1530             try {
1531                 Class<?> clazz = Class.forName(propValue, true,
1532                         ClassLoader.getSystemClassLoader());
1533                 Constructor<?> ctor = clazz.getConstructor();
1534                 return (Executor) ctor.newInstance();
1535             } catch (Exception ex) {
1536                 throw new Error(ex);
1537             }
1538         } else {
1539             return createDefaultForkJoinPoolScheduler();
1540         }
1541     }
1542 
1543     /**
1544      * Creates the default ForkJoinPool scheduler.
1545      */
1546     @SuppressWarnings("removal")
1547     private static ForkJoinPool createDefaultForkJoinPoolScheduler() {
1548         ForkJoinWorkerThreadFactory factory = pool -> {
1549             PrivilegedAction<ForkJoinWorkerThread> pa = () -> new CarrierThread(pool);
1550             return AccessController.doPrivileged(pa);
1551         };
1552         PrivilegedAction<ForkJoinPool> pa = () -> {
1553             int parallelism, maxPoolSize, minRunnable;
1554             String parallelismValue = System.getProperty("jdk.virtualThreadScheduler.parallelism");
1555             String maxPoolSizeValue = System.getProperty("jdk.virtualThreadScheduler.maxPoolSize");
1556             String minRunnableValue = System.getProperty("jdk.virtualThreadScheduler.minRunnable");
1557             if (parallelismValue != null) {
1558                 parallelism = Integer.parseInt(parallelismValue);
1559             } else {
1560                 parallelism = Runtime.getRuntime().availableProcessors();
1561             }
1562             if (maxPoolSizeValue != null) {
1563                 maxPoolSize = Integer.parseInt(maxPoolSizeValue);
1564                 parallelism = Integer.min(parallelism, maxPoolSize);
1565             } else {
1566                 maxPoolSize = Integer.max(parallelism, 256);
1567             }
1568             if (minRunnableValue != null) {
1569                 minRunnable = Integer.parseInt(minRunnableValue);
1570             } else {
1571                 minRunnable = Integer.max(parallelism / 2, 1);
1572             }
1573             Thread.UncaughtExceptionHandler handler = (t, e) -> { };
1574             boolean asyncMode = true; // FIFO
1575             return new ForkJoinPool(parallelism, factory, handler, asyncMode,
1576                          0, maxPoolSize, minRunnable, pool -> true, 30, SECONDS);
1577         };
1578         return AccessController.doPrivileged(pa);
1579     }
1580 
1581     /**
1582      * Schedule a runnable task to run after a delay.
1583      */
1584     private static Future<?> schedule(Runnable command, long delay, TimeUnit unit) {
1585         long tid = Thread.currentThread().threadId();
1586         int index = (int) tid & (DELAYED_TASK_SCHEDULERS.length - 1);
1587         return DELAYED_TASK_SCHEDULERS[index].schedule(command, delay, unit);
1588     }
1589 
1590     /**
1591      * Creates the ScheduledThreadPoolExecutors used to execute delayed tasks.
1592      */
1593     private static ScheduledExecutorService[] createDelayedTaskSchedulers() {
1594         String propName = "jdk.virtualThreadScheduler.timerQueues";
1595         String propValue = GetPropertyAction.privilegedGetProperty(propName);
1596         int queueCount;
1597         if (propValue != null) {
1598             queueCount = Integer.parseInt(propValue);
1599             if (queueCount != Integer.highestOneBit(queueCount)) {
1600                 throw new RuntimeException("Value of " + propName + " must be power of 2");
1601             }
1602         } else {
1603             int ncpus = Runtime.getRuntime().availableProcessors();
1604             queueCount = Math.max(Integer.highestOneBit(ncpus / 4), 1);
1605         }
1606         var schedulers = new ScheduledExecutorService[queueCount];
1607         for (int i = 0; i < queueCount; i++) {
1608             ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor)
1609                 Executors.newScheduledThreadPool(1, task -> {
1610                     Thread t = InnocuousThread.newThread("VirtualThread-unparker", task);
1611                     t.setDaemon(true);
1612                     return t;
1613                 });
1614             stpe.setRemoveOnCancelPolicy(true);
1615             schedulers[i] = stpe;
1616         }
1617         return schedulers;
1618     }
1619 
1620     /**
1621      * Schedule virtual threads that are ready to be scheduled after they blocked on
1622      * monitor enter.
1623      */
1624     private static void unblockVirtualThreads() {
1625         while (true) {
1626             VirtualThread vthread = takeVirtualThreadListToUnblock();
1627             while (vthread != null) {
1628                 assert vthread.onWaitingList == 1;
1629                 VirtualThread nextThread = vthread.next;
1630 
1631                 // remove from list and unblock
1632                 vthread.next = null;
1633                 boolean changed = vthread.compareAndSetOnWaitingList((byte) 1, (byte) 0);
1634                 assert changed;
1635                 vthread.unblock();
1636 
1637                 vthread = nextThread;
1638             }
1639         }
1640     }
1641 
1642     /**
1643      * Retrieves the list of virtual threads that are waiting to be unblocked, waiting
1644      * if necessary until a list of one or more threads becomes available.
1645      */
1646     private static native VirtualThread takeVirtualThreadListToUnblock();
1647 
1648     static {
1649         var unblocker = InnocuousThread.newThread("VirtualThread-unblocker",
1650                 VirtualThread::unblockVirtualThreads);
1651         unblocker.setDaemon(true);
1652         unblocker.start();
1653     }
1654 }