/*
 * Copyright (c) 1998, 2007, 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.
 */

#include "util.h"
#include "eventHandler.h"
#include "threadControl.h"
#include "commonRef.h"
#include "eventHelper.h"
#include "stepControl.h"
#include "invoker.h"
#include "bag.h"

#define HANDLING_EVENT(node) ((node)->current_ei != 0)

/*
 * Collection of info for properly handling co-located events.
 * If the ei field is non-zero, then one of the possible
 * co-located events has been posted and the other fields describe
 * the event's location.
 */
typedef struct CoLocatedEventInfo_ {
    EventIndex ei;
    jclass    clazz;
    jmethodID method;
    jlocation location;
} CoLocatedEventInfo;

/**
 * The main data structure in threadControl is the ThreadNode.
 * This is a per-thread structure that is allocated on the
 * first event that occurs in a thread. It is freed after the
 * thread's thread end event has completed processing. The
 * structure contains state information on its thread including
 * suspend counts. It also acts as a repository for other
 * per-thread state such as the current method invocation or
 * current step.
 *
 * suspendCount is the number of outstanding suspends
 * from the debugger. suspends from the app itself are
 * not included in this count.
 */
typedef struct ThreadNode {
    jthread thread;
    unsigned int toBeResumed : 1;
    unsigned int pendingInterrupt : 1;
    unsigned int isDebugThread : 1;
    unsigned int suspendOnStart : 1;
    unsigned int isStarted : 1;
    unsigned int popFrameEvent : 1;
    unsigned int popFrameProceed : 1;
    unsigned int popFrameThread : 1;
    EventIndex current_ei;
    jobject pendingStop;
    jint suspendCount;
    jint resumeFrameDepth; /* !=0 => This thread is in a call to Thread.resume() */
    jvmtiEventMode instructionStepMode;
    StepRequest currentStep;
    InvokeRequest currentInvoke;
    struct bag *eventBag;
    CoLocatedEventInfo cleInfo;
    struct ThreadNode *next;
    struct ThreadNode *prev;
    jlong frameGeneration;
    struct ThreadList *list;  /* Tells us what list this thread is in */
} ThreadNode;

static jint suspendAllCount;

typedef struct ThreadList {
    ThreadNode *first;
} ThreadList;

/*
 * popFrameEventLock is used to notify that the event has been received
 */
static jrawMonitorID popFrameEventLock = NULL;

/*
 * popFrameProceedLock is used to assure that the event thread is
 * re-suspended immediately after the event is acknowledged.
 */
static jrawMonitorID popFrameProceedLock = NULL;

static jrawMonitorID threadLock;
static jlocation resumeLocation;
static HandlerNode *breakpointHandlerNode;
static HandlerNode *framePopHandlerNode;
static HandlerNode *catchHandlerNode;

static jvmtiError threadControl_removeDebugThread(jthread thread);

/*
 * Threads which have issued thread start events and not yet issued thread
 * end events are maintained in the "runningThreads" list. All other threads known
 * to this module are kept in the "otherThreads" list.
 */
static ThreadList runningThreads;
static ThreadList otherThreads;

#define MAX_DEBUG_THREADS 10
static int debugThreadCount;
static jthread debugThreads[MAX_DEBUG_THREADS];

typedef struct DeferredEventMode {
    EventIndex ei;
    jvmtiEventMode mode;
    jthread thread;
    struct DeferredEventMode *next;
} DeferredEventMode;

typedef struct {
    DeferredEventMode *first;
    DeferredEventMode *last;
} DeferredEventModeList;

static DeferredEventModeList deferredEventModes;

static jint
getStackDepth(jthread thread)
{
    jint count = 0;
    jvmtiError error;

    error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
                        (gdata->jvmti, thread, &count);
    if (error != JVMTI_ERROR_NONE) {
        EXIT_ERROR(error, "getting frame count");
    }
    return count;
}

/* Get the state of the thread direct from JVMTI */
static jvmtiError
threadState(jthread thread, jint *pstate)
{
    *pstate = 0;
    return JVMTI_FUNC_PTR(gdata->jvmti,GetThreadState)
                        (gdata->jvmti, thread, pstate);
}

/* Set TLS on a specific jthread to the ThreadNode* */
static void
setThreadLocalStorage(jthread thread, ThreadNode *node)
{
    jvmtiError  error;

    error = JVMTI_FUNC_PTR(gdata->jvmti,SetThreadLocalStorage)
            (gdata->jvmti, thread, (void*)node);
    if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE ) {
        /* Just return, thread hasn't started yet */
        return;
    } else if ( error != JVMTI_ERROR_NONE ) {
        /* The jthread object must be valid, so this must be a fatal error */
        EXIT_ERROR(error, "cannot set thread local storage");
    }
}

/* Get TLS on a specific jthread, which is the ThreadNode* */
static ThreadNode *
getThreadLocalStorage(jthread thread)
{
    jvmtiError  error;
    ThreadNode *node;

    node = NULL;
    error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadLocalStorage)
            (gdata->jvmti, thread, (void**)&node);
    if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE ) {
        /* Just return NULL, thread hasn't started yet */
        return NULL;
    } else if ( error != JVMTI_ERROR_NONE ) {
        /* The jthread object must be valid, so this must be a fatal error */
        EXIT_ERROR(error, "cannot get thread local storage");
    }
    return node;
}

/* Search list for nodes that don't have TLS set and match this thread.
 *   It assumed that this logic is never dealing with terminated threads,
 *   since the ThreadEnd events always delete the ThreadNode while the
 *   jthread is still alive.  So we can only look at the ThreadNode's that
 *   have never had their TLS set, making the search much faster.
 *   But keep in mind, this kind of search should rarely be needed.
 */
static ThreadNode *
nonTlsSearch(JNIEnv *env, ThreadList *list, jthread thread)
{
    ThreadNode *node;

    for (node = list->first; node != NULL; node = node->next) {
        if (isSameObject(env, node->thread, thread)) {
            break;
        }
    }
    return node;
}

/*
 * These functions maintain the linked list of currently running threads.
 * All assume that the threadLock is held before calling.
 * If list==NULL, search both lists.
 */
static ThreadNode *
findThread(ThreadList *list, jthread thread)
{
    ThreadNode *node;

    /* Get thread local storage for quick thread -> node access */
    node = getThreadLocalStorage(thread);

    /* In some rare cases we might get NULL, so we check the list manually for
     *   any threads that we could match.
     */
    if ( node == NULL ) {
        JNIEnv *env;

        env = getEnv();
        if ( list != NULL ) {
            node = nonTlsSearch(env, list, thread);
        } else {
            node = nonTlsSearch(env, &runningThreads, thread);
            if ( node == NULL ) {
                node = nonTlsSearch(env, &otherThreads, thread);
            }
        }
        if ( node != NULL ) {
            /* Here we make another attempt to set TLS, it's ok if this fails */
            setThreadLocalStorage(thread, (void*)node);
        }
    }

    /* If a list is supplied, only return ones in this list */
    if ( node != NULL && list != NULL && node->list != list ) {
        return NULL;
    }
    return node;
}

/* Remove a ThreadNode from a ThreadList */
static void
removeNode(ThreadList *list, ThreadNode *node)
{
    ThreadNode *prev;
    ThreadNode *next;

    prev = node->prev;
    next = node->next;
    if ( prev != NULL ) {
        prev->next = next;
    }
    if ( next != NULL ) {
        next->prev = prev;
    }
    if ( prev == NULL ) {
        list->first = next;
    }
    node->next = NULL;
    node->prev = NULL;
    node->list = NULL;
}

/* Add a ThreadNode to a ThreadList */
static void
addNode(ThreadList *list, ThreadNode *node)
{
    node->next = NULL;
    node->prev = NULL;
    node->list = NULL;
    if ( list->first == NULL ) {
        list->first = node;
    } else {
        list->first->prev = node;
        node->next = list->first;
        list->first = node;
    }
    node->list = list;
}

