/*
 * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.lang;

import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import jdk.internal.event.VirtualThreadEndEvent;
import jdk.internal.event.VirtualThreadStartEvent;
import jdk.internal.event.VirtualThreadSubmitFailedEvent;
import jdk.internal.misc.CarrierThread;
import jdk.internal.misc.InnocuousThread;
import jdk.internal.misc.Unsafe;
import jdk.internal.vm.Continuation;
import jdk.internal.vm.ContinuationScope;
import jdk.internal.vm.StackableScope;
import jdk.internal.vm.ThreadContainer;
import jdk.internal.vm.ThreadContainers;
import jdk.internal.vm.annotation.ChangesCurrentThread;
import jdk.internal.vm.annotation.Hidden;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.vm.annotation.JvmtiHideEvents;
import jdk.internal.vm.annotation.JvmtiMountTransition;
import jdk.internal.vm.annotation.ReservedStackAccess;
import sun.nio.ch.Interruptible;
import static java.util.concurrent.TimeUnit.*;

/**
 * A thread that is scheduled by the Java virtual machine rather than the operating system.
 */
final class VirtualThread extends BaseVirtualThread {
    private static final Unsafe U = Unsafe.getUnsafe();
    private static final ContinuationScope VTHREAD_SCOPE = new ContinuationScope("VirtualThreads");
    private static final ForkJoinPool DEFAULT_SCHEDULER = createDefaultScheduler();

    private static final long STATE = U.objectFieldOffset(VirtualThread.class, "state");
    private static final long PARK_PERMIT = U.objectFieldOffset(VirtualThread.class, "parkPermit");
    private static final long CARRIER_THREAD = U.objectFieldOffset(VirtualThread.class, "carrierThread");
    private static final long TERMINATION = U.objectFieldOffset(VirtualThread.class, "termination");
    private static final long ON_WAITING_LIST = U.objectFieldOffset(VirtualThread.class, "onWaitingList");

    // scheduler and continuation
    private final Executor scheduler;
    private final Continuation cont;
    private final Runnable runContinuation;

    // virtual thread state, accessed by VM
    private volatile int state;

    /*
     * Virtual thread state transitions:
     *
     *      NEW -> STARTED         // Thread.start, schedule to run
     *  STARTED -> TERMINATED      // failed to start
     *  STARTED -> RUNNING         // first run
     *  RUNNING -> TERMINATED      // done
     *
     *  RUNNING -> PARKING         // Thread parking with LockSupport.park
     *  PARKING -> PARKED          // cont.yield successful, parked indefinitely
     *  PARKING -> PINNED          // cont.yield failed, parked indefinitely on carrier
     *   PARKED -> UNPARKED        // unparked, may be scheduled to continue
     *   PINNED -> RUNNING         // unparked, continue execution on same carrier
     * UNPARKED -> RUNNING         // continue execution after park
     *
     *       RUNNING -> TIMED_PARKING   // Thread parking with LockSupport.parkNanos
     * TIMED_PARKING -> TIMED_PARKED    // cont.yield successful, timed-parked
     * TIMED_PARKING -> TIMED_PINNED    // cont.yield failed, timed-parked on carrier
     *  TIMED_PARKED -> UNPARKED        // unparked, may be scheduled to continue
     *  TIMED_PINNED -> RUNNING         // unparked, continue execution on same carrier
     *
     *   RUNNING -> BLOCKING       // blocking on monitor enter
     *  BLOCKING -> BLOCKED        // blocked on monitor enter
     *   BLOCKED -> UNBLOCKED      // unblocked, may be scheduled to continue
     * UNBLOCKED -> RUNNING        // continue execution after blocked on monitor enter
     *
     *   RUNNING -> WAITING        // transitional state during wait on monitor
     *   WAITING -> WAIT           // waiting on monitor
     *      WAIT -> BLOCKED        // notified, waiting to be unblocked by monitor owner
     *      WAIT -> UNBLOCKED      // timed-out/interrupted
     *
     *       RUNNING -> TIMED_WAITING   // transition state during timed-waiting on monitor
     * TIMED_WAITING -> TIMED_WAIT      // timed-waiting on monitor
     *    TIMED_WAIT -> BLOCKED         // notified, waiting to be unblocked by monitor owner
     *    TIMED_WAIT -> UNBLOCKED       // timed-out/interrupted
     *
     *  RUNNING -> YIELDING        // Thread.yield
     * YIELDING -> YIELDED         // cont.yield successful, may be scheduled to continue
     * YIELDING -> RUNNING         // cont.yield failed
     *  YIELDED -> RUNNING         // continue execution after Thread.yield
     */
    private static final int NEW      = 0;
    private static final int STARTED  = 1;
    private static final int RUNNING  = 2;     // runnable-mounted

    // untimed and timed parking
    private static final int PARKING       = 3;
    private static final int PARKED        = 4;     // unmounted
    private static final int PINNED        = 5;     // mounted
    private static final int TIMED_PARKING = 6;
    private static final int TIMED_PARKED  = 7;     // unmounted
    private static final int TIMED_PINNED  = 8;     // mounted
    private static final int UNPARKED      = 9;     // unmounted but runnable

    // Thread.yield
    private static final int YIELDING = 10;
    private static final int YIELDED  = 11;         // unmounted but runnable

    // monitor enter
    private static final int BLOCKING  = 12;
    private static final int BLOCKED   = 13;        // unmounted
    private static final int UNBLOCKED = 14;        // unmounted but runnable

    // monitor wait/timed-wait
    private static final int WAITING       = 15;
    private static final int WAIT          = 16;    // waiting in Object.wait
    private static final int TIMED_WAITING = 17;
    private static final int TIMED_WAIT    = 18;    // waiting in timed-Object.wait

    private static final int TERMINATED = 99;  // final state

