jdk/src/share/back/threadControl.c
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
#include "util.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
#include "eventHandler.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
#include "threadControl.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
#include "commonRef.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
#include "eventHelper.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
#include "stepControl.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
#include "invoker.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
#include "bag.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
#define HANDLING_EVENT(node) ((node)->current_ei != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * Collection of info for properly handling co-located events.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * If the ei field is non-zero, then one of the possible
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * co-located events has been posted and the other fields describe
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * the event's location.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
typedef struct CoLocatedEventInfo_ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    EventIndex ei;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    jclass    clazz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    jmethodID method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    jlocation location;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
} CoLocatedEventInfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * The main data structure in threadControl is the ThreadNode.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * This is a per-thread structure that is allocated on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * first event that occurs in a thread. It is freed after the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * thread's thread end event has completed processing. The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * structure contains state information on its thread including
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * suspend counts. It also acts as a repository for other
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * per-thread state such as the current method invocation or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * current step.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * suspendCount is the number of outstanding suspends
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * from the debugger. suspends from the app itself are
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * not included in this count.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
typedef struct ThreadNode {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    jthread thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    unsigned int toBeResumed : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    unsigned int pendingInterrupt : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    unsigned int isDebugThread : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    unsigned int suspendOnStart : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    unsigned int isStarted : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    unsigned int popFrameEvent : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    unsigned int popFrameProceed : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    unsigned int popFrameThread : 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    EventIndex current_ei;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    jobject pendingStop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    jint suspendCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    jint resumeFrameDepth; /* !=0 => This thread is in a call to Thread.resume() */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    jvmtiEventMode instructionStepMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    StepRequest currentStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    InvokeRequest currentInvoke;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    struct bag *eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    CoLocatedEventInfo cleInfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    struct ThreadNode *next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    struct ThreadNode *prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    jlong frameGeneration;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    struct ThreadList *list;  /* Tells us what list this thread is in */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
} ThreadNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
static jint suspendAllCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
typedef struct ThreadList {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    ThreadNode *first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
} ThreadList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * popFrameEventLock is used to notify that the event has been received
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
static jrawMonitorID popFrameEventLock = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * popFrameProceedLock is used to assure that the event thread is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * re-suspended immediately after the event is acknowledged.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
static jrawMonitorID popFrameProceedLock = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
static jrawMonitorID threadLock;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
static jlocation resumeLocation;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
static HandlerNode *breakpointHandlerNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
static HandlerNode *framePopHandlerNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
static HandlerNode *catchHandlerNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
static jvmtiError threadControl_removeDebugThread(jthread thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 * Threads which have issued thread start events and not yet issued thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
 * end events are maintained in the "runningThreads" list. All other threads known
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
 * to this module are kept in the "otherThreads" list.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
static ThreadList runningThreads;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
static ThreadList otherThreads;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
#define MAX_DEBUG_THREADS 10
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
static int debugThreadCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
static jthread debugThreads[MAX_DEBUG_THREADS];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
typedef struct DeferredEventMode {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    EventIndex ei;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    jvmtiEventMode mode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    jthread thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    struct DeferredEventMode *next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
} DeferredEventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    DeferredEventMode *first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    DeferredEventMode *last;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
} DeferredEventModeList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
static DeferredEventModeList deferredEventModes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
static jint
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
getStackDepth(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    jint count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                        (gdata->jvmti, thread, &count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        EXIT_ERROR(error, "getting frame count");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    return count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
/* Get the state of the thread direct from JVMTI */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
threadState(jthread thread, jint *pstate)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
    *pstate = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
    return JVMTI_FUNC_PTR(gdata->jvmti,GetThreadState)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                        (gdata->jvmti, thread, pstate);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
/* Set TLS on a specific jthread to the ThreadNode* */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
setThreadLocalStorage(jthread thread, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    error = JVMTI_FUNC_PTR(gdata->jvmti,SetThreadLocalStorage)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            (gdata->jvmti, thread, (void*)node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        /* Just return, thread hasn't started yet */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    } else if ( error != JVMTI_ERROR_NONE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        /* The jthread object must be valid, so this must be a fatal error */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        EXIT_ERROR(error, "cannot set thread local storage");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
/* Get TLS on a specific jthread, which is the ThreadNode* */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
static ThreadNode *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
getThreadLocalStorage(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    node = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
    error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadLocalStorage)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
            (gdata->jvmti, thread, (void**)&node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    if ( error == JVMTI_ERROR_THREAD_NOT_ALIVE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        /* Just return NULL, thread hasn't started yet */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    } else if ( error != JVMTI_ERROR_NONE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        /* The jthread object must be valid, so this must be a fatal error */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        EXIT_ERROR(error, "cannot get thread local storage");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    return node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
/* Search list for nodes that don't have TLS set and match this thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
 *   It assumed that this logic is never dealing with terminated threads,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
 *   since the ThreadEnd events always delete the ThreadNode while the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
 *   jthread is still alive.  So we can only look at the ThreadNode's that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
 *   have never had their TLS set, making the search much faster.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
 *   But keep in mind, this kind of search should rarely be needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
static ThreadNode *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
nonTlsSearch(JNIEnv *env, ThreadList *list, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
    for (node = list->first; node != NULL; node = node->next) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        if (isSameObject(env, node->thread, thread)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    return node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
 * These functions maintain the linked list of currently running threads.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
 * All assume that the threadLock is held before calling.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
 * If list==NULL, search both lists.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
static ThreadNode *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
findThread(ThreadList *list, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    /* Get thread local storage for quick thread -> node access */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
    node = getThreadLocalStorage(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
    /* In some rare cases we might get NULL, so we check the list manually for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     *   any threads that we could match.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    if ( node == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        if ( list != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            node = nonTlsSearch(env, list, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            node = nonTlsSearch(env, &runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            if ( node == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                node = nonTlsSearch(env, &otherThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
        if ( node != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            /* Here we make another attempt to set TLS, it's ok if this fails */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            setThreadLocalStorage(thread, (void*)node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    /* If a list is supplied, only return ones in this list */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    if ( node != NULL && list != NULL && node->list != list ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
    return node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
/* Remove a ThreadNode from a ThreadList */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
removeNode(ThreadList *list, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    ThreadNode *prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
    ThreadNode *next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    prev = node->prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    next = node->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
    if ( prev != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        prev->next = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    if ( next != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        next->prev = prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
    if ( prev == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        list->first = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    node->next = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    node->prev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
    node->list = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
/* Add a ThreadNode to a ThreadList */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
addNode(ThreadList *list, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
    node->next = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    node->prev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    node->list = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    if ( list->first == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        list->first = node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        list->first->prev = node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        node->next = list->first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        list->first = node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
    node->list = list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
static ThreadNode *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
insertThread(JNIEnv *env, ThreadList *list, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
    struct bag *eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
    node = findThread(list, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
    if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        node = jvmtiAllocate(sizeof(*node));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table entry");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        (void)memset(node, 0, sizeof(*node));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        eventBag = eventHelper_createEventBag();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        if (eventBag == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            jvmtiDeallocate(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table entry");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
            return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
         * Init all flags false, all refs NULL, all counts 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
        saveGlobalRef(env, thread, &(node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        if (node->thread == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            jvmtiDeallocate(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
            bagDestroyBag(eventBag);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table entry");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
         * Remember if it is a debug thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        if (threadControl_isDebugThread(node->thread)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            node->isDebugThread = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        } else if (suspendAllCount > 0){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
             * If there is a pending suspendAll, all new threads should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
             * be initialized as if they were suspended by the suspendAll,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
             * and the thread will need to be suspended when it starts.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            node->suspendCount = suspendAllCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
            node->suspendOnStart = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        node->current_ei = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        node->instructionStepMode = JVMTI_DISABLE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        node->eventBag = eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        addNode(list, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        /* Set thread local storage for quick thread -> node access.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
         *   Some threads may not be in a state that allows setting of TLS,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
         *   which is ok, see findThread, it deals with threads without TLS set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
        setThreadLocalStorage(node->thread, (void*)node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
    return node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
clearThread(JNIEnv *env, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    if (node->pendingStop != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
        tossGlobalRef(env, &(node->pendingStop));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    stepControl_clearRequest(node->thread, &node->currentStep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
    if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        (void)threadControl_removeDebugThread(node->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    /* Clear out TLS on this thread (just a cleanup action) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
    setThreadLocalStorage(node->thread, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
    tossGlobalRef(env, &(node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
    bagDestroyBag(node->eventBag);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    jvmtiDeallocate(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
removeThread(JNIEnv *env, ThreadList *list, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
    node = findThread(list, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        removeNode(list, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        clearThread(env, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
removeResumed(JNIEnv *env, ThreadList *list)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
    node = list->first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
    while (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        ThreadNode *temp = node->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        if (node->suspendCount == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
            removeThread(env, list, node->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        node = temp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
moveNode(ThreadList *source, ThreadList *dest, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    removeNode(source, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    JDI_ASSERT(findThread(dest, node->thread) == NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    addNode(dest, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
typedef jvmtiError (*ThreadEnumerateFunction)(JNIEnv *, ThreadNode *, void *);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
enumerateOverThreadList(JNIEnv *env, ThreadList *list,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                        ThreadEnumerateFunction function, void *arg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
    jvmtiError error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    for (node = list->first; node != NULL; node = node->next) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        error = (*function)(env, node, arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        if ( error != JVMTI_ERROR_NONE ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
insertEventMode(DeferredEventModeList *list, DeferredEventMode *eventMode)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    if (list->last != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        list->last->next = eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        list->first = eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
    list->last = eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
removeEventMode(DeferredEventModeList *list, DeferredEventMode *eventMode, DeferredEventMode *prev)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
    if (prev == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        list->first = eventMode->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        prev->next = eventMode->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
    if (eventMode->next == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        list->last = prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
addDeferredEventMode(JNIEnv *env, jvmtiEventMode mode, EventIndex ei, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
    DeferredEventMode *eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
    /*LINTED*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    eventMode = jvmtiAllocate((jint)sizeof(DeferredEventMode));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
    if (eventMode == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        return AGENT_ERROR_OUT_OF_MEMORY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
    eventMode->thread = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    saveGlobalRef(env, thread, &(eventMode->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    eventMode->mode = mode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
    eventMode->ei = ei;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
    eventMode->next = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
    insertEventMode(&deferredEventModes, eventMode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
    return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
freeDeferredEventModes(JNIEnv *env)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
    DeferredEventMode *eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
    eventMode = deferredEventModes.first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
    while (eventMode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
        DeferredEventMode *next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        next = eventMode->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
        tossGlobalRef(env, &(eventMode->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        jvmtiDeallocate(eventMode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        eventMode = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
    deferredEventModes.first = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    deferredEventModes.last = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
threadSetEventNotificationMode(ThreadNode *node,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        jvmtiEventMode mode, EventIndex ei, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
    /* record single step mode */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    if (ei == EI_SINGLE_STEP) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        node->instructionStepMode = mode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        (gdata->jvmti, mode, eventIndex2jvmti(ei), thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
processDeferredEventModes(JNIEnv *env, jthread thread, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
    DeferredEventMode *eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
    DeferredEventMode *prev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
    prev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
    eventMode = deferredEventModes.first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
    while (eventMode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        DeferredEventMode *next = eventMode->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        if (isSameObject(env, thread, eventMode->thread)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
            error = threadSetEventNotificationMode(node,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                    eventMode->mode, eventMode->ei, eventMode->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
            if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                EXIT_ERROR(error, "cannot process deferred thread event notifications at thread start");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            removeEventMode(&deferredEventModes, eventMode, prev);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
            tossGlobalRef(env, &(eventMode->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            jvmtiDeallocate(eventMode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            prev = eventMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        eventMode = next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
getLocks(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
     * Anything which might be locked as part of the handling of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
     * a JVMTI event (which means: might be locked by an application
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
     * thread) needs to be grabbed here. This allows thread control
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
     * code to safely suspend and resume the application threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
     * while ensuring they don't hold a critical lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
    eventHandler_lock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
    invoker_lock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
    eventHelper_lock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
    stepControl_lock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
    commonRef_lock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
releaseLocks(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    commonRef_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
    stepControl_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
    eventHelper_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
    invoker_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
    eventHandler_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
threadControl_initialize(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
    jlocation unused;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
    suspendAllCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    runningThreads.first = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
    otherThreads.first = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
    debugThreadCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
    threadLock = debugMonitorCreate("JDWP Thread Lock");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
    if (gdata->threadClass==NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "no java.lang.thread class");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
    if (gdata->threadResume==0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
        EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "cannot resume thread");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
    /* Get the java.lang.Thread.resume() method beginning location */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
    error = methodLocation(gdata->threadResume, &resumeLocation, &unused);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
    if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        EXIT_ERROR(error, "getting method location");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
static jthread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
getResumee(jthread resumingThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
    jthread resumee = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    jobject object;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
    FrameNumber fnum = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
    error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
                    (gdata->jvmti, resumingThread, fnum, 0, &object);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
    if (error == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        resumee = object;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    return resumee;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
static jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
pendingAppResume(jboolean includeSuspended)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
    ThreadList *list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
    list = &runningThreads;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
    node = list->first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
    while (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
        if (node->resumeFrameDepth > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            if (includeSuspended) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                return JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                jint       state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                error = threadState(node->thread, &state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                    EXIT_ERROR(error, "getting thread state");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                    return JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        node = node->next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
    return JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
notifyAppResumeComplete(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
    debugMonitorNotifyAll(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
    if (!pendingAppResume(JNI_TRUE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
        if (framePopHandlerNode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            (void)eventHandler_free(framePopHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            framePopHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        if (catchHandlerNode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
            (void)eventHandler_free(catchHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            catchHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
handleAppResumeCompletion(JNIEnv *env, EventInfo *evinfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
                          HandlerNode *handlerNode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                          struct bag *eventBag)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
    jthread     thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
    thread = evinfo->thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        if (node->resumeFrameDepth > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            jint compareDepth = getStackDepth(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            if (evinfo->ei == EI_FRAME_POP) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                compareDepth--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            if (compareDepth < node->resumeFrameDepth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                node->resumeFrameDepth = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                notifyAppResumeComplete();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
blockOnDebuggerSuspend(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
    node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        while (node && node->suspendCount > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
            debugMonitorWait(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
            node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
trackAppResume(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
    FrameNumber fnum;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
    fnum = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        JDI_ASSERT(node->resumeFrameDepth == 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
        error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                        (gdata->jvmti, thread, fnum);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
        if (error == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
            jint frameDepth = getStackDepth(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
            if ((frameDepth > 0) && (framePopHandlerNode == NULL)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                framePopHandlerNode = eventHandler_createInternalThreadOnly(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                                           EI_FRAME_POP,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                                           handleAppResumeCompletion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                                           thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                catchHandlerNode = eventHandler_createInternalThreadOnly(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                                           EI_EXCEPTION_CATCH,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
                                           handleAppResumeCompletion,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                                           thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                if ((framePopHandlerNode == NULL) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                    (catchHandlerNode == NULL)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                    (void)eventHandler_free(framePopHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                    framePopHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                    (void)eventHandler_free(catchHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                    catchHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
            if ((framePopHandlerNode != NULL) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                (catchHandlerNode != NULL) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                (frameDepth > 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
                node->resumeFrameDepth = frameDepth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
handleAppResumeBreakpoint(JNIEnv *env, EventInfo *evinfo,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                          HandlerNode *handlerNode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                          struct bag *eventBag)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
    jthread resumer = evinfo->thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
    jthread resumee = getResumee(resumer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
    if (resumee != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
         * Hold up any attempt to resume as long as the debugger
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
         * has suspended the resumee.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
        blockOnDebuggerSuspend(resumee);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
    if (resumer != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
         * Track the resuming thread by marking it as being within
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
         * a resume and by setting up for notification on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
         * a frame pop or exception. We won't allow the debugger
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
         * to suspend threads while any thread is within a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
         * call to resume. This (along with the block above)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
         * ensures that when the debugger
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
         * suspends a thread it will remain suspended.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
        trackAppResume(resumer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
threadControl_onConnect(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
    breakpointHandlerNode = eventHandler_createInternalBreakpoint(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
                 handleAppResumeBreakpoint, NULL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
                 gdata->threadClass, gdata->threadResume, resumeLocation);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
threadControl_onDisconnect(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
    if (breakpointHandlerNode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
        (void)eventHandler_free(breakpointHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
        breakpointHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
    if (framePopHandlerNode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
        (void)eventHandler_free(framePopHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
        framePopHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
    if (catchHandlerNode != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
        (void)eventHandler_free(catchHandlerNode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
        catchHandlerNode = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
threadControl_onHook(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
     * As soon as the event hook is in place, we need to initialize
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
     * the thread list with already-existing threads. The threadLock
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
     * has been held since initialize, so we don't need to worry about
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
     * insertions or deletions from the event handlers while we do this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
    JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
     * Prevent any event processing until OnHook has been called
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
    WITH_LOCAL_REFS(env, 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        jint threadCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        jthread *threads;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
        threads = allThreads(&threadCount);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
        if (threads == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
            int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
            for (i = 0; i < threadCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
                ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
                jthread thread = threads[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
                node = insertThread(env, &runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
                 * This is a tiny bit risky. We have to assume that the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
                 * pre-existing threads have been started because we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
                 * can't rely on a thread start event for them. The chances
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
                 * of a problem related to this are pretty slim though, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
                 * there's really no choice because without setting this flag
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                 * there is no way to enable stepping and other events on
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                 * the threads that already exist (e.g. the finalizer thread).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                node->isStarted = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
    } END_WITH_LOCAL_REFS(env)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
commonSuspendByNode(ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
    LOG_MISC(("thread=%p suspended", node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
    error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
                (gdata->jvmti, node->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
     * Mark for resume only if suspend succeeded
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
    if (error == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
        node->toBeResumed = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
     * If the thread was suspended by another app thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
     * do nothing and report no error (we won't resume it later).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
     if (error == JVMTI_ERROR_THREAD_SUSPENDED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
        error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
     return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
 * Deferred suspends happen when the suspend is attempted on a thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
 * that is not started. Bookkeeping (suspendCount,etc.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
 * is handled by the original request, and once the thread actually
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
 * starts, an actual suspend is attempted. This function does the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
 * deferred suspend without changing the bookkeeping that is already
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
 * in place.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
static jint
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
deferredSuspendThreadByNode(ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
    error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
    if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
        /* Ignore requests for suspending debugger threads */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
     * Do the actual suspend only if a subsequent resume hasn't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
     * made it irrelevant.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
    if (node->suspendCount > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
        error = commonSuspendByNode(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
         * Attempt to clean up from any error by decrementing the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
         * suspend count. This compensates for the increment that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
         * happens when suspendOnStart is set to true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
          node->suspendCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
    node->suspendOnStart = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
    debugMonitorNotifyAll(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
suspendThreadByNode(ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
    jvmtiError error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
    if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
        /* Ignore requests for suspending debugger threads */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
     * Just increment the suspend count if we are waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
     * for a deferred suspend.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
    if (node->suspendOnStart) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
        node->suspendCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
    if (node->suspendCount == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
        error = commonSuspendByNode(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
        if (error == JVMTI_ERROR_THREAD_NOT_ALIVE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
             * This error means that the thread is either a zombie or not yet
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
             * started. In either case, we ignore the error. If the thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
             * is a zombie, suspend/resume are no-ops. If the thread is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
             * started, it will be suspended for real during the processing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
             * of its thread start event.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
            node->suspendOnStart = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
            error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
    if (error == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
        node->suspendCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
    debugMonitorNotifyAll(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
resumeThreadByNode(ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
    jvmtiError error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
    if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
        /* never suspended by debugger => don't ever try to resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
    if (node->suspendCount > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
        node->suspendCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
        debugMonitorNotifyAll(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
        if ((node->suspendCount == 0) && node->toBeResumed &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
            !node->suspendOnStart) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
            LOG_MISC(("thread=%p resumed", node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
            error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                        (gdata->jvmti, node->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
            node->frameGeneration++; /* Increment on each resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
            node->toBeResumed = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
            if (error == JVMTI_ERROR_THREAD_NOT_ALIVE && !node->isStarted) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                 * We successfully "suspended" this thread, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
                 * we never received a THREAD_START event for it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
                 * Since the thread never ran, we can ignore our
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
                 * failure to resume the thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
                error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
 * Functions which respond to user requests to suspend/resume
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
 * threads.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
 * Suspends and resumes add and subtract from a count respectively.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
 * The thread is only suspended when the count goes from 0 to 1 and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
 * resumed only when the count goes from 1 to 0.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
 * These functions suspend and resume application threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
 * without changing the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
 * state of threads that were already suspended beforehand.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
 * They must not be called from an application thread because
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
 * that thread may be suspended somewhere in the  middle of things.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
preSuspend(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
    getLocks();                     /* Avoid debugger deadlocks */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
     * Delay any suspend while a call to java.lang.Thread.resume is in
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
     * progress (not including those in suspended threads). The wait is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
     * timed because the threads suspended through
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
     * java.lang.Thread.suspend won't result in a notify even though
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
     * it may change the result of pendingAppResume()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
    while (pendingAppResume(JNI_FALSE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
         * This is ugly but we need to release the locks from getLocks
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
         * or else the notify will never happen. The locks must be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
         * released and reacquired in the right order. else deadlocks
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
         * can happen. It is possible that, during this dance, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
         * notify will be missed, but since the wait needs to be timed
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
         * anyway, it won't be a disaster. Note that this code will
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
         * execute only on very rare occasions anyway.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        releaseLocks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
        debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
        debugMonitorTimedWait(threadLock, 1000);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
        debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
        getLocks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
postSuspend(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
    releaseLocks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
 * This function must be called after preSuspend and before postSuspend.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
commonSuspend(JNIEnv *env, jthread thread, jboolean deferred)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
     * If the thread is not between its start and end events, we should
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
     * still suspend it. To keep track of things, add the thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
     * to a separate list of threads so that we'll resume it later.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
    if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
        node = insertThread(env, &otherThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
    if ( deferred ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
        return deferredSuspendThreadByNode(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
        return suspendThreadByNode(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
resumeCopyHelper(JNIEnv *env, ThreadNode *node, void *arg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
    if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
        /* never suspended by debugger => don't ever try to resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
    if (node->suspendCount > 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
        node->suspendCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
        /* nested suspend so just undo one level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
     * This thread was marked for suspension since its THREAD_START
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
     * event came in during a suspendAll, but the helper hasn't
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
     * completed the job yet. We decrement the count so the helper
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
     * won't suspend this thread after we are done with the resumeAll.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
     * Another case to be handled here is when the debugger suspends
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
     * the thread while the app has it suspended. In this case,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
     * the toBeResumed flag has been cleared indicating that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
     * the thread should not be resumed when the debugger does a resume.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
     * In this case, we also have to decrement the suspend count.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
     * If we don't then when the app resumes the thread and our Thread.resume
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
     * bkpt handler is called, blockOnDebuggerSuspend will not resume
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
     * the thread because suspendCount will be 1 meaning that the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
     * debugger has the thread suspended.  See bug 6224859.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
    if (node->suspendCount == 1 && (!node->toBeResumed || node->suspendOnStart)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
        node->suspendCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
    if (arg == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
        /* nothing to hard resume so we're done */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
     * This is tricky. A suspendCount of 1 and toBeResumed means that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
     * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
     * on this thread. The check for !suspendOnStart is paranoia that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
     * we inherited from resumeThreadByNode().
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
    if (node->suspendCount == 1 && node->toBeResumed && !node->suspendOnStart) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
        jthread **listPtr = (jthread **)arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
        **listPtr = node->thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
        (*listPtr)++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
    return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
resumeCountHelper(JNIEnv *env, ThreadNode *node, void *arg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
    if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
        /* never suspended by debugger => don't ever try to resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
     * This is tricky. A suspendCount of 1 and toBeResumed means that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
     * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
     * on this thread. The check for !suspendOnStart is paranoia that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
     * we inherited from resumeThreadByNode().
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
    if (node->suspendCount == 1 && node->toBeResumed && !node->suspendOnStart) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
        jint *counter = (jint *)arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
        (*counter)++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
    return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
static void *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
newArray(jint length, size_t nbytes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
    void *ptr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
    ptr = jvmtiAllocate(length*(jint)nbytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
    if ( ptr != NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
        (void)memset(ptr, 0, length*nbytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
    return ptr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
deleteArray(void *ptr)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
    jvmtiDeallocate(ptr);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
 * This function must be called with the threadLock held.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
 * Two facts conspire to make this routine complicated:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
 * 1) the VM doesn't support nested external suspend
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
 * 2) the original resumeAll code structure doesn't retrieve the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
 *    entire thread list from JVMTI so we use the runningThreads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
 *    list and two helpers to get the job done.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
 * Because we hold the threadLock, state seen by resumeCountHelper()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
 * is the same state seen in resumeCopyHelper(). resumeCountHelper()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
 * just counts up the number of threads to be hard resumed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
 * resumeCopyHelper() does the accounting for nested suspends and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
 * special cases and, finally, populates the list of hard resume
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
 * threads to be passed to ResumeThreadList().
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
 * At first glance, you might think that the accounting could be done
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
 * in resumeCountHelper(), but then resumeCopyHelper() would see
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
 * "post-resume" state in the accounting values (suspendCount and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
 * toBeResumed) and would not be able to distinguish between a thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
 * that needs a hard resume versus a thread that is already running.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
commonResumeList(JNIEnv *env)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
    jvmtiError   error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
    jint         i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
    jint         reqCnt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
    jthread     *reqList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
    jthread     *reqPtr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
    jvmtiError  *results;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
    reqCnt = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
    /* count number of threads to hard resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
    (void) enumerateOverThreadList(env, &runningThreads, resumeCountHelper,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
                                   &reqCnt);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
    if (reqCnt == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
        /* nothing to hard resume so do just the accounting part */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
        (void) enumerateOverThreadList(env, &runningThreads, resumeCopyHelper,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
                                       NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
        return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
    /*LINTED*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
    reqList = newArray(reqCnt, sizeof(jthread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
    if (reqList == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
        EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"resume request list");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
    /*LINTED*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
    results = newArray(reqCnt, sizeof(jvmtiError));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
    if (results == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
        EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"resume list");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
    /* copy the jthread values for threads to hard resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
    reqPtr = reqList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
    (void) enumerateOverThreadList(env, &runningThreads, resumeCopyHelper,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
                                   &reqPtr);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
    error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThreadList)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
                (gdata->jvmti, reqCnt, reqList, results);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
    for (i = 0; i < reqCnt; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
        node = findThread(&runningThreads, reqList[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
            EXIT_ERROR(AGENT_ERROR_INVALID_THREAD,"missing entry in running thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
        LOG_MISC(("thread=%p resumed as part of list", node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
         * resumeThreadByNode() assumes that JVM/DI ResumeThread()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
         * always works and does all the accounting updates. We do
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
         * the same here. We also don't clear the error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
        node->suspendCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
        node->toBeResumed = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
        node->frameGeneration++; /* Increment on each resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
    deleteArray(results);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
    deleteArray(reqList);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
    debugMonitorNotifyAll(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
 * This function must be called after preSuspend and before postSuspend.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
commonSuspendList(JNIEnv *env, jint initCount, jthread *initList)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
    jint        i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
    jint        reqCnt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
    jthread    *reqList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
    error   = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
    reqCnt  = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
    reqList = newArray(initCount, sizeof(jthread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
    if (reqList == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
        EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"request list");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
     * Go through the initial list and see if we have anything to suspend.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
    for (i = 0; i < initCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
         * If the thread is not between its start and end events, we should
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
         * still suspend it. To keep track of things, add the thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
         * to a separate list of threads so that we'll resume it later.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
        node = findThread(&runningThreads, initList[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
            node = insertThread(env, &otherThreads, initList[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
        if (node->isDebugThread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
            /* Ignore requests for suspending debugger threads */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
            continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
         * Just increment the suspend count if we are waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
         * for a deferred suspend or if this is a nested suspend.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
        if (node->suspendOnStart || node->suspendCount > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
            node->suspendCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
            continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
        if (node->suspendCount == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
            /* thread is not suspended yet so put it on the request list */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
            reqList[reqCnt++] = initList[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
    if (reqCnt > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
        jvmtiError *results = newArray(reqCnt, sizeof(jvmtiError));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
        if (results == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1312
            EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"suspend list results");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
         * We have something to suspend so try to do it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
        error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThreadList)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
                        (gdata->jvmti, reqCnt, reqList, results);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
        for (i = 0; i < reqCnt; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
            ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
            node = findThread(NULL, reqList[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
            if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
                EXIT_ERROR(AGENT_ERROR_INVALID_THREAD,"missing entry in thread tables");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
            LOG_MISC(("thread=%p suspended as part of list", node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
            if (results[i] == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
                /* thread was suspended as requested */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
                node->toBeResumed = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
            } else if (results[i] == JVMTI_ERROR_THREAD_SUSPENDED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
                 * If the thread was suspended by another app thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
                 * do nothing and report no error (we won't resume it later).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
                results[i] = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
            } else if (results[i] == JVMTI_ERROR_THREAD_NOT_ALIVE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
                 * This error means that the suspend request failed
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
                 * because the thread is either a zombie or not yet
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
                 * started. In either case, we ignore the error. If the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
                 * thread is a zombie, suspend/resume are no-ops. If the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
                 * thread is not started, it will be suspended for real
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
                 * during the processing of its thread start event.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
                node->suspendOnStart = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
                results[i] = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
            /* count real, app and deferred (suspendOnStart) suspensions */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1352
            if (results[i] == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
                node->suspendCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1356
        deleteArray(results);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1358
    deleteArray(reqList);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1359
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1360
    debugMonitorNotifyAll(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1361
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1362
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1363
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1364
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1365
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1366
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1367
commonResume(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1368
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1369
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1370
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1371
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
     * The thread is normally between its start and end events, but if
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
     * not, check the auxiliary list used by threadControl_suspendThread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1375
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1376
    node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1377
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1378
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1379
     * If the node is in neither list, the debugger never suspended
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1380
     * this thread, so do nothing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1381
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1382
    error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1383
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1384
        error = resumeThreadByNode(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1385
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1386
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1387
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1388
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1389
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
threadControl_suspendThread(jthread thread, jboolean deferred)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
    JNIEnv    *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
    log_debugee_location("threadControl_suspendThread()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
    preSuspend();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
    error = commonSuspend(env, thread, deferred);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
    postSuspend();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
threadControl_resumeThread(jthread thread, jboolean do_unblock)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1409
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
    JNIEnv    *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1414
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1415
    log_debugee_location("threadControl_resumeThread()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1416
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1417
    eventHandler_lock(); /* for proper lock order */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1418
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1419
    error = commonResume(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
    removeResumed(env, &otherThreads);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1421
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1422
    eventHandler_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1423
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1424
    if (do_unblock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1425
        /* let eventHelper.c: commandLoop() know we resumed one thread */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1426
        unblockCommandLoop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1427
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1428
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1429
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1430
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1431
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1432
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1433
threadControl_suspendCount(jthread thread, jint *count)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1434
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1435
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1436
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1437
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1438
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1439
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1440
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1441
    if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1442
        node = findThread(&otherThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1443
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1444
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1445
    error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1446
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1447
        *count = node->suspendCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1448
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1449
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1450
         * If the node is in neither list, the debugger never suspended
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1451
         * this thread, so the suspend count is 0.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1452
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1453
        *count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1454
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1455
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1456
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1457
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1458
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1459
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1460
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1461
static jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1462
contains(JNIEnv *env, jthread *list, jint count, jthread item)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1463
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1464
    int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1465
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1466
    for (i = 0; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1467
        if (isSameObject(env, list[i], item)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1468
            return JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1469
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1470
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1471
    return JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1472
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1473
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1474
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1475
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1476
    jthread *list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1477
    jint count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1478
} SuspendAllArg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1479
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1480
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1481
suspendAllHelper(JNIEnv *env, ThreadNode *node, void *arg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1482
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1483
    SuspendAllArg *saArg = (SuspendAllArg *)arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1484
    jvmtiError error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1485
    jthread *list = saArg->list;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1486
    jint count = saArg->count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1487
    if (!contains(env, list, count, node->thread)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1488
        error = commonSuspend(env, node->thread, JNI_FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1489
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1490
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1491
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1492
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1493
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1494
threadControl_suspendAll(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1495
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1496
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1497
    JNIEnv    *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1498
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1499
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1500
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1501
    log_debugee_location("threadControl_suspendAll()", NULL, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1502
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1503
    preSuspend();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1504
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1505
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1506
     * Get a list of all threads and suspend them.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1507
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1508
    WITH_LOCAL_REFS(env, 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1509
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1510
        jthread *threads;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1511
        jint count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1512
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1513
        threads = allThreads(&count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1514
        if (threads == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1515
            error = AGENT_ERROR_OUT_OF_MEMORY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1516
            goto err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1517
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1518
        if (canSuspendResumeThreadLists()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1519
            error = commonSuspendList(env, count, threads);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1520
            if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1521
                goto err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1522
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1523
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1524
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1525
            int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1526
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1527
            for (i = 0; i < count; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1528
                error = commonSuspend(env, threads[i], JNI_FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1529
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1530
                if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1531
                    goto err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1532
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1533
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1534
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1535
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1536
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1537
         * Update the suspend count of any threads not yet (or no longer)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1538
         * in the thread list above.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1539
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1540
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1541
            SuspendAllArg arg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1542
            arg.list = threads;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1543
            arg.count = count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1544
            error = enumerateOverThreadList(env, &otherThreads,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1545
                                            suspendAllHelper, &arg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1546
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1547
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1548
        if (error == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1549
            suspendAllCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1550
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1551
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1552
    err: ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1553
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1554
    } END_WITH_LOCAL_REFS(env)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1555
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1556
    postSuspend();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1557
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1558
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1559
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1560
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1561
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1562
resumeHelper(JNIEnv *env, ThreadNode *node, void *ignored)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1563
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1564
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1565
     * Since this helper is called with the threadLock held, we
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1566
     * don't need to recheck to see if the node is still on one
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1567
     * of the two thread lists.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1568
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1569
    return resumeThreadByNode(node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1570
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1571
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1572
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1573
threadControl_resumeAll(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1574
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1575
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1576
    JNIEnv    *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1577
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1578
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1579
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1580
    log_debugee_location("threadControl_resumeAll()", NULL, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1581
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1582
    eventHandler_lock(); /* for proper lock order */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1583
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1584
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1585
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1586
     * Resume only those threads that the debugger has suspended. All
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1587
     * such threads must have a node in one of the thread lists, so there's
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1588
     * no need to get the whole thread list from JVMTI (unlike
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1589
     * suspendAll).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1590
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1591
    if (canSuspendResumeThreadLists()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1592
        error = commonResumeList(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1593
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1594
        error = enumerateOverThreadList(env, &runningThreads,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1595
                                        resumeHelper, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1596
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1597
    if ((error == JVMTI_ERROR_NONE) && (otherThreads.first != NULL)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1598
        error = enumerateOverThreadList(env, &otherThreads,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1599
                                        resumeHelper, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1600
        removeResumed(env, &otherThreads);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1601
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1602
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1603
    if (suspendAllCount > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1604
        suspendAllCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1605
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1606
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1607
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1608
    eventHandler_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1609
    /* let eventHelper.c: commandLoop() know we are resuming */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1610
    unblockCommandLoop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1611
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1612
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1613
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1614
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1615
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1616
StepRequest *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1617
threadControl_getStepRequest(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1618
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1619
    ThreadNode  *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1620
    StepRequest *step;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1621
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1622
    step = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1623
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1624
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1625
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1626
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1627
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1628
        step = &node->currentStep;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1629
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1630
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1631
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1632
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1633
    return step;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1634
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1635
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1636
InvokeRequest *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1637
threadControl_getInvokeRequest(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1638
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1639
    ThreadNode    *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1640
    InvokeRequest *request;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1641
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1642
    request = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1643
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1644
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1645
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1646
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1647
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1648
         request = &node->currentInvoke;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1649
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1650
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1651
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1652
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1653
    return request;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1654
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1655
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1656
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1657
threadControl_addDebugThread(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1658
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1659
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1660
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1661
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1662
    if (debugThreadCount >= MAX_DEBUG_THREADS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1663
        error = AGENT_ERROR_OUT_OF_MEMORY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1664
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1665
        JNIEnv    *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1666
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1667
        env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1668
        debugThreads[debugThreadCount] = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1669
        saveGlobalRef(env, thread, &(debugThreads[debugThreadCount]));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1670
        if (debugThreads[debugThreadCount] == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1671
            error = AGENT_ERROR_OUT_OF_MEMORY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1672
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1673
            debugThreadCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1674
            error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1675
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1676
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1677
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1678
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1679
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1680
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1681
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1682
threadControl_removeDebugThread(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1683
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1684
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1685
    JNIEnv    *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1686
    int        i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1687
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1688
    error = AGENT_ERROR_INVALID_THREAD;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1689
    env   = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1690
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1691
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1692
    for (i = 0; i< debugThreadCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1693
        if (isSameObject(env, thread, debugThreads[i])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1694
            int j;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1695
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1696
            tossGlobalRef(env, &(debugThreads[i]));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1697
            for (j = i+1; j < debugThreadCount; j++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1698
                debugThreads[j-1] = debugThreads[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1699
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1700
            debugThreadCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1701
            error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1702
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1703
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1704
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1705
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1706
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1707
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1708
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1709
jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1710
threadControl_isDebugThread(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1711
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1712
    int      i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1713
    jboolean rc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1714
    JNIEnv  *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1715
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1716
    rc  = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1717
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1718
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1719
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1720
    for (i = 0; i < debugThreadCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1721
        if (isSameObject(env, thread, debugThreads[i])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1722
            rc = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1723
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1724
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1725
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1726
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1727
    return rc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1728
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1729
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1730
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1731
initLocks(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1732
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1733
    if (popFrameEventLock == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1734
        popFrameEventLock = debugMonitorCreate("JDWP PopFrame Event Lock");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1735
        popFrameProceedLock = debugMonitorCreate("JDWP PopFrame Proceed Lock");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1736
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1737
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1738
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1739
static jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1740
getPopFrameThread(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1741
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1742
    jboolean popFrameThread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1743
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1744
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1745
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1746
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1747
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1748
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1749
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1750
            popFrameThread = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1751
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1752
            popFrameThread = node->popFrameThread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1753
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1754
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1755
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1756
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1757
    return popFrameThread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1758
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1759
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1760
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1761
setPopFrameThread(jthread thread, jboolean value)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1762
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1763
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1764
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1765
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1766
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1767
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1768
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1769
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1770
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1771
            node->popFrameThread = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1772
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1773
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1774
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1775
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1776
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1777
static jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1778
getPopFrameEvent(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1779
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1780
    jboolean popFrameEvent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1781
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1782
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1783
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1784
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1785
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1786
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1787
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1788
            popFrameEvent = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1789
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1790
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1791
            popFrameEvent = node->popFrameEvent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1792
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1793
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1794
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1795
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1796
    return popFrameEvent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1797
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1798
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1799
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1800
setPopFrameEvent(jthread thread, jboolean value)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1801
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1802
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1803
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1804
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1805
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1806
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1807
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1808
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1809
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1810
            node->popFrameEvent = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1811
            node->frameGeneration++; /* Increment on each resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1812
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1813
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1814
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1815
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1816
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1817
static jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1818
getPopFrameProceed(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1819
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1820
    jboolean popFrameProceed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1821
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1822
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1823
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1824
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1825
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1826
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1827
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1828
            popFrameProceed = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1829
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1830
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1831
            popFrameProceed = node->popFrameProceed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1832
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1833
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1834
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1835
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1836
    return popFrameProceed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1837
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1838
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1839
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1840
setPopFrameProceed(jthread thread, jboolean value)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1841
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1842
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1843
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1844
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1845
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1846
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1847
        if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1848
            EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1849
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1850
            node->popFrameProceed = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1851
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1852
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1853
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1854
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1855
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1856
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1857
 * Special event handler for events on the popped thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1858
 * that occur during the pop operation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1859
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1860
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1861
popFrameCompleteEvent(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1862
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1863
      debugMonitorEnter(popFrameProceedLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1864
      {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1865
          /* notify that we got the event */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1866
          debugMonitorEnter(popFrameEventLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1867
          {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1868
              setPopFrameEvent(thread, JNI_TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1869
              debugMonitorNotify(popFrameEventLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1870
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1871
          debugMonitorExit(popFrameEventLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1872
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1873
          /* make sure we get suspended again */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1874
          setPopFrameProceed(thread, JNI_FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1875
          while (getPopFrameProceed(thread) == JNI_FALSE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1876
              debugMonitorWait(popFrameProceedLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1877
          }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1878
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1879
      debugMonitorExit(popFrameProceedLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1880
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1881
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1882
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1883
 * Pop one frame off the stack of thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1884
 * popFrameEventLock is already held
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1885
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1886
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1887
popOneFrame(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1888
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1889
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1890
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1891
    error = JVMTI_FUNC_PTR(gdata->jvmti,PopFrame)(gdata->jvmti, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1892
    if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1893
        return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1894
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1895
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1896
    /* resume the popped thread so that the pop occurs and so we */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1897
    /* will get the event (step or method entry) after the pop */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1898
    LOG_MISC(("thread=%p resumed in popOneFrame", thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1899
    error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)(gdata->jvmti, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1900
    if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1901
        return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1902
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1903
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1904
    /* wait for the event to occur */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1905
    setPopFrameEvent(thread, JNI_FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1906
    while (getPopFrameEvent(thread) == JNI_FALSE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1907
        debugMonitorWait(popFrameEventLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1908
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1909
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1910
    /* make sure not to suspend until the popped thread is on the wait */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1911
    debugMonitorEnter(popFrameProceedLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1912
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1913
        /* return popped thread to suspended state */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1914
        LOG_MISC(("thread=%p suspended in popOneFrame", thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1915
        error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThread)(gdata->jvmti, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1916
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1917
        /* notify popped thread so it can proceed when resumed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1918
        setPopFrameProceed(thread, JNI_TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1919
        debugMonitorNotify(popFrameProceedLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1920
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1921
    debugMonitorExit(popFrameProceedLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1922
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1923
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1924
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1925
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1926
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1927
 * pop frames of the stack of 'thread' until 'frame' is popped.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1928
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1929
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1930
threadControl_popFrames(jthread thread, FrameNumber fnum)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1931
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1932
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1933
    jvmtiEventMode prevStepMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1934
    jint framesPopped = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1935
    jint popCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1936
    jboolean prevInvokeRequestMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1937
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1938
    log_debugee_location("threadControl_popFrames()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1939
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1940
    initLocks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1941
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1942
    /* compute the number of frames to pop */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1943
    popCount = fnum+1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1944
    if (popCount < 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1945
        return AGENT_ERROR_NO_MORE_FRAMES;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1946
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1947
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1948
    /* enable instruction level single step, but first note prev value */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1949
    prevStepMode = threadControl_getInstructionStepMode(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1950
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1951
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1952
     * Fix bug 6517249.  The pop processing will disable invokes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1953
     * so remember if invokes are enabled now and restore
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1954
     * that state after we finish popping.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1955
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1956
    prevInvokeRequestMode = invoker_isEnabled(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1957
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1958
    error = threadControl_setEventMode(JVMTI_ENABLE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1959
                                       EI_SINGLE_STEP, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1960
    if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1961
        return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1962
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1963
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1964
    /* Inform eventHandler logic we are in a popFrame for this thread */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1965
    debugMonitorEnter(popFrameEventLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1966
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1967
        setPopFrameThread(thread, JNI_TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1968
        /* pop frames using single step */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1969
        while (framesPopped++ < popCount) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1970
            error = popOneFrame(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1971
            if (error != JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1972
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1973
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1974
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1975
        setPopFrameThread(thread, JNI_FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1976
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1977
    debugMonitorExit(popFrameEventLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1978
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1979
    /*  Reset StepRequest info (fromLine and stackDepth) after popframes
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1980
     *  only if stepping is enabled.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1981
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1982
    if (prevStepMode == JVMTI_ENABLE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1983
        stepControl_resetRequest(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1984
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1985
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1986
    if (prevInvokeRequestMode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1987
        invoker_enableInvokeRequests(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1988
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1989
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1990
    /* restore state */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1991
    (void)threadControl_setEventMode(prevStepMode,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1992
                               EI_SINGLE_STEP, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1993
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1994
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1995
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1996
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1997
/* Check to see if any events are being consumed by a popFrame(). */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1998
static jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1999
checkForPopFrameEvents(JNIEnv *env, EventIndex ei, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2000
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2001
    if ( getPopFrameThread(thread) ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2002
        switch (ei) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2003
            case EI_THREAD_START:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2004
                /* Excuse me? */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2005
                EXIT_ERROR(AGENT_ERROR_INTERNAL, "thread start during pop frame");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2006
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2007
            case EI_THREAD_END:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2008
                /* Thread wants to end? let it. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2009
                setPopFrameThread(thread, JNI_FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2010
                popFrameCompleteEvent(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2011
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2012
            case EI_SINGLE_STEP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2013
                /* This is an event we requested to mark the */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2014
                /*        completion of the pop frame */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2015
                popFrameCompleteEvent(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2016
                return JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2017
            case EI_BREAKPOINT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2018
            case EI_EXCEPTION:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2019
            case EI_FIELD_ACCESS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2020
            case EI_FIELD_MODIFICATION:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2021
            case EI_METHOD_ENTRY:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2022
            case EI_METHOD_EXIT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2023
                /* Tell event handler to assume event has been consumed. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2024
                return JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2025
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2026
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2027
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2028
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2029
    /* Pretend we were never called */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2030
    return JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2031
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2032
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2033
struct bag *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2034
threadControl_onEventHandlerEntry(jbyte sessionID, EventIndex ei, jthread thread, jobject currentException)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2035
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2036
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2037
    JNIEnv     *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2038
    struct bag *eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2039
    jthread     threadToSuspend;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2040
    jboolean    consumed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2041
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2042
    env             = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2043
    threadToSuspend = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2044
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2045
    log_debugee_location("threadControl_onEventHandlerEntry()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2046
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2047
    /* Events during pop commands may need to be ignored here. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2048
    consumed = checkForPopFrameEvents(env, ei, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2049
    if ( consumed ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2050
        /* Always restore any exception (see below). */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2051
        if (currentException != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2052
            JNI_FUNC_PTR(env,Throw)(env, currentException);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2053
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2054
            JNI_FUNC_PTR(env,ExceptionClear)(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2055
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2056
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2057
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2058
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2059
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2060
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2061
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2062
     * Check the list of unknown threads maintained by suspend
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2063
     * and resume. If this thread is currently present in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2064
     * list, it should be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2065
     * moved to the runningThreads list, since it is a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2066
     * well-known thread now.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2067
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2068
    node = findThread(&otherThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2069
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2070
        moveNode(&otherThreads, &runningThreads, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2071
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2072
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2073
         * Get a thread node for the reporting thread. For thread start
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2074
         * events, or if this event precedes a thread start event,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2075
         * the thread node may need to be created.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2076
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2077
         * It is possible for certain events (notably method entry/exit)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2078
         * to precede thread start for some VM implementations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2079
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2080
        node = insertThread(env, &runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2081
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2082
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2083
    if (ei == EI_THREAD_START) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2084
        node->isStarted = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2085
        processDeferredEventModes(env, thread, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2086
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2087
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2088
    node->current_ei = ei;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2089
    eventBag = node->eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2090
    if (node->suspendOnStart) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2091
        threadToSuspend = node->thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2092
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2093
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2094
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2095
    if (threadToSuspend != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2096
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2097
         * An attempt was made to suspend this thread before it started.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2098
         * We must suspend it now, before it starts to run. This must
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2099
         * be done with no locks held.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2100
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2101
        eventHelper_suspendThread(sessionID, threadToSuspend);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2102
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2103
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2104
    return eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2105
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2106
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2107
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2108
doPendingTasks(JNIEnv *env, ThreadNode *node)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2109
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2110
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2111
     * Take care of any pending interrupts/stops, and clear out
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2112
     * info on pending interrupts/stops.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2113
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2114
    if (node->pendingInterrupt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2115
        JVMTI_FUNC_PTR(gdata->jvmti,InterruptThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2116
                        (gdata->jvmti, node->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2117
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2118
         * TO DO: Log error
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2119
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2120
        node->pendingInterrupt = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2121
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2122
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2123
    if (node->pendingStop != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2124
        JVMTI_FUNC_PTR(gdata->jvmti,StopThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2125
                        (gdata->jvmti, node->thread, node->pendingStop);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2126
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2127
         * TO DO: Log error
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2128
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2129
        tossGlobalRef(env, &(node->pendingStop));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2130
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2131
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2132
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2133
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2134
threadControl_onEventHandlerExit(EventIndex ei, jthread thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2135
                                 struct bag *eventBag)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2136
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2137
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2138
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2139
    log_debugee_location("threadControl_onEventHandlerExit()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2140
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2141
    if (ei == EI_THREAD_END) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2142
        eventHandler_lock(); /* for proper lock order */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2143
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2144
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2145
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2146
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2147
    if (node == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2148
        EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"thread list corrupted");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2149
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2150
        JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2151
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2152
        env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2153
        if (ei == EI_THREAD_END) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2154
            jboolean inResume = (node->resumeFrameDepth > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2155
            removeThread(env, &runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2156
            node = NULL;   /* has been freed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2157
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2158
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2159
             * Clean up mechanism used to detect end of
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2160
             * resume.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2161
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2162
            if (inResume) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2163
                notifyAppResumeComplete();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2164
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2165
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2166
            /* No point in doing this if the thread is about to die.*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2167
            doPendingTasks(env, node);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2168
            node->eventBag = eventBag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2169
            node->current_ei = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2170
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2172
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2173
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2174
    if (ei == EI_THREAD_END) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2175
        eventHandler_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2176
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2177
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2178
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2179
/* Returns JDWP flavored status and status flags. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2180
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2181
threadControl_applicationThreadStatus(jthread thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2182
                        jdwpThreadStatus *pstatus, jint *statusFlags)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2183
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2184
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2185
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2186
    jint        state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2187
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2188
    log_debugee_location("threadControl_applicationThreadStatus()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2189
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2190
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2191
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2192
    error = threadState(thread, &state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2193
    *pstatus = map2jdwpThreadStatus(state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2194
    *statusFlags = map2jdwpSuspendStatus(state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2195
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2196
    if (error == JVMTI_ERROR_NONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2197
        node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2198
        if ((node != NULL) && HANDLING_EVENT(node)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2199
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2200
             * While processing an event, an application thread is always
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2201
             * considered to be running even if its handler happens to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2202
             * cond waiting on an internal debugger monitor, etc.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2203
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2204
             * Leave suspend status untouched since it is not possible
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2205
             * to distinguish debugger suspends from app suspends.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2206
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2207
            *pstatus = JDWP_THREAD_STATUS(RUNNING);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2208
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2210
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2211
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2212
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2213
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2214
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2215
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2216
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2217
threadControl_interrupt(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2218
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2219
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2220
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2221
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2222
    error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2223
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2224
    log_debugee_location("threadControl_interrupt()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2225
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2226
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2227
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2228
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2229
    if ((node == NULL) || !HANDLING_EVENT(node)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2230
        error = JVMTI_FUNC_PTR(gdata->jvmti,InterruptThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2231
                        (gdata->jvmti, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2232
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2233
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2234
         * Hold any interrupts until after the event is processed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2235
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2236
        node->pendingInterrupt = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2237
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2238
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2239
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2240
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2241
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2242
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2243
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2244
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2245
threadControl_clearCLEInfo(JNIEnv *env, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2246
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2247
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2248
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2249
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2250
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2251
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2252
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2253
        node->cleInfo.ei = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2254
        if (node->cleInfo.clazz != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2255
            tossGlobalRef(env, &(node->cleInfo.clazz));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2256
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2257
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2258
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2259
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2260
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2261
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2262
jboolean
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2263
threadControl_cmpCLEInfo(JNIEnv *env, jthread thread, jclass clazz,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2264
                         jmethodID method, jlocation location)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2265
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2266
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2267
    jboolean    result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2268
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2269
    result = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2270
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2271
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2272
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2273
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2274
    if (node != NULL && node->cleInfo.ei != 0 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2275
        node->cleInfo.method == method &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2276
        node->cleInfo.location == location &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2277
        (isSameObject(env, node->cleInfo.clazz, clazz))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2278
        result = JNI_TRUE; /* we have a match */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2279
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2280
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2281
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2282
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2283
    return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2284
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2285
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2286
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2287
threadControl_saveCLEInfo(JNIEnv *env, jthread thread, EventIndex ei,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2288
                          jclass clazz, jmethodID method, jlocation location)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2289
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2290
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2291
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2292
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2293
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2294
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2295
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2296
        node->cleInfo.ei = ei;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2297
        /* Create a class ref that will live beyond */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2298
        /* the end of this call */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2299
        saveGlobalRef(env, clazz, &(node->cleInfo.clazz));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2300
        /* if returned clazz is NULL, we just won't match */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2301
        node->cleInfo.method    = method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2302
        node->cleInfo.location  = location;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2303
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2304
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2305
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2306
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2307
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2308
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2309
threadControl_setPendingInterrupt(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2310
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2311
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2312
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2313
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2314
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2315
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2316
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2317
        node->pendingInterrupt = JNI_TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2318
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2319
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2320
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2321
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2322
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2323
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2324
threadControl_stop(jthread thread, jobject throwable)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2325
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2326
    ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2327
    jvmtiError  error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2328
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2329
    error = JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2330
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2331
    log_debugee_location("threadControl_stop()", thread, NULL, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2332
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2333
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2334
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2335
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2336
    if ((node == NULL) || !HANDLING_EVENT(node)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2337
        error = JVMTI_FUNC_PTR(gdata->jvmti,StopThread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2338
                        (gdata->jvmti, thread, throwable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2339
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2340
        JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2341
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2342
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2343
         * Hold any stops until after the event is processed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2344
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2345
        env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2346
        saveGlobalRef(env, throwable, &(node->pendingStop));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2347
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2348
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2349
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2350
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2351
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2352
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2353
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2354
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2355
detachHelper(JNIEnv *env, ThreadNode *node, void *arg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2356
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2357
    invoker_detach(&node->currentInvoke);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2358
    return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2359
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2360
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2361
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2362
threadControl_detachInvokes(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2363
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2364
    JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2365
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2366
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2367
    invoker_lock(); /* for proper lock order */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2368
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2369
    (void)enumerateOverThreadList(env, &runningThreads, detachHelper, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2370
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2371
    invoker_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2372
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2373
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2374
static jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2375
resetHelper(JNIEnv *env, ThreadNode *node, void *arg)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2376
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2377
    if (node->toBeResumed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2378
        LOG_MISC(("thread=%p resumed", node->thread));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2379
        (void)JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)(gdata->jvmti, node->thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2380
        node->frameGeneration++; /* Increment on each resume */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2381
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2382
    stepControl_clearRequest(node->thread, &node->currentStep);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2383
    node->toBeResumed = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2384
    node->suspendCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2385
    node->suspendOnStart = JNI_FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2386
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2387
    return JVMTI_ERROR_NONE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2388
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2389
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2390
void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2391
threadControl_reset(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2392
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2393
    JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2394
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2395
    env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2396
    eventHandler_lock(); /* for proper lock order */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2397
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2398
    (void)enumerateOverThreadList(env, &runningThreads, resetHelper, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2399
    (void)enumerateOverThreadList(env, &otherThreads, resetHelper, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2400
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2401
    removeResumed(env, &otherThreads);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2402
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2403
    freeDeferredEventModes(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2404
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2405
    suspendAllCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2406
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2407
    /* Everything should have been resumed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2408
    JDI_ASSERT(otherThreads.first == NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2409
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2410
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2411
    eventHandler_unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2412
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2413
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2414
jvmtiEventMode
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2415
threadControl_getInstructionStepMode(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2416
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2417
    ThreadNode    *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2418
    jvmtiEventMode mode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2419
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2420
    mode = JVMTI_DISABLE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2421
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2422
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2423
    node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2424
    if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2425
        mode = node->instructionStepMode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2426
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2427
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2428
    return mode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2429
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2430
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2431
jvmtiError
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2432
threadControl_setEventMode(jvmtiEventMode mode, EventIndex ei, jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2433
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2434
    jvmtiError error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2435
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2436
    /* Global event */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2437
    if ( thread == NULL ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2438
        error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2439
                    (gdata->jvmti, mode, eventIndex2jvmti(ei), thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2440
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2441
        /* Thread event */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2442
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2443
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2444
        debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2445
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2446
            node = findThread(&runningThreads, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2447
            if ((node == NULL) || (!node->isStarted)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2448
                JNIEnv *env;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2449
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2450
                env = getEnv();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2451
                error = addDeferredEventMode(env, mode, ei, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2452
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2453
                error = threadSetEventNotificationMode(node,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2454
                        mode, ei, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2455
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2456
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2457
        debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2458
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2459
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2460
    return error;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2461
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2462
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2463
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2464
 * Returns the current thread, if the thread has generated at least
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2465
 * one event, and has not generated a thread end event.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2466
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2467
jthread threadControl_currentThread(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2468
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2469
    jthread thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2470
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2471
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2472
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2473
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2474
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2475
        node = findThread(&runningThreads, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2476
        thread = (node == NULL) ? NULL : node->thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2477
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2478
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2479
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2480
    return thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2481
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2482
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2483
jlong
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2484
threadControl_getFrameGeneration(jthread thread)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2485
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2486
    jlong frameGeneration = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2487
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2488
    debugMonitorEnter(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2489
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2490
        ThreadNode *node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2491
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2492
        node = findThread(NULL, thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2493
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2494
        if (node != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2495
            frameGeneration = node->frameGeneration;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2496
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2497
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2498
    debugMonitorExit(threadLock);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2499
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2500
    return frameGeneration;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  2501
}