static ThreadNode *
insertThread(JNIEnv *env, ThreadList *list, jthread thread)
{
    ThreadNode *node;
    struct bag *eventBag;

    node = findThread(list, thread);
    if (node == NULL) {
        node = jvmtiAllocate(sizeof(*node));
        if (node == NULL) {
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table entry");
            return NULL;
        }
        (void)memset(node, 0, sizeof(*node));
        eventBag = eventHelper_createEventBag();
        if (eventBag == NULL) {
            jvmtiDeallocate(node);
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table entry");
            return NULL;
        }

        /*
         * Init all flags false, all refs NULL, all counts 0
         */

        saveGlobalRef(env, thread, &(node->thread));
        if (node->thread == NULL) {
            jvmtiDeallocate(node);
            bagDestroyBag(eventBag);
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table entry");
            return NULL;
        }
        /*
         * Remember if it is a debug thread
         */
        if (threadControl_isDebugThread(node->thread)) {
            node->isDebugThread = JNI_TRUE;
        } else if (suspendAllCount > 0){
            /*
             * If there is a pending suspendAll, all new threads should
             * be initialized as if they were suspended by the suspendAll,
             * and the thread will need to be suspended when it starts.
             */
            node->suspendCount = suspendAllCount;
            node->suspendOnStart = JNI_TRUE;
        }
        node->current_ei = 0;
        node->instructionStepMode = JVMTI_DISABLE;
        node->eventBag = eventBag;
        addNode(list, node);

        /* Set thread local storage for quick thread -> node access.
         *   Some threads may not be in a state that allows setting of TLS,
         *   which is ok, see findThread, it deals with threads without TLS set.
         */
        setThreadLocalStorage(node->thread, (void*)node);
    }

    return node;
}

static void
clearThread(JNIEnv *env, ThreadNode *node)
{
    if (node->pendingStop != NULL) {
        tossGlobalRef(env, &(node->pendingStop));
    }
    stepControl_clearRequest(node->thread, &node->currentStep);
    if (node->isDebugThread) {
        (void)threadControl_removeDebugThread(node->thread);
    }
    /* Clear out TLS on this thread (just a cleanup action) */
    setThreadLocalStorage(node->thread, NULL);
    tossGlobalRef(env, &(node->thread));
    bagDestroyBag(node->eventBag);
    jvmtiDeallocate(node);
}

static void
removeThread(JNIEnv *env, ThreadList *list, jthread thread)
{
    ThreadNode *node;

    node = findThread(list, thread);
    if (node != NULL) {
        removeNode(list, node);
        clearThread(env, node);
    }
}

static void
removeResumed(JNIEnv *env, ThreadList *list)
{
    ThreadNode *node;

    node = list->first;
    while (node != NULL) {
        ThreadNode *temp = node->next;
        if (node->suspendCount == 0) {
            removeThread(env, list, node->thread);
        }
        node = temp;
    }
}

static void
moveNode(ThreadList *source, ThreadList *dest, ThreadNode *node)
{
    removeNode(source, node);
    JDI_ASSERT(findThread(dest, node->thread) == NULL);
    addNode(dest, node);
}

typedef jvmtiError (*ThreadEnumerateFunction)(JNIEnv *, ThreadNode *, void *);

static jvmtiError
enumerateOverThreadList(JNIEnv *env, ThreadList *list,
                        ThreadEnumerateFunction function, void *arg)
{
    ThreadNode *node;
    jvmtiError error = JVMTI_ERROR_NONE;

    for (node = list->first; node != NULL; node = node->next) {
        error = (*function)(env, node, arg);
        if ( error != JVMTI_ERROR_NONE ) {
            break;
        }
    }
    return error;
}

static void
insertEventMode(DeferredEventModeList *list, DeferredEventMode *eventMode)
{
    if (list->last != NULL) {
        list->last->next = eventMode;
    } else {
        list->first = eventMode;
    }
    list->last = eventMode;
}

static void
removeEventMode(DeferredEventModeList *list, DeferredEventMode *eventMode, DeferredEventMode *prev)
{
    if (prev == NULL) {
        list->first = eventMode->next;
    } else {
        prev->next = eventMode->next;
    }
    if (eventMode->next == NULL) {
        list->last = prev;
    }
}

static jvmtiError
addDeferredEventMode(JNIEnv *env, jvmtiEventMode mode, EventIndex ei, jthread thread)
{
    DeferredEventMode *eventMode;

    /*LINTED*/
    eventMode = jvmtiAllocate((jint)sizeof(DeferredEventMode));
    if (eventMode == NULL) {
        return AGENT_ERROR_OUT_OF_MEMORY;
    }
    eventMode->thread = NULL;
    saveGlobalRef(env, thread, &(eventMode->thread));
    eventMode->mode = mode;
    eventMode->ei = ei;
    eventMode->next = NULL;
    insertEventMode(&deferredEventModes, eventMode);
    return JVMTI_ERROR_NONE;
}

static void
freeDeferredEventModes(JNIEnv *env)
{
    DeferredEventMode *eventMode;
    eventMode = deferredEventModes.first;
    while (eventMode != NULL) {
        DeferredEventMode *next;
        next = eventMode->next;
        tossGlobalRef(env, &(eventMode->thread));
        jvmtiDeallocate(eventMode);
        eventMode = next;
    }
    deferredEventModes.first = NULL;
    deferredEventModes.last = NULL;
}

static jvmtiError
threadSetEventNotificationMode(ThreadNode *node,
        jvmtiEventMode mode, EventIndex ei, jthread thread)
{
    jvmtiError error;

    /* record single step mode */
    if (ei == EI_SINGLE_STEP) {
        node->instructionStepMode = mode;
    }
    error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
        (gdata->jvmti, mode, eventIndex2jvmti(ei), thread);
    return error;
}

static void
processDeferredEventModes(JNIEnv *env, jthread thread, ThreadNode *node)
{
    jvmtiError error;
    DeferredEventMode *eventMode;
    DeferredEventMode *prev;

    prev = NULL;
    eventMode = deferredEventModes.first;
    while (eventMode != NULL) {
        DeferredEventMode *next = eventMode->next;
        if (isSameObject(env, thread, eventMode->thread)) {
            error = threadSetEventNotificationMode(node,
                    eventMode->mode, eventMode->ei, eventMode->thread);
            if (error != JVMTI_ERROR_NONE) {
                EXIT_ERROR(error, "cannot process deferred thread event notifications at thread start");
            }
            removeEventMode(&deferredEventModes, eventMode, prev);
            tossGlobalRef(env, &(eventMode->thread));
            jvmtiDeallocate(eventMode);
        } else {
            prev = eventMode;
        }
        eventMode = next;
    }
}

static void
getLocks(void)
{
    /*
     * Anything which might be locked as part of the handling of
     * a JVMTI event (which means: might be locked by an application
     * thread) needs to be grabbed here. This allows thread control
     * code to safely suspend and resume the application threads
     * while ensuring they don't hold a critical lock.
     */

    eventHandler_lock();
    invoker_lock();
    eventHelper_lock();
    stepControl_lock();
    commonRef_lock();
    debugMonitorEnter(threadLock);

}

static void
releaseLocks(void)
{
    debugMonitorExit(threadLock);
    commonRef_unlock();
    stepControl_unlock();
    eventHelper_unlock();
    invoker_unlock();
    eventHandler_unlock();
}

void
threadControl_initialize(void)
{
    jlocation unused;
    jvmtiError error;

    suspendAllCount = 0;
    runningThreads.first = NULL;
    otherThreads.first = NULL;
    debugThreadCount = 0;
    threadLock = debugMonitorCreate("JDWP Thread Lock");
    if (gdata->threadClass==NULL) {
        EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "no java.lang.thread class");
    }
    if (gdata->threadResume==0) {
        EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "cannot resume thread");
    }
    /* Get the java.lang.Thread.resume() method beginning location */
    error = methodLocation(gdata->threadResume, &resumeLocation, &unused);
    if (error != JVMTI_ERROR_NONE) {
        EXIT_ERROR(error, "getting method location");
    }
}

static jthread
getResumee(jthread resumingThread)
{
    jthread resumee = NULL;
    jvmtiError error;
    jobject object;
    FrameNumber fnum = 0;

    error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
                    (gdata->jvmti, resumingThread, fnum, 0, &object);
    if (error == JVMTI_ERROR_NONE) {
        resumee = object;
    }
    return resumee;
}