    // can be suspended from scheduling when unmounted
    private static final int SUSPENDED = 1 << 8;

    // parking permit made available by LockSupport.unpark
    private volatile boolean parkPermit;

    // blocking permit made available by unblocker thread when another thread exits monitor
    private volatile boolean blockPermit;

    // true when on the list of virtual threads waiting to be unblocked
    private volatile boolean onWaitingList;

    // next virtual thread on the list of virtual threads waiting to be unblocked
    private volatile VirtualThread next;

    // notified by Object.notify/notifyAll while waiting in Object.wait
    private volatile boolean notified;

    // timed-wait support
    private byte timedWaitSeqNo;

    // timeout for timed-park and timed-wait, only accessed on current/carrier thread
    private long timeout;

    // timer task for timed-park and timed-wait, only accessed on current/carrier thread
    private Future<?> timeoutTask;

    // carrier thread when mounted, accessed by VM
    private volatile Thread carrierThread;

    // termination object when joining, created lazily if needed
    private volatile CountDownLatch termination;

    /**
     * Returns the default scheduler.
     */
    static Executor defaultScheduler() {
        return DEFAULT_SCHEDULER;
    }

    /**
     * Returns the continuation scope used for virtual threads.
     */
    static ContinuationScope continuationScope() {
        return VTHREAD_SCOPE;
    }

    /**
     * Creates a new {@code VirtualThread} to run the given task with the given
     * scheduler. If the given scheduler is {@code null} and the current thread
     * is a platform thread then the newly created virtual thread will use the
     * default scheduler. If given scheduler is {@code null} and the current
     * thread is a virtual thread then the current thread's scheduler is used.
     *
     * @param scheduler the scheduler or null
     * @param name thread name
     * @param characteristics characteristics
     * @param task the task to execute
     */
    VirtualThread(Executor scheduler, String name, int characteristics, Runnable task) {
        super(name, characteristics, /*bound*/ false);
        Objects.requireNonNull(task);

        // choose scheduler if not specified
        if (scheduler == null) {
            Thread parent = Thread.currentThread();
            if (parent instanceof VirtualThread vparent) {
                scheduler = vparent.scheduler;
            } else {
                scheduler = DEFAULT_SCHEDULER;
            }
        }

        this.scheduler = scheduler;
        this.cont = new VThreadContinuation(this, task);
        this.runContinuation = this::runContinuation;
    }

    /**
     * The continuation that a virtual thread executes.
     */
    private static class VThreadContinuation extends Continuation {
        VThreadContinuation(VirtualThread vthread, Runnable task) {
            super(VTHREAD_SCOPE, wrap(vthread, task));
        }
        @Override
        protected void onPinned(Continuation.Pinned reason) {
        }
        private static Runnable wrap(VirtualThread vthread, Runnable task) {
            return new Runnable() {
                @Hidden
                @JvmtiHideEvents
                public void run() {
                    vthread.notifyJvmtiStart(); // notify JVMTI
                    try {
                        vthread.run(task);
                    } finally {
                        vthread.notifyJvmtiEnd(); // notify JVMTI
                    }
                }
            };
        }
    }

    /**
     * Runs or continues execution on the current thread. The virtual thread is mounted
     * on the current thread before the task runs or continues. It unmounts when the
     * task completes or yields.
     */
    @ChangesCurrentThread // allow mount/unmount to be inlined
    private void runContinuation() {
        // the carrier must be a platform thread
        if (Thread.currentThread().isVirtual()) {
            throw new WrongThreadException();
        }

        // set state to RUNNING
        int initialState = state();
        if (initialState == STARTED || initialState == UNPARKED
                || initialState == UNBLOCKED || initialState == YIELDED) {
            // newly started or continue after parking/blocking/Thread.yield
            if (!compareAndSetState(initialState, RUNNING)) {
                return;
            }
            // consume permit when continuing after parking or blocking. If continue
            // after a timed-park or timed-wait then the timeout task is cancelled.
            if (initialState == UNPARKED) {
                cancelTimeoutTask();
                setParkPermit(false);
            } else if (initialState == UNBLOCKED) {
                cancelTimeoutTask();
                blockPermit = false;
            }
        } else {
            // not runnable
            return;
        }

        mount();
        try {
            cont.run();
        } finally {
            unmount();
            if (cont.isDone()) {
                afterDone();
            } else {
                afterYield();
            }
        }
    }

    /**
     * Cancel timeout task when continuing after timed-park or timed-wait.
     * The timeout task may be executing, or may have already completed.
     */
    private void cancelTimeoutTask() {
        if (timeoutTask != null) {
            timeoutTask.cancel(false);
            timeoutTask = null;
        }
    }

    /**
     * Submits the runContinuation task to the scheduler. For the default scheduler,
     * and calling it on a worker thread, the task will be pushed to the local queue,
     * otherwise it will be pushed to an external submission queue.
     * @param scheduler the scheduler
     * @param retryOnOOME true to retry indefinitely if OutOfMemoryError is thrown
     * @throws RejectedExecutionException
     */
    private void submitRunContinuation(Executor scheduler, boolean retryOnOOME) {
        boolean done = false;
        while (!done) {
            try {
                // Pin the continuation to prevent the virtual thread from unmounting
                // when submitting a task. For the default scheduler this ensures that
                // the carrier doesn't change when pushing a task. For other schedulers
                // it avoids deadlock that could arise due to carriers and virtual
                // threads contending for a lock.
                if (currentThread().isVirtual()) {
                    Continuation.pin();
                    try {
                        scheduler.execute(runContinuation);
                    } finally {
                        Continuation.unpin();
                    }
                } else {
                    scheduler.execute(runContinuation);
                }
                done = true;
            } catch (RejectedExecutionException ree) {
                submitFailed(ree);
                throw ree;
            } catch (OutOfMemoryError e) {
                if (retryOnOOME) {
                    U.park(false, 100_000_000); // 100ms
                } else {
                    throw e;
                }
            }
        }
    }

