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