static jboolean
pendingAppResume(jboolean includeSuspended)
{
    ThreadList *list;
    ThreadNode *node;

    list = &runningThreads;
    node = list->first;
    while (node != NULL) {
        if (node->resumeFrameDepth > 0) {
            if (includeSuspended) {
                return JNI_TRUE;
            } else {
                jvmtiError error;
                jint       state;

                error = threadState(node->thread, &state);
                if (error != JVMTI_ERROR_NONE) {
                    EXIT_ERROR(error, "getting thread state");
                }
                if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) {
                    return JNI_TRUE;
                }
            }
        }
        node = node->next;
    }
    return JNI_FALSE;
}

static void
notifyAppResumeComplete(void)
{
    debugMonitorNotifyAll(threadLock);
    if (!pendingAppResume(JNI_TRUE)) {
        if (framePopHandlerNode != NULL) {
            (void)eventHandler_free(framePopHandlerNode);
            framePopHandlerNode = NULL;
        }
        if (catchHandlerNode != NULL) {
            (void)eventHandler_free(catchHandlerNode);
            catchHandlerNode = NULL;
        }
    }
}

static void
handleAppResumeCompletion(JNIEnv *env, EventInfo *evinfo,
                          HandlerNode *handlerNode,
                          struct bag *eventBag)
{
    ThreadNode *node;
    jthread     thread;

    thread = evinfo->thread;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        if (node->resumeFrameDepth > 0) {
            jint compareDepth = getStackDepth(thread);
            if (evinfo->ei == EI_FRAME_POP) {
                compareDepth--;
            }
            if (compareDepth < node->resumeFrameDepth) {
                node->resumeFrameDepth = 0;
                notifyAppResumeComplete();
            }
        }
    }

    debugMonitorExit(threadLock);
}

static void
blockOnDebuggerSuspend(jthread thread)
{
    ThreadNode *node;

    node = findThread(NULL, thread);
    if (node != NULL) {
        while (node && node->suspendCount > 0) {
            debugMonitorWait(threadLock);
            node = findThread(NULL, thread);
        }
    }
}

static void
trackAppResume(jthread thread)
{
    jvmtiError  error;
    FrameNumber fnum;
    ThreadNode *node;

    fnum = 0;
    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        JDI_ASSERT(node->resumeFrameDepth == 0);
        error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
                        (gdata->jvmti, thread, fnum);
        if (error == JVMTI_ERROR_NONE) {
            jint frameDepth = getStackDepth(thread);
            if ((frameDepth > 0) && (framePopHandlerNode == NULL)) {
                framePopHandlerNode = eventHandler_createInternalThreadOnly(
                                           EI_FRAME_POP,
                                           handleAppResumeCompletion,
                                           thread);
                catchHandlerNode = eventHandler_createInternalThreadOnly(
                                           EI_EXCEPTION_CATCH,
                                           handleAppResumeCompletion,
                                           thread);
                if ((framePopHandlerNode == NULL) ||
                    (catchHandlerNode == NULL)) {
                    (void)eventHandler_free(framePopHandlerNode);
                    framePopHandlerNode = NULL;
                    (void)eventHandler_free(catchHandlerNode);
                    catchHandlerNode = NULL;
                }
            }
            if ((framePopHandlerNode != NULL) &&
                (catchHandlerNode != NULL) &&
                (frameDepth > 0)) {
                node->resumeFrameDepth = frameDepth;
            }
        }
    }
}

static void
handleAppResumeBreakpoint(JNIEnv *env, EventInfo *evinfo,
                          HandlerNode *handlerNode,
                          struct bag *eventBag)
{
    jthread resumer = evinfo->thread;
    jthread resumee = getResumee(resumer);

    debugMonitorEnter(threadLock);
    if (resumee != NULL) {
        /*
         * Hold up any attempt to resume as long as the debugger
         * has suspended the resumee.
         */
        blockOnDebuggerSuspend(resumee);
    }

    if (resumer != NULL) {
        /*
         * Track the resuming thread by marking it as being within
         * a resume and by setting up for notification on
         * a frame pop or exception. We won't allow the debugger
         * to suspend threads while any thread is within a
         * call to resume. This (along with the block above)
         * ensures that when the debugger
         * suspends a thread it will remain suspended.
         */
        trackAppResume(resumer);
    }

    debugMonitorExit(threadLock);
}

void
threadControl_onConnect(void)
{
    breakpointHandlerNode = eventHandler_createInternalBreakpoint(
                 handleAppResumeBreakpoint, NULL,
                 gdata->threadClass, gdata->threadResume, resumeLocation);
}

void
threadControl_onDisconnect(void)
{
    if (breakpointHandlerNode != NULL) {
        (void)eventHandler_free(breakpointHandlerNode);
        breakpointHandlerNode = NULL;
    }
    if (framePopHandlerNode != NULL) {
        (void)eventHandler_free(framePopHandlerNode);
        framePopHandlerNode = NULL;
    }
    if (catchHandlerNode != NULL) {
        (void)eventHandler_free(catchHandlerNode);
        catchHandlerNode = NULL;
    }
}

void
threadControl_onHook(void)
{
    /*
     * As soon as the event hook is in place, we need to initialize
     * the thread list with already-existing threads. The threadLock
     * has been held since initialize, so we don't need to worry about
     * insertions or deletions from the event handlers while we do this
     */
    JNIEnv *env;

    env = getEnv();

    /*
     * Prevent any event processing until OnHook has been called
     */
    debugMonitorEnter(threadLock);

    WITH_LOCAL_REFS(env, 1) {

        jint threadCount;
        jthread *threads;

        threads = allThreads(&threadCount);
        if (threads == NULL) {
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table");
        } else {

            int i;

            for (i = 0; i < threadCount; i++) {
                ThreadNode *node;
                jthread thread = threads[i];
                node = insertThread(env, &runningThreads, thread);

                /*
                 * This is a tiny bit risky. We have to assume that the
                 * pre-existing threads have been started because we
                 * can't rely on a thread start event for them. The chances
                 * of a problem related to this are pretty slim though, and
                 * there's really no choice because without setting this flag
                 * there is no way to enable stepping and other events on
                 * the threads that already exist (e.g. the finalizer thread).
                 */
                node->isStarted = JNI_TRUE;
            }
        }

    } END_WITH_LOCAL_REFS(env)

    debugMonitorExit(threadLock);
}

static jvmtiError
commonSuspendByNode(ThreadNode *node)
{
    jvmtiError error;

    LOG_MISC(("thread=%p suspended", node->thread));
    error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThread)
                (gdata->jvmti, node->thread);

    /*
     * Mark for resume only if suspend succeeded
     */
    if (error == JVMTI_ERROR_NONE) {
        node->toBeResumed = JNI_TRUE;
    }

    /*
     * If the thread was suspended by another app thread,
     * do nothing and report no error (we won't resume it later).
     */
     if (error == JVMTI_ERROR_THREAD_SUSPENDED) {
        error = JVMTI_ERROR_NONE;
     }

     return error;
}

/*
 * Deferred suspends happen when the suspend is attempted on a thread
 * that is not started. Bookkeeping (suspendCount,etc.)
 * is handled by the original request, and once the thread actually
 * starts, an actual suspend is attempted. This function does the
 * deferred suspend without changing the bookkeeping that is already
 * in place.
 */
static jint
deferredSuspendThreadByNode(ThreadNode *node)
{
    jvmtiError error;

    error = JVMTI_ERROR_NONE;
    if (node->isDebugThread) {
        /* Ignore requests for suspending debugger threads */
        return JVMTI_ERROR_NONE;
    }

    /*
     * Do the actual suspend only if a subsequent resume hasn't
     * made it irrelevant.
     */
    if (node->suspendCount > 0) {
        error = commonSuspendByNode(node);

        /*
         * Attempt to clean up from any error by decrementing the
         * suspend count. This compensates for the increment that
         * happens when suspendOnStart is set to true.
         */
        if (error != JVMTI_ERROR_NONE) {
          node->suspendCount--;
        }
    }

    node->suspendOnStart = JNI_FALSE;

    debugMonitorNotifyAll(threadLock);

    return error;
}