    /**
     * Submits the runContinuation task to the given scheduler as an external submit.
     * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
     * @throws RejectedExecutionException
     * @see ForkJoinPool#externalSubmit(ForkJoinTask)
     */
    private void externalSubmitRunContinuation(ForkJoinPool pool) {
        assert Thread.currentThread() instanceof CarrierThread;
        try {
            pool.externalSubmit(ForkJoinTask.adapt(runContinuation));
        } catch (RejectedExecutionException ree) {
            submitFailed(ree);
            throw ree;
        } catch (OutOfMemoryError e) {
            submitRunContinuation(pool, true);
        }
    }

    /**
     * Submits the runContinuation task to the scheduler. For the default scheduler,
     * and calling it on a worker thread, the task will be pushed to the local queue,
     * otherwise it will be pushed to an external submission queue.
     * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
     * @throws RejectedExecutionException
     */
    private void submitRunContinuation() {
        submitRunContinuation(scheduler, true);
    }

    /**
     * Lazy submit the runContinuation task if invoked on a carrier thread and its local
     * queue is empty. If not empty, or invoked by another thread, then this method works
     * like submitRunContinuation and just submits the task to the scheduler.
     * If OutOfMemoryError is thrown then the submit will be retried until it succeeds.
     * @throws RejectedExecutionException
     * @see ForkJoinPool#lazySubmit(ForkJoinTask)
     */
    private void lazySubmitRunContinuation() {
        if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
            ForkJoinPool pool = ct.getPool();
            try {
                pool.lazySubmit(ForkJoinTask.adapt(runContinuation));
            } catch (RejectedExecutionException ree) {
                submitFailed(ree);
                throw ree;
            } catch (OutOfMemoryError e) {
                submitRunContinuation();
            }
        } else {
            submitRunContinuation();
        }
    }

    /**
     * Submits the runContinuation task to the scheduler. For the default scheduler, and
     * calling it a virtual thread that uses the default scheduler, the task will be
     * pushed to an external submission queue. This method may throw OutOfMemoryError.
     * @throws RejectedExecutionException
     * @throws OutOfMemoryError
     */
    private void externalSubmitRunContinuationOrThrow() {
        if (scheduler == DEFAULT_SCHEDULER && currentCarrierThread() instanceof CarrierThread ct) {
            try {
                ct.getPool().externalSubmit(ForkJoinTask.adapt(runContinuation));
            } catch (RejectedExecutionException ree) {
                submitFailed(ree);
                throw ree;
            }
        } else {
            submitRunContinuation(scheduler, false);
        }
    }

    /**
     * If enabled, emits a JFR VirtualThreadSubmitFailedEvent.
     */
    private void submitFailed(RejectedExecutionException ree) {
        var event = new VirtualThreadSubmitFailedEvent();
        if (event.isEnabled()) {
            event.javaThreadId = threadId();
            event.exceptionMessage = ree.getMessage();
            event.commit();
        }
    }

    /**
     * Runs a task in the context of this virtual thread.
     */
    private void run(Runnable task) {
        assert Thread.currentThread() == this && state == RUNNING;

        // emit JFR event if enabled
        if (VirtualThreadStartEvent.isTurnedOn()) {
            var event = new VirtualThreadStartEvent();
            event.javaThreadId = threadId();
            event.commit();
        }

        Object bindings = Thread.scopedValueBindings();
        try {
            runWith(bindings, task);
        } catch (Throwable exc) {
            dispatchUncaughtException(exc);
        } finally {
            // pop any remaining scopes from the stack, this may block
            StackableScope.popAll();

            // emit JFR event if enabled
            if (VirtualThreadEndEvent.isTurnedOn()) {
                var event = new VirtualThreadEndEvent();
                event.javaThreadId = threadId();
                event.commit();
            }
        }
    }

    /**
     * Mounts this virtual thread onto the current platform thread. On
     * return, the current thread is the virtual thread.
     */
    @ChangesCurrentThread
    @ReservedStackAccess
    private void mount() {
        // notify JVMTI before mount
        notifyJvmtiMount(/*hide*/true);

        // sets the carrier thread
        Thread carrier = Thread.currentCarrierThread();
        setCarrierThread(carrier);

        // sync up carrier thread interrupt status if needed
        if (interrupted) {
            carrier.setInterrupt();
        } else if (carrier.isInterrupted()) {
            synchronized (interruptLock) {
                // need to recheck interrupt status
                if (!interrupted) {
                    carrier.clearInterrupt();
                }
            }
        }

        // set Thread.currentThread() to return this virtual thread
        carrier.setCurrentThread(this);
    }

    /**
     * Unmounts this virtual thread from the carrier. On return, the
     * current thread is the current platform thread.
     */
    @ChangesCurrentThread
    @ReservedStackAccess
    private void unmount() {
        assert !Thread.holdsLock(interruptLock);

        // set Thread.currentThread() to return the platform thread
        Thread carrier = this.carrierThread;
        carrier.setCurrentThread(carrier);

        // break connection to carrier thread, synchronized with interrupt
        synchronized (interruptLock) {
            setCarrierThread(null);
        }
        carrier.clearInterrupt();

        // notify JVMTI after unmount
        notifyJvmtiUnmount(/*hide*/false);
    }

    /**
     * Invokes Continuation.yield, notifying JVMTI (if enabled) to hide frames until
     * the continuation continues.
     */
    @Hidden
    private boolean yieldContinuation() {
        notifyJvmtiUnmount(/*hide*/true);
        try {
            return Continuation.yield(VTHREAD_SCOPE);
        } finally {
            notifyJvmtiMount(/*hide*/false);
        }
    }

    /**
     * Invoked in the context of the carrier thread after the Continuation yields when
     * parking, blocking on monitor enter, Object.wait, or Thread.yield.
     */
    private void afterYield() {
        assert carrierThread == null;

        // re-adjust parallelism if the virtual thread yielded when compensating
        if (currentThread() instanceof CarrierThread ct) {
            ct.endBlocking();
        }

        int s = state();

        // LockSupport.park/parkNanos
        if (s == PARKING || s == TIMED_PARKING) {
            int newState;
            if (s == PARKING) {
                setState(newState = PARKED);
            } else {
                // schedule unpark
                long timeout = this.timeout;
                assert timeout > 0;
                timeoutTask = schedule(this::parkTimeoutExpired, timeout, NANOSECONDS);
                setState(newState = TIMED_PARKED);
            }

            // may have been unparked while parking
            if (parkPermit && compareAndSetState(newState, UNPARKED)) {
                // lazy submit if local queue is empty
                lazySubmitRunContinuation();
            }
            return;
        }

        // Thread.yield
        if (s == YIELDING) {
            setState(YIELDED);

            // external submit if there are no tasks in the local task queue
            if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
                externalSubmitRunContinuation(ct.getPool());
            } else {
                submitRunContinuation();
            }
            return;
        }

        // blocking on monitorenter
        if (s == BLOCKING) {
            setState(BLOCKED);

            // may have been unblocked while blocking
            if (blockPermit && compareAndSetState(BLOCKED, UNBLOCKED)) {
                // lazy submit if local queue is empty
                lazySubmitRunContinuation();
            }
            return;
        }

        // Object.wait
        if (s == WAITING || s == TIMED_WAITING) {
            int newState;
            if (s == WAITING) {
                setState(newState = WAIT);
            } else {
                // For timed-wait, a timeout task is scheduled to execute. The timeout
                // task will change the thread state to UNBLOCKED and submit the thread
                // to the scheduler. A sequence number is used to ensure that the timeout
                // task only unblocks the thread for this timed-wait. We synchronize with
                // the timeout task to coordinate access to the sequence number and to
                // ensure the timeout task doesn't execute until the thread has got to
                // the TIMED_WAIT state.
                long timeout = this.timeout;
                assert timeout > 0;
                synchronized (timedWaitLock()) {
                    byte seqNo = ++timedWaitSeqNo;
                    timeoutTask = schedule(() -> waitTimeoutExpired(seqNo), timeout, MILLISECONDS);
                    setState(newState = TIMED_WAIT);
                }
            }

            // may have been notified while in transition to wait state
            if (notified && compareAndSetState(newState, BLOCKED)) {
                // may have even been unblocked already
                if (blockPermit && compareAndSetState(BLOCKED, UNBLOCKED)) {
                    submitRunContinuation();
                }
                return;
            }

            // may have been interrupted while in transition to wait state
            if (interrupted && compareAndSetState(newState, UNBLOCKED)) {
                submitRunContinuation();
                return;
            }
            return;
        }

        assert false;
    }

    /**
     * Invoked after the continuation completes.
     */
    private void afterDone() {
        afterDone(true);
    }

    /**
     * Invoked after the continuation completes (or start failed). Sets the thread
     * state to TERMINATED and notifies anyone waiting for the thread to terminate.
     *
     * @param notifyContainer true if its container should be notified
     */
    private void afterDone(boolean notifyContainer) {
        assert carrierThread == null;
        setState(TERMINATED);

        // notify anyone waiting for this virtual thread to terminate
        CountDownLatch termination = this.termination;
        if (termination != null) {
            assert termination.getCount() == 1;
            termination.countDown();
        }

        // notify container
        if (notifyContainer) {
            threadContainer().remove(this);
        }

        // clear references to thread locals
        clearReferences();
    }

    /**
     * Schedules this {@code VirtualThread} to execute.
     *
     * @throws IllegalStateException if the container is shutdown or closed
     * @throws IllegalThreadStateException if the thread has already been started
     * @throws RejectedExecutionException if the scheduler cannot accept a task
     */
    @Override
    void start(ThreadContainer container) {
        if (!compareAndSetState(NEW, STARTED)) {
            throw new IllegalThreadStateException("Already started");
        }

        // bind thread to container
        assert threadContainer() == null;
        setThreadContainer(container);

        // start thread
        boolean addedToContainer = false;
        boolean started = false;
        try {
            container.add(this);  // may throw
            addedToContainer = true;

            // scoped values may be inherited
            inheritScopedValueBindings(container);

            // submit task to run thread, using externalSubmit if possible
            externalSubmitRunContinuationOrThrow();
            started = true;
        } finally {
            if (!started) {
                afterDone(addedToContainer);
            }
        }
    }

    @Override
    public void start() {
        start(ThreadContainers.root());
    }

    @Override
    public void run() {
        // do nothing
    }

    /**
     * Parks until unparked or interrupted. If already unparked then the parking
     * permit is consumed and this method completes immediately (meaning it doesn't
     * yield). It also completes immediately if the interrupt status is set.
     */
    @Override
    void park() {
        assert Thread.currentThread() == this;

        // complete immediately if parking permit available or interrupted
        if (getAndSetParkPermit(false) || interrupted)
            return;

        // park the thread
        boolean yielded = false;
        setState(PARKING);
        try {
            yielded = yieldContinuation();
        } catch (OutOfMemoryError e) {
            // park on carrier
        } finally {
            assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
            if (!yielded) {
                assert state() == PARKING;
                setState(RUNNING);
            }
        }

        // park on the carrier thread when pinned
        if (!yielded) {
            parkOnCarrierThread(false, 0);
        }
    }

    /**
     * Parks up to the given waiting time or until unparked or interrupted.
     * If already unparked then the parking permit is consumed and this method
     * completes immediately (meaning it doesn't yield). It also completes immediately
     * if the interrupt status is set or the waiting time is {@code <= 0}.
     *
     * @param nanos the maximum number of nanoseconds to wait.
     */
    @Override
    void parkNanos(long nanos) {
        assert Thread.currentThread() == this;

        // complete immediately if parking permit available or interrupted
        if (getAndSetParkPermit(false) || interrupted)
            return;

        // park the thread for the waiting time
        if (nanos > 0) {
            long startTime = System.nanoTime();

            // park the thread, afterYield will schedule the thread to unpark
            boolean yielded = false;
            timeout = nanos;
            setState(TIMED_PARKING);
            try {
                yielded = yieldContinuation();
            } catch (OutOfMemoryError e) {
                // park on carrier
            } finally {
                assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
                if (!yielded) {
                    assert state() == TIMED_PARKING;
                    setState(RUNNING);
                }
            }

            // park on carrier thread for remaining time when pinned (or OOME)
            if (!yielded) {
                long remainingNanos = nanos - (System.nanoTime() - startTime);
                parkOnCarrierThread(true, remainingNanos);
            }
        }
    }

    /**
     * Parks the current carrier thread up to the given waiting time or until
     * unparked or interrupted. If the virtual thread is interrupted then the
     * interrupt status will be propagated to the carrier thread.
     * @param timed true for a timed park, false for untimed
     * @param nanos the waiting time in nanoseconds
     */
    private void parkOnCarrierThread(boolean timed, long nanos) {
        assert state() == RUNNING;

        setState(timed ? TIMED_PINNED : PINNED);
        try {
            if (!parkPermit) {
                if (!timed) {
                    U.park(false, 0);
                } else if (nanos > 0) {
                    U.park(false, nanos);
                }
            }
        } finally {
            setState(RUNNING);
        }

        // consume parking permit
        setParkPermit(false);

        // JFR jdk.VirtualThreadPinned event
        postPinnedEvent("LockSupport.park");
    }

    /**
     * Call into VM when pinned to record a JFR jdk.VirtualThreadPinned event.
     * Recording the event in the VM avoids having JFR event recorded in Java
     * with the same name, but different ID, to events recorded by the VM.
     */
    @Hidden
    private static native void postPinnedEvent(String op);

    /**
     * Re-enables this virtual thread for scheduling. If this virtual thread is parked
     * then its task is scheduled to continue, otherwise its next call to {@code park} or
     * {@linkplain #parkNanos(long) parkNanos} is guaranteed not to block.
     * @throws RejectedExecutionException if the scheduler cannot accept a task
     */
    @Override
    void unpark() {
        if (!getAndSetParkPermit(true) && currentThread() != this) {
            int s = state();

            // unparked while parked
            if ((s == PARKED || s == TIMED_PARKED) && compareAndSetState(s, UNPARKED)) {
                submitRunContinuation();
                return;
            }

            // unparked while parked when pinned
            if (s == PINNED || s == TIMED_PINNED) {
                // unpark carrier thread when pinned
                disableSuspendAndPreempt();
                try {
                    synchronized (carrierThreadAccessLock()) {
                        Thread carrier = carrierThread;
                        if (carrier != null && ((s = state()) == PINNED || s == TIMED_PINNED)) {
                            U.unpark(carrier);
                        }
                    }
                } finally {
                    enableSuspendAndPreempt();
                }
                return;
            }
        }
    }

    /**
     * Invoked by unblocker thread to unblock this virtual thread.
     */
    private void unblock() {
        assert !Thread.currentThread().isVirtual();
        blockPermit = true;
        if (state() == BLOCKED && compareAndSetState(BLOCKED, UNBLOCKED)) {
            submitRunContinuation();
        }
    }

    /**
     * Invoked by FJP worker thread or STPE thread when park timeout expires.
     */
    private void parkTimeoutExpired() {
        assert !VirtualThread.currentThread().isVirtual();
        if (!getAndSetParkPermit(true)
                && (state() == TIMED_PARKED)
                && compareAndSetState(TIMED_PARKED, UNPARKED)) {
            lazySubmitRunContinuation();
        }
    }

    /**
     * Invoked by FJP worker thread or STPE thread when wait timeout expires.
     * If the virtual thread is in timed-wait then this method will unblock the thread
     * and submit its task so that it continues and attempts to reenter the monitor.
     * This method does nothing if the thread has been woken by notify or interrupt.
     */
    private void waitTimeoutExpired(byte seqNo) {
        assert !Thread.currentThread().isVirtual();
        for (;;) {
            boolean unblocked = false;
            synchronized (timedWaitLock()) {
                if (seqNo != timedWaitSeqNo) {
                    // this timeout task is for a past timed-wait
                    return;
                }
                int s = state();
                if (s == TIMED_WAIT) {
                    unblocked = compareAndSetState(TIMED_WAIT, UNBLOCKED);
                } else if (s != (TIMED_WAIT | SUSPENDED)) {
                    // notified or interrupted, no longer waiting
                    return;
                }
            }
            if (unblocked) {
                lazySubmitRunContinuation();
                return;
            }
            // need to retry when thread is suspended in time-wait
            Thread.yield();
        }
    }

    /**
     * Attempts to yield the current virtual thread (Thread.yield).
     */
    void tryYield() {
        assert Thread.currentThread() == this;
        setState(YIELDING);
        boolean yielded = false;
        try {
            yielded = yieldContinuation();  // may throw
        } finally {
            assert (Thread.currentThread() == this) && (yielded == (state() == RUNNING));
            if (!yielded) {
                assert state() == YIELDING;
                setState(RUNNING);
            }
        }
    }

    /**
     * Sleep the current thread for the given sleep time (in nanoseconds). If
     * nanos is 0 then the thread will attempt to yield.
     *
     * @implNote This implementation parks the thread for the given sleeping time
     * and will therefore be observed in PARKED state during the sleep. Parking
     * will consume the parking permit so this method makes available the parking
     * permit after the sleep. This may be observed as a spurious, but benign,
     * wakeup when the thread subsequently attempts to park.
     *
     * @param nanos the maximum number of nanoseconds to sleep
     * @throws InterruptedException if interrupted while sleeping
     */
    void sleepNanos(long nanos) throws InterruptedException {
        assert Thread.currentThread() == this && nanos >= 0;
        if (getAndClearInterrupt())
            throw new InterruptedException();
        if (nanos == 0) {
            tryYield();
        } else {
            // park for the sleep time
            try {
                long remainingNanos = nanos;
                long startNanos = System.nanoTime();
                while (remainingNanos > 0) {
                    parkNanos(remainingNanos);
                    if (getAndClearInterrupt()) {
                        throw new InterruptedException();
                    }
                    remainingNanos = nanos - (System.nanoTime() - startNanos);
                }
            } finally {
                // may have been unparked while sleeping
                setParkPermit(true);
            }
        }
    }

    /**
     * Waits up to {@code nanos} nanoseconds for this virtual thread to terminate.
     * A timeout of {@code 0} means to wait forever.
     *
     * @throws InterruptedException if interrupted while waiting
     * @return true if the thread has terminated
     */
    boolean joinNanos(long nanos) throws InterruptedException {
        if (state() == TERMINATED)
            return true;

        // ensure termination object exists, then re-check state
        CountDownLatch termination = getTermination();
        if (state() == TERMINATED)
            return true;

        // wait for virtual thread to terminate
        if (nanos == 0) {
            termination.await();
        } else {
            boolean terminated = termination.await(nanos, NANOSECONDS);
            if (!terminated) {
                // waiting time elapsed
                return false;
            }
        }
        assert state() == TERMINATED;
        return true;
    }

    @Override
    void blockedOn(Interruptible b) {
        disableSuspendAndPreempt();
        try {
            super.blockedOn(b);
        } finally {
            enableSuspendAndPreempt();
        }
    }

    @Override
    public void interrupt() {
        if (Thread.currentThread() != this) {
            // if current thread is a virtual thread then prevent it from being
            // suspended or unmounted when entering or holding interruptLock
            Interruptible blocker;
            disableSuspendAndPreempt();
            try {
                synchronized (interruptLock) {
                    interrupted = true;
                    blocker = nioBlocker();
                    if (blocker != null) {
                        blocker.interrupt(this);
                    }

                    // interrupt carrier thread if mounted
                    Thread carrier = carrierThread;
                    if (carrier != null) carrier.setInterrupt();
                }
            } finally {
                enableSuspendAndPreempt();
            }

            // notify blocker after releasing interruptLock
            if (blocker != null) {
                blocker.postInterrupt();
            }

            // make available parking permit, unpark thread if parked
            unpark();

            // if thread is waiting in Object.wait then schedule to try to reenter
            int s = state();
            if ((s == WAIT || s == TIMED_WAIT) && compareAndSetState(s, UNBLOCKED)) {
                submitRunContinuation();
            }

        } else {
            interrupted = true;
            carrierThread.setInterrupt();
            setParkPermit(true);
        }
    }

    @Override
    public boolean isInterrupted() {
        return interrupted;
    }

    @Override
    boolean getAndClearInterrupt() {
        assert Thread.currentThread() == this;
        boolean oldValue = interrupted;
        if (oldValue) {
            disableSuspendAndPreempt();
            try {
                synchronized (interruptLock) {
                    interrupted = false;
                    carrierThread.clearInterrupt();
                }
            } finally {
                enableSuspendAndPreempt();
            }
        }
        return oldValue;
    }

    @Override
    Thread.State threadState() {
        int s = state();
        switch (s & ~SUSPENDED) {
            case NEW:
                return Thread.State.NEW;
            case STARTED:
                // return NEW if thread container not yet set
                if (threadContainer() == null) {
                    return Thread.State.NEW;
                } else {
                    return Thread.State.RUNNABLE;
                }
            case UNPARKED:
            case UNBLOCKED:
            case YIELDED:
                // runnable, not mounted
                return Thread.State.RUNNABLE;
            case RUNNING:
                // if mounted then return state of carrier thread
                if (Thread.currentThread() != this) {
                    disableSuspendAndPreempt();
                    try {
                        synchronized (carrierThreadAccessLock()) {
                            Thread carrierThread = this.carrierThread;
                            if (carrierThread != null) {
                                return carrierThread.threadState();
                            }
                        }
                    } finally {
                        enableSuspendAndPreempt();
                    }
                }
                // runnable, mounted
                return Thread.State.RUNNABLE;
            case PARKING:
            case TIMED_PARKING:
            case WAITING:
            case TIMED_WAITING:
            case YIELDING:
                // runnable, in transition
                return Thread.State.RUNNABLE;
            case PARKED:
            case PINNED:
            case WAIT:
                return Thread.State.WAITING;
            case TIMED_PARKED:
            case TIMED_PINNED:
            case TIMED_WAIT:
                return Thread.State.TIMED_WAITING;
            case BLOCKING:
            case BLOCKED:
                return Thread.State.BLOCKED;
            case TERMINATED:
                return Thread.State.TERMINATED;
            default:
                throw new InternalError();
        }
    }

    @Override
    boolean alive() {
        int s = state;
        return (s != NEW && s != TERMINATED);
    }

    @Override
    boolean isTerminated() {
        return (state == TERMINATED);
    }

    @Override
    StackTraceElement[] asyncGetStackTrace() {
        StackTraceElement[] stackTrace;
        do {
            stackTrace = (carrierThread != null)
                    ? super.asyncGetStackTrace()  // mounted
                    : tryGetStackTrace();         // unmounted
            if (stackTrace == null) {
                Thread.yield();
            }
        } while (stackTrace == null);
        return stackTrace;
    }

    /**
     * Returns the stack trace for this virtual thread if it is unmounted.
     * Returns null if the thread is mounted or in transition.
     */
    private StackTraceElement[] tryGetStackTrace() {
        int initialState = state() & ~SUSPENDED;
        switch (initialState) {
            case NEW, STARTED, TERMINATED -> {
                return new StackTraceElement[0];  // unmounted, empty stack
            }
            case RUNNING, PINNED, TIMED_PINNED -> {
                return null;   // mounted
            }
            case PARKED, TIMED_PARKED, BLOCKED, WAIT, TIMED_WAIT -> {
                // unmounted, not runnable
            }
            case UNPARKED, UNBLOCKED, YIELDED -> {
                // unmounted, runnable
            }
            case PARKING, TIMED_PARKING, BLOCKING, YIELDING, WAITING, TIMED_WAITING -> {
                return null;  // in transition
            }
            default -> throw new InternalError("" + initialState);
        }

        // thread is unmounted, prevent it from continuing
        int suspendedState = initialState | SUSPENDED;
        if (!compareAndSetState(initialState, suspendedState)) {
            return null;
        }

        // get stack trace and restore state
        StackTraceElement[] stack;
        try {
            stack = cont.getStackTrace();
        } finally {
            assert state == suspendedState;
            setState(initialState);
        }
        boolean resubmit = switch (initialState) {
            case UNPARKED, UNBLOCKED, YIELDED -> {
                // resubmit as task may have run while suspended
                yield true;
            }
            case PARKED, TIMED_PARKED -> {
                // resubmit if unparked while suspended
                yield parkPermit && compareAndSetState(initialState, UNPARKED);
            }
            case BLOCKED -> {
                // resubmit if unblocked while suspended
                yield blockPermit && compareAndSetState(BLOCKED, UNBLOCKED);
            }
            case WAIT, TIMED_WAIT -> {
                // resubmit if notified or interrupted while waiting (Object.wait)
                // waitTimeoutExpired will retry if the timed expired when suspended
                yield (notified || interrupted) && compareAndSetState(initialState, UNBLOCKED);
            }
            default -> throw new InternalError();
        };
        if (resubmit) {
            submitRunContinuation();
        }
        return stack;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("VirtualThread[#");
        sb.append(threadId());
        String name = getName();
        if (!name.isEmpty()) {
            sb.append(",");
            sb.append(name);
        }
        sb.append("]/");

        // add the carrier state and thread name when mounted
        boolean mounted;
        if (Thread.currentThread() == this) {
            mounted = appendCarrierInfo(sb);
        } else {
            disableSuspendAndPreempt();
            try {
                synchronized (carrierThreadAccessLock()) {
                    mounted = appendCarrierInfo(sb);
                }
            } finally {
                enableSuspendAndPreempt();
            }
        }

        // add virtual thread state when not mounted
        if (!mounted) {
            String stateAsString = threadState().toString();
            sb.append(stateAsString.toLowerCase(Locale.ROOT));
        }

        return sb.toString();
    }

    /**
     * Appends the carrier state and thread name to the string buffer if mounted.
     * @return true if mounted, false if not mounted
     */
    private boolean appendCarrierInfo(StringBuilder sb) {
        assert Thread.currentThread() == this || Thread.holdsLock(carrierThreadAccessLock());
        Thread carrier = carrierThread;
        if (carrier != null) {
            String stateAsString = carrier.threadState().toString();
            sb.append(stateAsString.toLowerCase(Locale.ROOT));
            sb.append('@');
            sb.append(carrier.getName());
            return true;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return (int) threadId();
    }

    @Override
    public boolean equals(Object obj) {
        return obj == this;
    }

    /**
     * Returns the termination object, creating it if needed.
     */
    private CountDownLatch getTermination() {
        CountDownLatch termination = this.termination;
        if (termination == null) {
            termination = new CountDownLatch(1);
            if (!U.compareAndSetReference(this, TERMINATION, null, termination)) {
                termination = this.termination;
            }
        }
        return termination;
    }

    /**
     * Returns the lock object to synchronize on when accessing carrierThread.
     * The lock prevents carrierThread from being reset to null during unmount.
     */
    private Object carrierThreadAccessLock() {
        // return interruptLock as unmount has to coordinate with interrupt
        return interruptLock;
    }

    /**
     * Returns a lock object for coordinating timed-wait setup and timeout handling.
     */
    private Object timedWaitLock() {
        // use this object for now to avoid the overhead of introducing another lock
        return runContinuation;
    }

    /**
     * Disallow the current thread be suspended or preempted.
     */
    private void disableSuspendAndPreempt() {
        notifyJvmtiDisableSuspend(true);
        Continuation.pin();
    }

    /**
     * Allow the current thread be suspended or preempted.
     */
    private void enableSuspendAndPreempt() {
        Continuation.unpin();
        notifyJvmtiDisableSuspend(false);
    }

    // -- wrappers for get/set of state, parking permit, and carrier thread --

    private int state() {
        return state;  // volatile read
    }

    private void setState(int newValue) {
        state = newValue;  // volatile write
    }

    private boolean compareAndSetState(int expectedValue, int newValue) {
        return U.compareAndSetInt(this, STATE, expectedValue, newValue);
    }

    private boolean compareAndSetOnWaitingList(boolean expectedValue, boolean newValue) {
        return U.compareAndSetBoolean(this, ON_WAITING_LIST, expectedValue, newValue);
    }

    private void setParkPermit(boolean newValue) {
        if (parkPermit != newValue) {
            parkPermit = newValue;
        }
    }

    private boolean getAndSetParkPermit(boolean newValue) {
        if (parkPermit != newValue) {
            return U.getAndSetBoolean(this, PARK_PERMIT, newValue);
        } else {
            return newValue;
        }
    }

    private void setCarrierThread(Thread carrier) {
        // U.putReferenceRelease(this, CARRIER_THREAD, carrier);
        this.carrierThread = carrier;
    }

    // -- JVM TI support --

    @IntrinsicCandidate
    @JvmtiMountTransition
    private native void notifyJvmtiStart();

    @IntrinsicCandidate
    @JvmtiMountTransition
    private native void notifyJvmtiEnd();

    @IntrinsicCandidate
    @JvmtiMountTransition
    private native void notifyJvmtiMount(boolean hide);

    @IntrinsicCandidate
    @JvmtiMountTransition
    private native void notifyJvmtiUnmount(boolean hide);

    @IntrinsicCandidate
    private static native void notifyJvmtiDisableSuspend(boolean enter);

    private static native void registerNatives();
    static {
        registerNatives();

        // ensure VTHREAD_GROUP is created, may be accessed by JVMTI
        var group = Thread.virtualThreadGroup();
    }

    /**
     * Creates the default ForkJoinPool scheduler.
     */
    private static ForkJoinPool createDefaultScheduler() {
        ForkJoinWorkerThreadFactory factory = pool -> new CarrierThread(pool);
        int parallelism, maxPoolSize, minRunnable;
        String parallelismValue = System.getProperty("jdk.virtualThreadScheduler.parallelism");
        String maxPoolSizeValue = System.getProperty("jdk.virtualThreadScheduler.maxPoolSize");
        String minRunnableValue = System.getProperty("jdk.virtualThreadScheduler.minRunnable");
        if (parallelismValue != null) {
            parallelism = Integer.parseInt(parallelismValue);
        } else {
            parallelism = Runtime.getRuntime().availableProcessors();
        }
        if (maxPoolSizeValue != null) {
            maxPoolSize = Integer.parseInt(maxPoolSizeValue);
            parallelism = Integer.min(parallelism, maxPoolSize);
        } else {
            maxPoolSize = Integer.max(parallelism, 256);
        }
        if (minRunnableValue != null) {
            minRunnable = Integer.parseInt(minRunnableValue);
        } else {
            minRunnable = Integer.max(parallelism / 2, 1);
        }
        Thread.UncaughtExceptionHandler handler = (t, e) -> { };
        boolean asyncMode = true; // FIFO
        return new ForkJoinPool(parallelism, factory, handler, asyncMode,
                     0, maxPoolSize, minRunnable, pool -> true, 30, SECONDS);
    }

    /**
     * Schedule a runnable task to run after a delay.
     */
    private Future<?> schedule(Runnable command, long delay, TimeUnit unit) {
        if (scheduler instanceof ForkJoinPool pool) {
            return pool.schedule(command, delay, unit);
        } else {
            return DelayedTaskSchedulers.schedule(command, delay, unit);
        }
    }

    /**
     * Supports scheduling a runnable task to run after a delay. It uses a number
     * of ScheduledThreadPoolExecutor instances to reduce contention on the delayed
     * work queue used. This class is used when using a custom scheduler.
     */
    private static class DelayedTaskSchedulers {
        private static final ScheduledExecutorService[] INSTANCE = createDelayedTaskSchedulers();

        static Future<?> schedule(Runnable command, long delay, TimeUnit unit) {
            long tid = Thread.currentThread().threadId();
            int index = (int) tid & (INSTANCE.length - 1);
            return INSTANCE[index].schedule(command, delay, unit);
        }

        private static ScheduledExecutorService[] createDelayedTaskSchedulers() {
            String propName = "jdk.virtualThreadScheduler.timerQueues";
            String propValue = System.getProperty(propName);
            int queueCount;
            if (propValue != null) {
                queueCount = Integer.parseInt(propValue);
                if (queueCount != Integer.highestOneBit(queueCount)) {
                    throw new RuntimeException("Value of " + propName + " must be power of 2");
                }
            } else {
                int ncpus = Runtime.getRuntime().availableProcessors();
                queueCount = Math.max(Integer.highestOneBit(ncpus / 4), 1);
            }
            var schedulers = new ScheduledExecutorService[queueCount];
            for (int i = 0; i < queueCount; i++) {
                ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor)
                    Executors.newScheduledThreadPool(1, task -> {
                        Thread t = InnocuousThread.newThread("VirtualThread-unparker", task);
                        t.setDaemon(true);
                        return t;
                    });
                stpe.setRemoveOnCancelPolicy(true);
                schedulers[i] = stpe;
            }
            return schedulers;
        }
    }

    /**
     * Schedule virtual threads that are ready to be scheduled after they blocked on
     * monitor enter.
     */
    private static void unblockVirtualThreads() {
        while (true) {
            VirtualThread vthread = takeVirtualThreadListToUnblock();
            while (vthread != null) {
                assert vthread.onWaitingList;
                VirtualThread nextThread = vthread.next;

                // remove from list and unblock
                vthread.next = null;
                boolean changed = vthread.compareAndSetOnWaitingList(true, false);
                assert changed;
                vthread.unblock();

                vthread = nextThread;
            }
        }
    }

    /**
     * Retrieves the list of virtual threads that are waiting to be unblocked, waiting
     * if necessary until a list of one or more threads becomes available.
     */
    private static native VirtualThread takeVirtualThreadListToUnblock();

    static {
        var unblocker = InnocuousThread.newThread("VirtualThread-unblocker",
                VirtualThread::unblockVirtualThreads);
        unblocker.setDaemon(true);
        unblocker.start();
    }
}