/*
 * Copyright 1998-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.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;
}