static jvmtiError
suspendThreadByNode(ThreadNode *node)
{
    jvmtiError error = JVMTI_ERROR_NONE;
    if (node->isDebugThread) {
        /* Ignore requests for suspending debugger threads */
        return JVMTI_ERROR_NONE;
    }

    /*
     * Just increment the suspend count if we are waiting
     * for a deferred suspend.
     */
    if (node->suspendOnStart) {
        node->suspendCount++;
        return JVMTI_ERROR_NONE;
    }

    if (node->suspendCount == 0) {
        error = commonSuspendByNode(node);

        if (error == JVMTI_ERROR_THREAD_NOT_ALIVE) {
            /*
             * This error means that the thread is either a zombie or not yet
             * started. In either case, we ignore the error. If the thread
             * is a zombie, suspend/resume are no-ops. If the thread is not
             * started, it will be suspended for real during the processing
             * of its thread start event.
             */
            node->suspendOnStart = JNI_TRUE;
            error = JVMTI_ERROR_NONE;
        }
    }

    if (error == JVMTI_ERROR_NONE) {
        node->suspendCount++;
    }

    debugMonitorNotifyAll(threadLock);

    return error;
}

static jvmtiError
resumeThreadByNode(ThreadNode *node)
{
    jvmtiError error = JVMTI_ERROR_NONE;

    if (node->isDebugThread) {
        /* never suspended by debugger => don't ever try to resume */
        return JVMTI_ERROR_NONE;
    }
    if (node->suspendCount > 0) {
        node->suspendCount--;
        debugMonitorNotifyAll(threadLock);
        if ((node->suspendCount == 0) && node->toBeResumed &&
            !node->suspendOnStart) {
            LOG_MISC(("thread=%p resumed", node->thread));
            error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)
                        (gdata->jvmti, node->thread);
            node->frameGeneration++; /* Increment on each resume */
            node->toBeResumed = JNI_FALSE;
            if (error == JVMTI_ERROR_THREAD_NOT_ALIVE && !node->isStarted) {
                /*
                 * We successfully "suspended" this thread, but
                 * we never received a THREAD_START event for it.
                 * Since the thread never ran, we can ignore our
                 * failure to resume the thread.
                 */
                error = JVMTI_ERROR_NONE;
            }
        }
    }

    return error;
}

/*
 * Functions which respond to user requests to suspend/resume
 * threads.
 * Suspends and resumes add and subtract from a count respectively.
 * The thread is only suspended when the count goes from 0 to 1 and
 * resumed only when the count goes from 1 to 0.
 *
 * These functions suspend and resume application threads
 * without changing the
 * state of threads that were already suspended beforehand.
 * They must not be called from an application thread because
 * that thread may be suspended somewhere in the  middle of things.
 */
static void
preSuspend(void)
{
    getLocks();                     /* Avoid debugger deadlocks */

    /*
     * Delay any suspend while a call to java.lang.Thread.resume is in
     * progress (not including those in suspended threads). The wait is
     * timed because the threads suspended through
     * java.lang.Thread.suspend won't result in a notify even though
     * it may change the result of pendingAppResume()
     */
    while (pendingAppResume(JNI_FALSE)) {
        /*
         * This is ugly but we need to release the locks from getLocks
         * or else the notify will never happen. The locks must be
         * released and reacquired in the right order. else deadlocks
         * can happen. It is possible that, during this dance, the
         * notify will be missed, but since the wait needs to be timed
         * anyway, it won't be a disaster. Note that this code will
         * execute only on very rare occasions anyway.
         */
        releaseLocks();

        debugMonitorEnter(threadLock);
        debugMonitorTimedWait(threadLock, 1000);
        debugMonitorExit(threadLock);

        getLocks();
    }
}

static void
postSuspend(void)
{
    releaseLocks();
}

/*
 * This function must be called after preSuspend and before postSuspend.
 */
static jvmtiError
commonSuspend(JNIEnv *env, jthread thread, jboolean deferred)
{
    ThreadNode *node;

    /*
     * If the thread is not between its start and end events, we should
     * still suspend it. To keep track of things, add the thread
     * to a separate list of threads so that we'll resume it later.
     */
    node = findThread(&runningThreads, thread);
    if (node == NULL) {
        node = insertThread(env, &otherThreads, thread);
    }

    if ( deferred ) {
        return deferredSuspendThreadByNode(node);
    } else {
        return suspendThreadByNode(node);
    }
}


static jvmtiError
resumeCopyHelper(JNIEnv *env, ThreadNode *node, void *arg)
{
    if (node->isDebugThread) {
        /* never suspended by debugger => don't ever try to resume */
        return JVMTI_ERROR_NONE;
    }

    if (node->suspendCount > 1) {
        node->suspendCount--;
        /* nested suspend so just undo one level */
        return JVMTI_ERROR_NONE;
    }

    /*
     * This thread was marked for suspension since its THREAD_START
     * event came in during a suspendAll, but the helper hasn't
     * completed the job yet. We decrement the count so the helper
     * won't suspend this thread after we are done with the resumeAll.
     * Another case to be handled here is when the debugger suspends
     * the thread while the app has it suspended. In this case,
     * the toBeResumed flag has been cleared indicating that
     * the thread should not be resumed when the debugger does a resume.
     * In this case, we also have to decrement the suspend count.
     * If we don't then when the app resumes the thread and our Thread.resume
     * bkpt handler is called, blockOnDebuggerSuspend will not resume
     * the thread because suspendCount will be 1 meaning that the
     * debugger has the thread suspended.  See bug 6224859.
     */
    if (node->suspendCount == 1 && (!node->toBeResumed || node->suspendOnStart)) {
        node->suspendCount--;
        return JVMTI_ERROR_NONE;
    }

    if (arg == NULL) {
        /* nothing to hard resume so we're done */
        return JVMTI_ERROR_NONE;
    }

    /*
     * This is tricky. A suspendCount of 1 and toBeResumed means that
     * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called
     * on this thread. The check for !suspendOnStart is paranoia that
     * we inherited from resumeThreadByNode().
     */
    if (node->suspendCount == 1 && node->toBeResumed && !node->suspendOnStart) {
        jthread **listPtr = (jthread **)arg;

        **listPtr = node->thread;
        (*listPtr)++;
    }
    return JVMTI_ERROR_NONE;
}


static jvmtiError
resumeCountHelper(JNIEnv *env, ThreadNode *node, void *arg)
{
    if (node->isDebugThread) {
        /* never suspended by debugger => don't ever try to resume */
        return JVMTI_ERROR_NONE;
    }

    /*
     * This is tricky. A suspendCount of 1 and toBeResumed means that
     * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called
     * on this thread. The check for !suspendOnStart is paranoia that
     * we inherited from resumeThreadByNode().
     */
    if (node->suspendCount == 1 && node->toBeResumed && !node->suspendOnStart) {
        jint *counter = (jint *)arg;

        (*counter)++;
    }
    return JVMTI_ERROR_NONE;
}

static void *
newArray(jint length, size_t nbytes)
{
    void *ptr;
    ptr = jvmtiAllocate(length*(jint)nbytes);
    if ( ptr != NULL ) {
        (void)memset(ptr, 0, length*nbytes);
    }
    return ptr;
}

static void
deleteArray(void *ptr)
{
    jvmtiDeallocate(ptr);
}

/*
 * This function must be called with the threadLock held.
 *
 * Two facts conspire to make this routine complicated:
 *
 * 1) the VM doesn't support nested external suspend
 * 2) the original resumeAll code structure doesn't retrieve the
 *    entire thread list from JVMTI so we use the runningThreads
 *    list and two helpers to get the job done.
 *
 * Because we hold the threadLock, state seen by resumeCountHelper()
 * is the same state seen in resumeCopyHelper(). resumeCountHelper()
 * just counts up the number of threads to be hard resumed.
 * resumeCopyHelper() does the accounting for nested suspends and
 * special cases and, finally, populates the list of hard resume
 * threads to be passed to ResumeThreadList().
 *
 * At first glance, you might think that the accounting could be done
 * in resumeCountHelper(), but then resumeCopyHelper() would see
 * "post-resume" state in the accounting values (suspendCount and
 * toBeResumed) and would not be able to distinguish between a thread
 * that needs a hard resume versus a thread that is already running.
 */
static jvmtiError
commonResumeList(JNIEnv *env)
{
    jvmtiError   error;
    jint         i;
    jint         reqCnt;
    jthread     *reqList;
    jthread     *reqPtr;
    jvmtiError  *results;

    reqCnt = 0;

    /* count number of threads to hard resume */
    (void) enumerateOverThreadList(env, &runningThreads, resumeCountHelper,
                                   &reqCnt);
    if (reqCnt == 0) {
        /* nothing to hard resume so do just the accounting part */
        (void) enumerateOverThreadList(env, &runningThreads, resumeCopyHelper,
                                       NULL);
        return JVMTI_ERROR_NONE;
    }

    /*LINTED*/
    reqList = newArray(reqCnt, sizeof(jthread));
    if (reqList == NULL) {
        EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"resume request list");
    }
    /*LINTED*/
    results = newArray(reqCnt, sizeof(jvmtiError));
    if (results == NULL) {
        EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"resume list");
    }

    /* copy the jthread values for threads to hard resume */
    reqPtr = reqList;
    (void) enumerateOverThreadList(env, &runningThreads, resumeCopyHelper,
                                   &reqPtr);

    error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThreadList)
                (gdata->jvmti, reqCnt, reqList, results);
    for (i = 0; i < reqCnt; i++) {
        ThreadNode *node;

        node = findThread(&runningThreads, reqList[i]);
        if (node == NULL) {
            EXIT_ERROR(AGENT_ERROR_INVALID_THREAD,"missing entry in running thread table");
        }
        LOG_MISC(("thread=%p resumed as part of list", node->thread));

        /*
         * resumeThreadByNode() assumes that JVM/DI ResumeThread()
         * always works and does all the accounting updates. We do
         * the same here. We also don't clear the error.
         */
        node->suspendCount--;
        node->toBeResumed = JNI_FALSE;
        node->frameGeneration++; /* Increment on each resume */
    }
    deleteArray(results);
    deleteArray(reqList);

    debugMonitorNotifyAll(threadLock);

    return error;
}


/*
 * This function must be called after preSuspend and before postSuspend.
 */
static jvmtiError
commonSuspendList(JNIEnv *env, jint initCount, jthread *initList)
{
    jvmtiError  error;
    jint        i;
    jint        reqCnt;
    jthread    *reqList;

    error   = JVMTI_ERROR_NONE;
    reqCnt  = 0;
    reqList = newArray(initCount, sizeof(jthread));
    if (reqList == NULL) {
        EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"request list");
    }

    /*
     * Go through the initial list and see if we have anything to suspend.
     */
    for (i = 0; i < initCount; i++) {
        ThreadNode *node;

        /*
         * If the thread is not between its start and end events, we should
         * still suspend it. To keep track of things, add the thread
         * to a separate list of threads so that we'll resume it later.
         */
        node = findThread(&runningThreads, initList[i]);
        if (node == NULL) {
            node = insertThread(env, &otherThreads, initList[i]);
        }

        if (node->isDebugThread) {
            /* Ignore requests for suspending debugger threads */
            continue;
        }

        /*
         * Just increment the suspend count if we are waiting
         * for a deferred suspend or if this is a nested suspend.
         */
        if (node->suspendOnStart || node->suspendCount > 0) {
            node->suspendCount++;
            continue;
        }

        if (node->suspendCount == 0) {
            /* thread is not suspended yet so put it on the request list */
            reqList[reqCnt++] = initList[i];
        }
    }

    if (reqCnt > 0) {
        jvmtiError *results = newArray(reqCnt, sizeof(jvmtiError));

        if (results == NULL) {
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"suspend list results");
        }

        /*
         * We have something to suspend so try to do it.
         */
        error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThreadList)
                        (gdata->jvmti, reqCnt, reqList, results);
        for (i = 0; i < reqCnt; i++) {
            ThreadNode *node;

            node = findThread(NULL, reqList[i]);
            if (node == NULL) {
                EXIT_ERROR(AGENT_ERROR_INVALID_THREAD,"missing entry in thread tables");
            }
            LOG_MISC(("thread=%p suspended as part of list", node->thread));

            if (results[i] == JVMTI_ERROR_NONE) {
                /* thread was suspended as requested */
                node->toBeResumed = JNI_TRUE;
            } else if (results[i] == JVMTI_ERROR_THREAD_SUSPENDED) {
                /*
                 * If the thread was suspended by another app thread,
                 * do nothing and report no error (we won't resume it later).
                 */
                results[i] = JVMTI_ERROR_NONE;
            } else if (results[i] == JVMTI_ERROR_THREAD_NOT_ALIVE) {
                /*
                 * This error means that the suspend request failed
                 * because the thread is either a zombie or not yet
                 * started. In either case, we ignore the error. If the
                 * thread is a zombie, suspend/resume are no-ops. If the
                 * thread is not started, it will be suspended for real
                 * during the processing of its thread start event.
                 */
                node->suspendOnStart = JNI_TRUE;
                results[i] = JVMTI_ERROR_NONE;
            }

            /* count real, app and deferred (suspendOnStart) suspensions */
            if (results[i] == JVMTI_ERROR_NONE) {
                node->suspendCount++;
            }
        }
        deleteArray(results);
    }
    deleteArray(reqList);

    debugMonitorNotifyAll(threadLock);

    return error;
}


static jvmtiError
commonResume(jthread thread)
{
    jvmtiError  error;
    ThreadNode *node;

    /*
     * The thread is normally between its start and end events, but if
     * not, check the auxiliary list used by threadControl_suspendThread.
     */
    node = findThread(NULL, thread);

    /*
     * If the node is in neither list, the debugger never suspended
     * this thread, so do nothing.
     */
    error = JVMTI_ERROR_NONE;
    if (node != NULL) {
        error = resumeThreadByNode(node);
    }
    return error;
}


jvmtiError
threadControl_suspendThread(jthread thread, jboolean deferred)
{
    jvmtiError error;
    JNIEnv    *env;

    env = getEnv();

    log_debugee_location("threadControl_suspendThread()", thread, NULL, 0);

    preSuspend();
    error = commonSuspend(env, thread, deferred);
    postSuspend();

    return error;
}

jvmtiError
threadControl_resumeThread(jthread thread, jboolean do_unblock)
{
    jvmtiError error;
    JNIEnv    *env;

    env = getEnv();

    log_debugee_location("threadControl_resumeThread()", thread, NULL, 0);

    eventHandler_lock(); /* for proper lock order */
    debugMonitorEnter(threadLock);
    error = commonResume(thread);
    removeResumed(env, &otherThreads);
    debugMonitorExit(threadLock);
    eventHandler_unlock();

    if (do_unblock) {
        /* let eventHelper.c: commandLoop() know we resumed one thread */
        unblockCommandLoop();
    }

    return error;
}

jvmtiError
threadControl_suspendCount(jthread thread, jint *count)
{
    jvmtiError  error;
    ThreadNode *node;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node == NULL) {
        node = findThread(&otherThreads, thread);
    }

    error = JVMTI_ERROR_NONE;
    if (node != NULL) {
        *count = node->suspendCount;
    } else {
        /*
         * If the node is in neither list, the debugger never suspended
         * this thread, so the suspend count is 0.
         */
        *count = 0;
    }

    debugMonitorExit(threadLock);

    return error;
}

static jboolean
contains(JNIEnv *env, jthread *list, jint count, jthread item)
{
    int i;

    for (i = 0; i < count; i++) {
        if (isSameObject(env, list[i], item)) {
            return JNI_TRUE;
        }
    }
    return JNI_FALSE;
}


typedef struct {
    jthread *list;
    jint count;
} SuspendAllArg;

static jvmtiError
suspendAllHelper(JNIEnv *env, ThreadNode *node, void *arg)
{
    SuspendAllArg *saArg = (SuspendAllArg *)arg;
    jvmtiError error = JVMTI_ERROR_NONE;
    jthread *list = saArg->list;
    jint count = saArg->count;
    if (!contains(env, list, count, node->thread)) {
        error = commonSuspend(env, node->thread, JNI_FALSE);
    }
    return error;
}

jvmtiError
threadControl_suspendAll(void)
{
    jvmtiError error;
    JNIEnv    *env;

    env = getEnv();

    log_debugee_location("threadControl_suspendAll()", NULL, NULL, 0);

    preSuspend();

    /*
     * Get a list of all threads and suspend them.
     */
    WITH_LOCAL_REFS(env, 1) {

        jthread *threads;
        jint count;

        threads = allThreads(&count);
        if (threads == NULL) {
            error = AGENT_ERROR_OUT_OF_MEMORY;
            goto err;
        }
        if (canSuspendResumeThreadLists()) {
            error = commonSuspendList(env, count, threads);
            if (error != JVMTI_ERROR_NONE) {
                goto err;
            }
        } else {

            int i;

            for (i = 0; i < count; i++) {
                error = commonSuspend(env, threads[i], JNI_FALSE);

                if (error != JVMTI_ERROR_NONE) {
                    goto err;
                }
            }
        }

        /*
         * Update the suspend count of any threads not yet (or no longer)
         * in the thread list above.
         */
        {
            SuspendAllArg arg;
            arg.list = threads;
            arg.count = count;
            error = enumerateOverThreadList(env, &otherThreads,
                                            suspendAllHelper, &arg);
        }

        if (error == JVMTI_ERROR_NONE) {
            suspendAllCount++;
        }

    err: ;

    } END_WITH_LOCAL_REFS(env)

    postSuspend();

    return error;
}

static jvmtiError
resumeHelper(JNIEnv *env, ThreadNode *node, void *ignored)
{
    /*
     * Since this helper is called with the threadLock held, we
     * don't need to recheck to see if the node is still on one
     * of the two thread lists.
     */
    return resumeThreadByNode(node);
}

jvmtiError
threadControl_resumeAll(void)
{
    jvmtiError error;
    JNIEnv    *env;

    env = getEnv();

    log_debugee_location("threadControl_resumeAll()", NULL, NULL, 0);

    eventHandler_lock(); /* for proper lock order */
    debugMonitorEnter(threadLock);

    /*
     * Resume only those threads that the debugger has suspended. All
     * such threads must have a node in one of the thread lists, so there's
     * no need to get the whole thread list from JVMTI (unlike
     * suspendAll).
     */
    if (canSuspendResumeThreadLists()) {
        error = commonResumeList(env);
    } else {
        error = enumerateOverThreadList(env, &runningThreads,
                                        resumeHelper, NULL);
    }
    if ((error == JVMTI_ERROR_NONE) && (otherThreads.first != NULL)) {
        error = enumerateOverThreadList(env, &otherThreads,
                                        resumeHelper, NULL);
        removeResumed(env, &otherThreads);
    }

    if (suspendAllCount > 0) {
        suspendAllCount--;
    }

    debugMonitorExit(threadLock);
    eventHandler_unlock();
    /* let eventHelper.c: commandLoop() know we are resuming */
    unblockCommandLoop();

    return error;
}


StepRequest *
threadControl_getStepRequest(jthread thread)
{
    ThreadNode  *node;
    StepRequest *step;

    step = NULL;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        step = &node->currentStep;
    }

    debugMonitorExit(threadLock);

    return step;
}

InvokeRequest *
threadControl_getInvokeRequest(jthread thread)
{
    ThreadNode    *node;
    InvokeRequest *request;

    request = NULL;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL) {
         request = &node->currentInvoke;
    }

    debugMonitorExit(threadLock);

    return request;
}

jvmtiError
threadControl_addDebugThread(jthread thread)
{
    jvmtiError error;

    debugMonitorEnter(threadLock);
    if (debugThreadCount >= MAX_DEBUG_THREADS) {
        error = AGENT_ERROR_OUT_OF_MEMORY;
    } else {
        JNIEnv    *env;

        env = getEnv();
        debugThreads[debugThreadCount] = NULL;
        saveGlobalRef(env, thread, &(debugThreads[debugThreadCount]));
        if (debugThreads[debugThreadCount] == NULL) {
            error = AGENT_ERROR_OUT_OF_MEMORY;
        } else {
            debugThreadCount++;
            error = JVMTI_ERROR_NONE;
        }
    }
    debugMonitorExit(threadLock);
    return error;
}

static jvmtiError
threadControl_removeDebugThread(jthread thread)
{
    jvmtiError error;
    JNIEnv    *env;
    int        i;

    error = AGENT_ERROR_INVALID_THREAD;
    env   = getEnv();

    debugMonitorEnter(threadLock);
    for (i = 0; i< debugThreadCount; i++) {
        if (isSameObject(env, thread, debugThreads[i])) {
            int j;

            tossGlobalRef(env, &(debugThreads[i]));
            for (j = i+1; j < debugThreadCount; j++) {
                debugThreads[j-1] = debugThreads[j];
            }
            debugThreadCount--;
            error = JVMTI_ERROR_NONE;
            break;
        }
    }
    debugMonitorExit(threadLock);
    return error;
}

jboolean
threadControl_isDebugThread(jthread thread)
{
    int      i;
    jboolean rc;
    JNIEnv  *env;

    rc  = JNI_FALSE;
    env = getEnv();

    debugMonitorEnter(threadLock);
    for (i = 0; i < debugThreadCount; i++) {
        if (isSameObject(env, thread, debugThreads[i])) {
            rc = JNI_TRUE;
            break;
        }
    }
    debugMonitorExit(threadLock);
    return rc;
}

static void
initLocks(void)
{
    if (popFrameEventLock == NULL) {
        popFrameEventLock = debugMonitorCreate("JDWP PopFrame Event Lock");
        popFrameProceedLock = debugMonitorCreate("JDWP PopFrame Proceed Lock");
    }
}

static jboolean
getPopFrameThread(jthread thread)
{
    jboolean popFrameThread;

    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);
        if (node == NULL) {
            popFrameThread = JNI_FALSE;
        } else {
            popFrameThread = node->popFrameThread;
        }
    }
    debugMonitorExit(threadLock);

    return popFrameThread;
}

static void
setPopFrameThread(jthread thread, jboolean value)
{
    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);
        if (node == NULL) {
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
        } else {
            node->popFrameThread = value;
        }
    }
    debugMonitorExit(threadLock);
}

static jboolean
getPopFrameEvent(jthread thread)
{
    jboolean popFrameEvent;

    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);
        if (node == NULL) {
            popFrameEvent = JNI_FALSE;
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
        } else {
            popFrameEvent = node->popFrameEvent;
        }
    }
    debugMonitorExit(threadLock);

    return popFrameEvent;
}

static void
setPopFrameEvent(jthread thread, jboolean value)
{
    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);
        if (node == NULL) {
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
        } else {
            node->popFrameEvent = value;
            node->frameGeneration++; /* Increment on each resume */
        }
    }
    debugMonitorExit(threadLock);
}

static jboolean
getPopFrameProceed(jthread thread)
{
    jboolean popFrameProceed;

    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);
        if (node == NULL) {
            popFrameProceed = JNI_FALSE;
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
        } else {
            popFrameProceed = node->popFrameProceed;
        }
    }
    debugMonitorExit(threadLock);

    return popFrameProceed;
}

static void
setPopFrameProceed(jthread thread, jboolean value)
{
    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);
        if (node == NULL) {
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
        } else {
            node->popFrameProceed = value;
        }
    }
    debugMonitorExit(threadLock);
}

/**
 * Special event handler for events on the popped thread
 * that occur during the pop operation.
 */
static void
popFrameCompleteEvent(jthread thread)
{
      debugMonitorEnter(popFrameProceedLock);
      {
          /* notify that we got the event */
          debugMonitorEnter(popFrameEventLock);
          {
              setPopFrameEvent(thread, JNI_TRUE);
              debugMonitorNotify(popFrameEventLock);
          }
          debugMonitorExit(popFrameEventLock);

          /* make sure we get suspended again */
          setPopFrameProceed(thread, JNI_FALSE);
          while (getPopFrameProceed(thread) == JNI_FALSE) {
              debugMonitorWait(popFrameProceedLock);
          }
      }
      debugMonitorExit(popFrameProceedLock);
}

/**
 * Pop one frame off the stack of thread.
 * popFrameEventLock is already held
 */
static jvmtiError
popOneFrame(jthread thread)
{
    jvmtiError error;

    error = JVMTI_FUNC_PTR(gdata->jvmti,PopFrame)(gdata->jvmti, thread);
    if (error != JVMTI_ERROR_NONE) {
        return error;
    }

    /* resume the popped thread so that the pop occurs and so we */
    /* will get the event (step or method entry) after the pop */
    LOG_MISC(("thread=%p resumed in popOneFrame", thread));
    error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)(gdata->jvmti, thread);
    if (error != JVMTI_ERROR_NONE) {
        return error;
    }

    /* wait for the event to occur */
    setPopFrameEvent(thread, JNI_FALSE);
    while (getPopFrameEvent(thread) == JNI_FALSE) {
        debugMonitorWait(popFrameEventLock);
    }

    /* make sure not to suspend until the popped thread is on the wait */
    debugMonitorEnter(popFrameProceedLock);
    {
        /* return popped thread to suspended state */
        LOG_MISC(("thread=%p suspended in popOneFrame", thread));
        error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThread)(gdata->jvmti, thread);

        /* notify popped thread so it can proceed when resumed */
        setPopFrameProceed(thread, JNI_TRUE);
        debugMonitorNotify(popFrameProceedLock);
    }
    debugMonitorExit(popFrameProceedLock);

    return error;
}

/**
 * pop frames of the stack of 'thread' until 'frame' is popped.
 */
jvmtiError
threadControl_popFrames(jthread thread, FrameNumber fnum)
{
    jvmtiError error;
    jvmtiEventMode prevStepMode;
    jint framesPopped = 0;
    jint popCount;
    jboolean prevInvokeRequestMode;

    log_debugee_location("threadControl_popFrames()", thread, NULL, 0);

    initLocks();

    /* compute the number of frames to pop */
    popCount = fnum+1;
    if (popCount < 1) {
        return AGENT_ERROR_NO_MORE_FRAMES;
    }

    /* enable instruction level single step, but first note prev value */
    prevStepMode = threadControl_getInstructionStepMode(thread);

    /*
     * Fix bug 6517249.  The pop processing will disable invokes,
     * so remember if invokes are enabled now and restore
     * that state after we finish popping.
     */
    prevInvokeRequestMode = invoker_isEnabled(thread);

    error = threadControl_setEventMode(JVMTI_ENABLE,
                                       EI_SINGLE_STEP, thread);
    if (error != JVMTI_ERROR_NONE) {
        return error;
    }

    /* Inform eventHandler logic we are in a popFrame for this thread */
    debugMonitorEnter(popFrameEventLock);
    {
        setPopFrameThread(thread, JNI_TRUE);
        /* pop frames using single step */
        while (framesPopped++ < popCount) {
            error = popOneFrame(thread);
            if (error != JVMTI_ERROR_NONE) {
                break;
            }
        }
        setPopFrameThread(thread, JNI_FALSE);
    }
    debugMonitorExit(popFrameEventLock);

    /*  Reset StepRequest info (fromLine and stackDepth) after popframes
     *  only if stepping is enabled.
     */
    if (prevStepMode == JVMTI_ENABLE) {
        stepControl_resetRequest(thread);
    }

    if (prevInvokeRequestMode) {
        invoker_enableInvokeRequests(thread);
    }

    /* restore state */
    (void)threadControl_setEventMode(prevStepMode,
                               EI_SINGLE_STEP, thread);

    return error;
}

/* Check to see if any events are being consumed by a popFrame(). */
static jboolean
checkForPopFrameEvents(JNIEnv *env, EventIndex ei, jthread thread)
{
    if ( getPopFrameThread(thread) ) {
        switch (ei) {
            case EI_THREAD_START:
                /* Excuse me? */
                EXIT_ERROR(AGENT_ERROR_INTERNAL, "thread start during pop frame");
                break;
            case EI_THREAD_END:
                /* Thread wants to end? let it. */
                setPopFrameThread(thread, JNI_FALSE);
                popFrameCompleteEvent(thread);
                break;
            case EI_SINGLE_STEP:
                /* This is an event we requested to mark the */
                /*        completion of the pop frame */
                popFrameCompleteEvent(thread);
                return JNI_TRUE;
            case EI_BREAKPOINT:
            case EI_EXCEPTION:
            case EI_FIELD_ACCESS:
            case EI_FIELD_MODIFICATION:
            case EI_METHOD_ENTRY:
            case EI_METHOD_EXIT:
                /* Tell event handler to assume event has been consumed. */
                return JNI_TRUE;
            default:
                break;
        }
    }
    /* Pretend we were never called */
    return JNI_FALSE;
}

struct bag *
threadControl_onEventHandlerEntry(jbyte sessionID, EventIndex ei, jthread thread, jobject currentException)
{
    ThreadNode *node;
    JNIEnv     *env;
    struct bag *eventBag;
    jthread     threadToSuspend;
    jboolean    consumed;

    env             = getEnv();
    threadToSuspend = NULL;

    log_debugee_location("threadControl_onEventHandlerEntry()", thread, NULL, 0);

    /* Events during pop commands may need to be ignored here. */
    consumed = checkForPopFrameEvents(env, ei, thread);
    if ( consumed ) {
        /* Always restore any exception (see below). */
        if (currentException != NULL) {
            JNI_FUNC_PTR(env,Throw)(env, currentException);
        } else {
            JNI_FUNC_PTR(env,ExceptionClear)(env);
        }
        return NULL;
    }

    debugMonitorEnter(threadLock);

    /*
     * Check the list of unknown threads maintained by suspend
     * and resume. If this thread is currently present in the
     * list, it should be
     * moved to the runningThreads list, since it is a
     * well-known thread now.
     */
    node = findThread(&otherThreads, thread);
    if (node != NULL) {
        moveNode(&otherThreads, &runningThreads, node);
    } else {
        /*
         * Get a thread node for the reporting thread. For thread start
         * events, or if this event precedes a thread start event,
         * the thread node may need to be created.
         *
         * It is possible for certain events (notably method entry/exit)
         * to precede thread start for some VM implementations.
         */
        node = insertThread(env, &runningThreads, thread);
    }

    if (ei == EI_THREAD_START) {
        node->isStarted = JNI_TRUE;
        processDeferredEventModes(env, thread, node);
    }

    node->current_ei = ei;
    eventBag = node->eventBag;
    if (node->suspendOnStart) {
        threadToSuspend = node->thread;
    }
    debugMonitorExit(threadLock);

    if (threadToSuspend != NULL) {
        /*
         * An attempt was made to suspend this thread before it started.
         * We must suspend it now, before it starts to run. This must
         * be done with no locks held.
         */
        eventHelper_suspendThread(sessionID, threadToSuspend);
    }

    return eventBag;
}

static void
doPendingTasks(JNIEnv *env, ThreadNode *node)
{
    /*
     * Take care of any pending interrupts/stops, and clear out
     * info on pending interrupts/stops.
     */
    if (node->pendingInterrupt) {
        JVMTI_FUNC_PTR(gdata->jvmti,InterruptThread)
                        (gdata->jvmti, node->thread);
        /*
         * TO DO: Log error
         */
        node->pendingInterrupt = JNI_FALSE;
    }

    if (node->pendingStop != NULL) {
        JVMTI_FUNC_PTR(gdata->jvmti,StopThread)
                        (gdata->jvmti, node->thread, node->pendingStop);
        /*
         * TO DO: Log error
         */
        tossGlobalRef(env, &(node->pendingStop));
    }
}

void
threadControl_onEventHandlerExit(EventIndex ei, jthread thread,
                                 struct bag *eventBag)
{
    ThreadNode *node;

    log_debugee_location("threadControl_onEventHandlerExit()", thread, NULL, 0);

    if (ei == EI_THREAD_END) {
        eventHandler_lock(); /* for proper lock order */
    }
    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node == NULL) {
        EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"thread list corrupted");
    } else {
        JNIEnv *env;

        env = getEnv();
        if (ei == EI_THREAD_END) {
            jboolean inResume = (node->resumeFrameDepth > 0);
            removeThread(env, &runningThreads, thread);
            node = NULL;   /* has been freed */

            /*
             * Clean up mechanism used to detect end of
             * resume.
             */
            if (inResume) {
                notifyAppResumeComplete();
            }
        } else {
            /* No point in doing this if the thread is about to die.*/
            doPendingTasks(env, node);
            node->eventBag = eventBag;
            node->current_ei = 0;
        }
    }

    debugMonitorExit(threadLock);
    if (ei == EI_THREAD_END) {
        eventHandler_unlock();
    }
}

/* Returns JDWP flavored status and status flags. */
jvmtiError
threadControl_applicationThreadStatus(jthread thread,
                        jdwpThreadStatus *pstatus, jint *statusFlags)
{
    ThreadNode *node;
    jvmtiError  error;
    jint        state;

    log_debugee_location("threadControl_applicationThreadStatus()", thread, NULL, 0);

    debugMonitorEnter(threadLock);

    error = threadState(thread, &state);
    *pstatus = map2jdwpThreadStatus(state);
    *statusFlags = map2jdwpSuspendStatus(state);

    if (error == JVMTI_ERROR_NONE) {
        node = findThread(&runningThreads, thread);
        if ((node != NULL) && HANDLING_EVENT(node)) {
            /*
             * While processing an event, an application thread is always
             * considered to be running even if its handler happens to be
             * cond waiting on an internal debugger monitor, etc.
             *
             * Leave suspend status untouched since it is not possible
             * to distinguish debugger suspends from app suspends.
             */
            *pstatus = JDWP_THREAD_STATUS(RUNNING);
        }
    }

    debugMonitorExit(threadLock);

    return error;
}

jvmtiError
threadControl_interrupt(jthread thread)
{
    ThreadNode *node;
    jvmtiError  error;

    error = JVMTI_ERROR_NONE;

    log_debugee_location("threadControl_interrupt()", thread, NULL, 0);

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if ((node == NULL) || !HANDLING_EVENT(node)) {
        error = JVMTI_FUNC_PTR(gdata->jvmti,InterruptThread)
                        (gdata->jvmti, thread);
    } else {
        /*
         * Hold any interrupts until after the event is processed.
         */
        node->pendingInterrupt = JNI_TRUE;
    }

    debugMonitorExit(threadLock);

    return error;
}

void
threadControl_clearCLEInfo(JNIEnv *env, jthread thread)
{
    ThreadNode *node;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        node->cleInfo.ei = 0;
        if (node->cleInfo.clazz != NULL) {
            tossGlobalRef(env, &(node->cleInfo.clazz));
        }
    }

    debugMonitorExit(threadLock);
}

jboolean
threadControl_cmpCLEInfo(JNIEnv *env, jthread thread, jclass clazz,
                         jmethodID method, jlocation location)
{
    ThreadNode *node;
    jboolean    result;

    result = JNI_FALSE;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL && node->cleInfo.ei != 0 &&
        node->cleInfo.method == method &&
        node->cleInfo.location == location &&
        (isSameObject(env, node->cleInfo.clazz, clazz))) {
        result = JNI_TRUE; /* we have a match */
    }

    debugMonitorExit(threadLock);

    return result;
}

void
threadControl_saveCLEInfo(JNIEnv *env, jthread thread, EventIndex ei,
                          jclass clazz, jmethodID method, jlocation location)
{
    ThreadNode *node;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        node->cleInfo.ei = ei;
        /* Create a class ref that will live beyond */
        /* the end of this call */
        saveGlobalRef(env, clazz, &(node->cleInfo.clazz));
        /* if returned clazz is NULL, we just won't match */
        node->cleInfo.method    = method;
        node->cleInfo.location  = location;
    }

    debugMonitorExit(threadLock);
}

void
threadControl_setPendingInterrupt(jthread thread)
{
    ThreadNode *node;

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        node->pendingInterrupt = JNI_TRUE;
    }

    debugMonitorExit(threadLock);
}

jvmtiError
threadControl_stop(jthread thread, jobject throwable)
{
    ThreadNode *node;
    jvmtiError  error;

    error = JVMTI_ERROR_NONE;

    log_debugee_location("threadControl_stop()", thread, NULL, 0);

    debugMonitorEnter(threadLock);

    node = findThread(&runningThreads, thread);
    if ((node == NULL) || !HANDLING_EVENT(node)) {
        error = JVMTI_FUNC_PTR(gdata->jvmti,StopThread)
                        (gdata->jvmti, thread, throwable);
    } else {
        JNIEnv *env;

        /*
         * Hold any stops until after the event is processed.
         */
        env = getEnv();
        saveGlobalRef(env, throwable, &(node->pendingStop));
    }

    debugMonitorExit(threadLock);

    return error;
}

static jvmtiError
detachHelper(JNIEnv *env, ThreadNode *node, void *arg)
{
    invoker_detach(&node->currentInvoke);
    return JVMTI_ERROR_NONE;
}

void
threadControl_detachInvokes(void)
{
    JNIEnv *env;

    env = getEnv();
    invoker_lock(); /* for proper lock order */
    debugMonitorEnter(threadLock);
    (void)enumerateOverThreadList(env, &runningThreads, detachHelper, NULL);
    debugMonitorExit(threadLock);
    invoker_unlock();
}

static jvmtiError
resetHelper(JNIEnv *env, ThreadNode *node, void *arg)
{
    if (node->toBeResumed) {
        LOG_MISC(("thread=%p resumed", node->thread));
        (void)JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)(gdata->jvmti, node->thread);
        node->frameGeneration++; /* Increment on each resume */
    }
    stepControl_clearRequest(node->thread, &node->currentStep);
    node->toBeResumed = JNI_FALSE;
    node->suspendCount = 0;
    node->suspendOnStart = JNI_FALSE;

    return JVMTI_ERROR_NONE;
}

void
threadControl_reset(void)
{
    JNIEnv *env;

    env = getEnv();
    eventHandler_lock(); /* for proper lock order */
    debugMonitorEnter(threadLock);
    (void)enumerateOverThreadList(env, &runningThreads, resetHelper, NULL);
    (void)enumerateOverThreadList(env, &otherThreads, resetHelper, NULL);

    removeResumed(env, &otherThreads);

    freeDeferredEventModes(env);

    suspendAllCount = 0;

    /* Everything should have been resumed */
    JDI_ASSERT(otherThreads.first == NULL);

    debugMonitorExit(threadLock);
    eventHandler_unlock();
}

jvmtiEventMode
threadControl_getInstructionStepMode(jthread thread)
{
    ThreadNode    *node;
    jvmtiEventMode mode;

    mode = JVMTI_DISABLE;

    debugMonitorEnter(threadLock);
    node = findThread(&runningThreads, thread);
    if (node != NULL) {
        mode = node->instructionStepMode;
    }
    debugMonitorExit(threadLock);
    return mode;
}

jvmtiError
threadControl_setEventMode(jvmtiEventMode mode, EventIndex ei, jthread thread)
{
    jvmtiError error;

    /* Global event */
    if ( thread == NULL ) {
        error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
                    (gdata->jvmti, mode, eventIndex2jvmti(ei), thread);
    } else {
        /* Thread event */
        ThreadNode *node;

        debugMonitorEnter(threadLock);
        {
            node = findThread(&runningThreads, thread);
            if ((node == NULL) || (!node->isStarted)) {
                JNIEnv *env;

                env = getEnv();
                error = addDeferredEventMode(env, mode, ei, thread);
            } else {
                error = threadSetEventNotificationMode(node,
                        mode, ei, thread);
            }
        }
        debugMonitorExit(threadLock);

    }
    return error;
}

/*
 * Returns the current thread, if the thread has generated at least
 * one event, and has not generated a thread end event.
 */
jthread threadControl_currentThread(void)
{
    jthread thread;

    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(&runningThreads, NULL);
        thread = (node == NULL) ? NULL : node->thread;
    }
    debugMonitorExit(threadLock);

    return thread;
}

jlong
threadControl_getFrameGeneration(jthread thread)
{
    jlong frameGeneration = -1;

    debugMonitorEnter(threadLock);
    {
        ThreadNode *node;

        node = findThread(NULL, thread);

        if (node != NULL) {
            frameGeneration = node->frameGeneration;
        }
    }
    debugMonitorExit(threadLock);

    return frameGeneration;
}
