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 // ANDROID-CHANGED: On ART 'this' is not always in register 0. We just use GetLocalInstance in 597 // all cases. 598 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance) 599 (gdata->jvmti, resumingThread, fnum, &object); 600 if (error == JVMTI_ERROR_NONE) { 601 resumee = object; 602 } 603 return resumee; 604 } 605 606 607 static jboolean 608 pendingAppResume(jboolean includeSuspended) 609 { 610 ThreadList *list; 611 ThreadNode *node; 612 613 list = &runningThreads; 614 node = list->first; 615 while (node != NULL) { 616 if (node->resumeFrameDepth > 0) { 617 if (includeSuspended) { 618 return JNI_TRUE; 619 } else { 620 jvmtiError error; 621 jint state; 622 623 error = threadState(node->thread, &state); 624 if (error != JVMTI_ERROR_NONE) { 625 EXIT_ERROR(error, "getting thread state"); 626 } 627 if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) { 628 return JNI_TRUE; 629 } 630 } 631 } 632 node = node->next; 633 } 634 return JNI_FALSE; 635 } 636 637 static void 638 notifyAppResumeComplete(void) 639 { 640 debugMonitorNotifyAll(threadLock); 641 if (!pendingAppResume(JNI_TRUE)) { 642 if (framePopHandlerNode != NULL) { 643 (void)eventHandler_free(framePopHandlerNode); 644 framePopHandlerNode = NULL; 645 } 646 if (catchHandlerNode != NULL) { 647 (void)eventHandler_free(catchHandlerNode); 648 catchHandlerNode = NULL; 649 } 650 } 651 } 652 653 static void 654 handleAppResumeCompletion(JNIEnv *env, EventInfo *evinfo, 655 HandlerNode *handlerNode, 656 struct bag *eventBag) 657 { 658 ThreadNode *node; 659 jthread thread; 660 661 thread = evinfo->thread; 662 663 debugMonitorEnter(threadLock); 664 665 node = findThread(&runningThreads, thread); 666 if (node != NULL) { 667 if (node->resumeFrameDepth > 0) { 668 jint compareDepth = getStackDepth(thread); 669 if (evinfo->ei == EI_FRAME_POP) { 670 compareDepth--; 671 } 672 if (compareDepth < node->resumeFrameDepth) { 673 node->resumeFrameDepth = 0; 674 notifyAppResumeComplete(); 675 } 676 } 677 } 678 679 debugMonitorExit(threadLock); 680 } 681 682 static void 683 blockOnDebuggerSuspend(jthread thread) 684 { 685 ThreadNode *node; 686 687 node = findThread(NULL, thread); 688 if (node != NULL) { 689 while (node && node->suspendCount > 0) { 690 debugMonitorWait(threadLock); 691 node = findThread(NULL, thread); 692 } 693 } 694 } 695 696 static void 697 trackAppResume(jthread thread) 698 { 699 jvmtiError error; 700 FrameNumber fnum; 701 ThreadNode *node; 702 703 fnum = 0; 704 node = findThread(&runningThreads, thread); 705 if (node != NULL) { 706 JDI_ASSERT(node->resumeFrameDepth == 0); 707 error = JVMTI_FUNC_PTR(gdata->jvmti,NotifyFramePop) 708 (gdata->jvmti, thread, fnum); 709 if (error == JVMTI_ERROR_NONE) { 710 jint frameDepth = getStackDepth(thread); 711 if ((frameDepth > 0) && (framePopHandlerNode == NULL)) { 712 framePopHandlerNode = eventHandler_createInternalThreadOnly( 713 EI_FRAME_POP, 714 handleAppResumeCompletion, 715 thread); 716 catchHandlerNode = eventHandler_createInternalThreadOnly( 717 EI_EXCEPTION_CATCH, 718 handleAppResumeCompletion, 719 thread); 720 if ((framePopHandlerNode == NULL) || 721 (catchHandlerNode == NULL)) { 722 (void)eventHandler_free(framePopHandlerNode); 723 framePopHandlerNode = NULL; 724 (void)eventHandler_free(catchHandlerNode); 725 catchHandlerNode = NULL; 726 } 727 } 728 if ((framePopHandlerNode != NULL) && 729 (catchHandlerNode != NULL) && 730 (frameDepth > 0)) { 731 node->resumeFrameDepth = frameDepth; 732 } 733 } 734 } 735 } 736 737 static void 738 handleAppResumeBreakpoint(JNIEnv *env, EventInfo *evinfo, 739 HandlerNode *handlerNode, 740 struct bag *eventBag) 741 { 742 jthread resumer = evinfo->thread; 743 jthread resumee = getResumee(resumer); 744 745 debugMonitorEnter(threadLock); 746 if (resumee != NULL) { 747 /* 748 * Hold up any attempt to resume as long as the debugger 749 * has suspended the resumee. 750 */ 751 blockOnDebuggerSuspend(resumee); 752 } 753 754 if (resumer != NULL) { 755 /* 756 * Track the resuming thread by marking it as being within 757 * a resume and by setting up for notification on 758 * a frame pop or exception. We won't allow the debugger 759 * to suspend threads while any thread is within a 760 * call to resume. This (along with the block above) 761 * ensures that when the debugger 762 * suspends a thread it will remain suspended. 763 */ 764 trackAppResume(resumer); 765 } 766 767 debugMonitorExit(threadLock); 768 } 769 770 void 771 threadControl_onConnect(void) 772 { 773 breakpointHandlerNode = eventHandler_createInternalBreakpoint( 774 handleAppResumeBreakpoint, NULL, 775 gdata->threadClass, gdata->threadResume, resumeLocation); 776 } 777 778 void 779 threadControl_onDisconnect(void) 780 { 781 if (breakpointHandlerNode != NULL) { 782 (void)eventHandler_free(breakpointHandlerNode); 783 breakpointHandlerNode = NULL; 784 } 785 if (framePopHandlerNode != NULL) { 786 (void)eventHandler_free(framePopHandlerNode); 787 framePopHandlerNode = NULL; 788 } 789 if (catchHandlerNode != NULL) { 790 (void)eventHandler_free(catchHandlerNode); 791 catchHandlerNode = NULL; 792 } 793 } 794 795 void 796 threadControl_onHook(void) 797 { 798 /* 799 * As soon as the event hook is in place, we need to initialize 800 * the thread list with already-existing threads. The threadLock 801 * has been held since initialize, so we don't need to worry about 802 * insertions or deletions from the event handlers while we do this 803 */ 804 JNIEnv *env; 805 806 env = getEnv(); 807 808 /* 809 * Prevent any event processing until OnHook has been called 810 */ 811 debugMonitorEnter(threadLock); 812 813 WITH_LOCAL_REFS(env, 1) { 814 815 jint threadCount; 816 jthread *threads; 817 818 threads = allThreads(&threadCount); 819 if (threads == NULL) { 820 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"thread table"); 821 } else { 822 823 int i; 824 825 for (i = 0; i < threadCount; i++) { 826 ThreadNode *node; 827 jthread thread = threads[i]; 828 node = insertThread(env, &runningThreads, thread); 829 830 /* 831 * This is a tiny bit risky. We have to assume that the 832 * pre-existing threads have been started because we 833 * can't rely on a thread start event for them. The chances 834 * of a problem related to this are pretty slim though, and 835 * there's really no choice because without setting this flag 836 * there is no way to enable stepping and other events on 837 * the threads that already exist (e.g. the finalizer thread). 838 */ 839 node->isStarted = JNI_TRUE; 840 } 841 } 842 843 } END_WITH_LOCAL_REFS(env) 844 845 debugMonitorExit(threadLock); 846 } 847 848 static jvmtiError 849 commonSuspendByNode(ThreadNode *node) 850 { 851 jvmtiError error; 852 853 LOG_MISC(("thread=%p suspended", node->thread)); 854 error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThread) 855 (gdata->jvmti, node->thread); 856 857 /* 858 * Mark for resume only if suspend succeeded 859 */ 860 if (error == JVMTI_ERROR_NONE) { 861 node->toBeResumed = JNI_TRUE; 862 } 863 864 /* 865 * If the thread was suspended by another app thread, 866 * do nothing and report no error (we won't resume it later). 867 */ 868 if (error == JVMTI_ERROR_THREAD_SUSPENDED) { 869 error = JVMTI_ERROR_NONE; 870 } 871 872 return error; 873 } 874 875 /* 876 * Deferred suspends happen when the suspend is attempted on a thread 877 * that is not started. Bookkeeping (suspendCount,etc.) 878 * is handled by the original request, and once the thread actually 879 * starts, an actual suspend is attempted. This function does the 880 * deferred suspend without changing the bookkeeping that is already 881 * in place. 882 */ 883 static jint 884 deferredSuspendThreadByNode(ThreadNode *node) 885 { 886 jvmtiError error; 887 888 error = JVMTI_ERROR_NONE; 889 if (node->isDebugThread) { 890 /* Ignore requests for suspending debugger threads */ 891 return JVMTI_ERROR_NONE; 892 } 893 894 /* 895 * Do the actual suspend only if a subsequent resume hasn't 896 * made it irrelevant. 897 */ 898 if (node->suspendCount > 0) { 899 error = commonSuspendByNode(node); 900 901 /* 902 * Attempt to clean up from any error by decrementing the 903 * suspend count. This compensates for the increment that 904 * happens when suspendOnStart is set to true. 905 */ 906 if (error != JVMTI_ERROR_NONE) { 907 node->suspendCount--; 908 } 909 } 910 911 node->suspendOnStart = JNI_FALSE; 912 913 debugMonitorNotifyAll(threadLock); 914 915 return error; 916 } 917 918 static jvmtiError 919 suspendThreadByNode(ThreadNode *node) 920 { 921 jvmtiError error = JVMTI_ERROR_NONE; 922 if (node->isDebugThread) { 923 /* Ignore requests for suspending debugger threads */ 924 return JVMTI_ERROR_NONE; 925 } 926 927 /* 928 * Just increment the suspend count if we are waiting 929 * for a deferred suspend. 930 */ 931 if (node->suspendOnStart) { 932 node->suspendCount++; 933 return JVMTI_ERROR_NONE; 934 } 935 936 if (node->suspendCount == 0) { 937 error = commonSuspendByNode(node); 938 939 if (error == JVMTI_ERROR_THREAD_NOT_ALIVE) { 940 /* 941 * This error means that the thread is either a zombie or not yet 942 * started. In either case, we ignore the error. If the thread 943 * is a zombie, suspend/resume are no-ops. If the thread is not 944 * started, it will be suspended for real during the processing 945 * of its thread start event. 946 */ 947 node->suspendOnStart = JNI_TRUE; 948 error = JVMTI_ERROR_NONE; 949 } 950 } 951 952 if (error == JVMTI_ERROR_NONE) { 953 node->suspendCount++; 954 } 955 956 debugMonitorNotifyAll(threadLock); 957 958 return error; 959 } 960 961 static jvmtiError 962 resumeThreadByNode(ThreadNode *node) 963 { 964 jvmtiError error = JVMTI_ERROR_NONE; 965 966 if (node->isDebugThread) { 967 /* never suspended by debugger => don't ever try to resume */ 968 return JVMTI_ERROR_NONE; 969 } 970 if (node->suspendCount > 0) { 971 node->suspendCount--; 972 debugMonitorNotifyAll(threadLock); 973 if ((node->suspendCount == 0) && node->toBeResumed && 974 !node->suspendOnStart) { 975 LOG_MISC(("thread=%p resumed", node->thread)); 976 error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread) 977 (gdata->jvmti, node->thread); 978 node->frameGeneration++; /* Increment on each resume */ 979 node->toBeResumed = JNI_FALSE; 980 if (error == JVMTI_ERROR_THREAD_NOT_ALIVE && !node->isStarted) { 981 /* 982 * We successfully "suspended" this thread, but 983 * we never received a THREAD_START event for it. 984 * Since the thread never ran, we can ignore our 985 * failure to resume the thread. 986 */ 987 error = JVMTI_ERROR_NONE; 988 } 989 } 990 } 991 992 return error; 993 } 994 995 /* 996 * Functions which respond to user requests to suspend/resume 997 * threads. 998 * Suspends and resumes add and subtract from a count respectively. 999 * The thread is only suspended when the count goes from 0 to 1 and 1000 * resumed only when the count goes from 1 to 0. 1001 * 1002 * These functions suspend and resume application threads 1003 * without changing the 1004 * state of threads that were already suspended beforehand. 1005 * They must not be called from an application thread because 1006 * that thread may be suspended somewhere in the middle of things. 1007 */ 1008 static void 1009 preSuspend(void) 1010 { 1011 getLocks(); /* Avoid debugger deadlocks */ 1012 1013 /* 1014 * Delay any suspend while a call to java.lang.Thread.resume is in 1015 * progress (not including those in suspended threads). The wait is 1016 * timed because the threads suspended through 1017 * java.lang.Thread.suspend won't result in a notify even though 1018 * it may change the result of pendingAppResume() 1019 */ 1020 while (pendingAppResume(JNI_FALSE)) { 1021 /* 1022 * This is ugly but we need to release the locks from getLocks 1023 * or else the notify will never happen. The locks must be 1024 * released and reacquired in the right order. else deadlocks 1025 * can happen. It is possible that, during this dance, the 1026 * notify will be missed, but since the wait needs to be timed 1027 * anyway, it won't be a disaster. Note that this code will 1028 * execute only on very rare occasions anyway. 1029 */ 1030 releaseLocks(); 1031 1032 debugMonitorEnter(threadLock); 1033 debugMonitorTimedWait(threadLock, 1000); 1034 debugMonitorExit(threadLock); 1035 1036 getLocks(); 1037 } 1038 } 1039 1040 static void 1041 postSuspend(void) 1042 { 1043 releaseLocks(); 1044 } 1045 1046 /* 1047 * This function must be called after preSuspend and before postSuspend. 1048 */ 1049 static jvmtiError 1050 commonSuspend(JNIEnv *env, jthread thread, jboolean deferred) 1051 { 1052 ThreadNode *node; 1053 1054 /* 1055 * If the thread is not between its start and end events, we should 1056 * still suspend it. To keep track of things, add the thread 1057 * to a separate list of threads so that we'll resume it later. 1058 */ 1059 node = findThread(&runningThreads, thread); 1060 if (node == NULL) { 1061 node = insertThread(env, &otherThreads, thread); 1062 } 1063 1064 if ( deferred ) { 1065 return deferredSuspendThreadByNode(node); 1066 } else { 1067 return suspendThreadByNode(node); 1068 } 1069 } 1070 1071 1072 static jvmtiError 1073 resumeCopyHelper(JNIEnv *env, ThreadNode *node, void *arg) 1074 { 1075 if (node->isDebugThread) { 1076 /* never suspended by debugger => don't ever try to resume */ 1077 return JVMTI_ERROR_NONE; 1078 } 1079 1080 if (node->suspendCount > 1) { 1081 node->suspendCount--; 1082 /* nested suspend so just undo one level */ 1083 return JVMTI_ERROR_NONE; 1084 } 1085 1086 /* 1087 * This thread was marked for suspension since its THREAD_START 1088 * event came in during a suspendAll, but the helper hasn't 1089 * completed the job yet. We decrement the count so the helper 1090 * won't suspend this thread after we are done with the resumeAll. 1091 * Another case to be handled here is when the debugger suspends 1092 * the thread while the app has it suspended. In this case, 1093 * the toBeResumed flag has been cleared indicating that 1094 * the thread should not be resumed when the debugger does a resume. 1095 * In this case, we also have to decrement the suspend count. 1096 * If we don't then when the app resumes the thread and our Thread.resume 1097 * bkpt handler is called, blockOnDebuggerSuspend will not resume 1098 * the thread because suspendCount will be 1 meaning that the 1099 * debugger has the thread suspended. See bug 6224859. 1100 */ 1101 if (node->suspendCount == 1 && (!node->toBeResumed || node->suspendOnStart)) { 1102 node->suspendCount--; 1103 return JVMTI_ERROR_NONE; 1104 } 1105 1106 if (arg == NULL) { 1107 /* nothing to hard resume so we're done */ 1108 return JVMTI_ERROR_NONE; 1109 } 1110 1111 /* 1112 * This is tricky. A suspendCount of 1 and toBeResumed means that 1113 * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called 1114 * on this thread. The check for !suspendOnStart is paranoia that 1115 * we inherited from resumeThreadByNode(). 1116 */ 1117 if (node->suspendCount == 1 && node->toBeResumed && !node->suspendOnStart) { 1118 jthread **listPtr = (jthread **)arg; 1119 1120 **listPtr = node->thread; 1121 (*listPtr)++; 1122 } 1123 return JVMTI_ERROR_NONE; 1124 } 1125 1126 1127 static jvmtiError 1128 resumeCountHelper(JNIEnv *env, ThreadNode *node, void *arg) 1129 { 1130 if (node->isDebugThread) { 1131 /* never suspended by debugger => don't ever try to resume */ 1132 return JVMTI_ERROR_NONE; 1133 } 1134 1135 /* 1136 * This is tricky. A suspendCount of 1 and toBeResumed means that 1137 * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called 1138 * on this thread. The check for !suspendOnStart is paranoia that 1139 * we inherited from resumeThreadByNode(). 1140 */ 1141 if (node->suspendCount == 1 && node->toBeResumed && !node->suspendOnStart) { 1142 jint *counter = (jint *)arg; 1143 1144 (*counter)++; 1145 } 1146 return JVMTI_ERROR_NONE; 1147 } 1148 1149 static void * 1150 newArray(jint length, size_t nbytes) 1151 { 1152 void *ptr; 1153 ptr = jvmtiAllocate(length*(jint)nbytes); 1154 if ( ptr != NULL ) { 1155 (void)memset(ptr, 0, length*nbytes); 1156 } 1157 return ptr; 1158 } 1159 1160 static void 1161 deleteArray(void *ptr) 1162 { 1163 jvmtiDeallocate(ptr); 1164 } 1165 1166 /* 1167 * This function must be called with the threadLock held. 1168 * 1169 * Two facts conspire to make this routine complicated: 1170 * 1171 * 1) the VM doesn't support nested external suspend 1172 * 2) the original resumeAll code structure doesn't retrieve the 1173 * entire thread list from JVMTI so we use the runningThreads 1174 * list and two helpers to get the job done. 1175 * 1176 * Because we hold the threadLock, state seen by resumeCountHelper() 1177 * is the same state seen in resumeCopyHelper(). resumeCountHelper() 1178 * just counts up the number of threads to be hard resumed. 1179 * resumeCopyHelper() does the accounting for nested suspends and 1180 * special cases and, finally, populates the list of hard resume 1181 * threads to be passed to ResumeThreadList(). 1182 * 1183 * At first glance, you might think that the accounting could be done 1184 * in resumeCountHelper(), but then resumeCopyHelper() would see 1185 * "post-resume" state in the accounting values (suspendCount and 1186 * toBeResumed) and would not be able to distinguish between a thread 1187 * that needs a hard resume versus a thread that is already running. 1188 */ 1189 static jvmtiError 1190 commonResumeList(JNIEnv *env) 1191 { 1192 jvmtiError error; 1193 jint i; 1194 jint reqCnt; 1195 jthread *reqList; 1196 jthread *reqPtr; 1197 jvmtiError *results; 1198 1199 reqCnt = 0; 1200 1201 /* count number of threads to hard resume */ 1202 (void) enumerateOverThreadList(env, &runningThreads, resumeCountHelper, 1203 &reqCnt); 1204 if (reqCnt == 0) { 1205 /* nothing to hard resume so do just the accounting part */ 1206 (void) enumerateOverThreadList(env, &runningThreads, resumeCopyHelper, 1207 NULL); 1208 return JVMTI_ERROR_NONE; 1209 } 1210 1211 /*LINTED*/ 1212 reqList = newArray(reqCnt, sizeof(jthread)); 1213 if (reqList == NULL) { 1214 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"resume request list"); 1215 } 1216 /*LINTED*/ 1217 results = newArray(reqCnt, sizeof(jvmtiError)); 1218 if (results == NULL) { 1219 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"resume list"); 1220 } 1221 1222 /* copy the jthread values for threads to hard resume */ 1223 reqPtr = reqList; 1224 (void) enumerateOverThreadList(env, &runningThreads, resumeCopyHelper, 1225 &reqPtr); 1226 1227 error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThreadList) 1228 (gdata->jvmti, reqCnt, reqList, results); 1229 for (i = 0; i < reqCnt; i++) { 1230 ThreadNode *node; 1231 1232 node = findThread(&runningThreads, reqList[i]); 1233 if (node == NULL) { 1234 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD,"missing entry in running thread table"); 1235 } 1236 LOG_MISC(("thread=%p resumed as part of list", node->thread)); 1237 1238 /* 1239 * resumeThreadByNode() assumes that JVM/DI ResumeThread() 1240 * always works and does all the accounting updates. We do 1241 * the same here. We also don't clear the error. 1242 */ 1243 node->suspendCount--; 1244 node->toBeResumed = JNI_FALSE; 1245 node->frameGeneration++; /* Increment on each resume */ 1246 } 1247 deleteArray(results); 1248 deleteArray(reqList); 1249 1250 debugMonitorNotifyAll(threadLock); 1251 1252 return error; 1253 } 1254 1255 1256 /* 1257 * This function must be called after preSuspend and before postSuspend. 1258 */ 1259 static jvmtiError 1260 commonSuspendList(JNIEnv *env, jint initCount, jthread *initList) 1261 { 1262 jvmtiError error; 1263 jint i; 1264 jint reqCnt; 1265 jthread *reqList; 1266 1267 error = JVMTI_ERROR_NONE; 1268 reqCnt = 0; 1269 reqList = newArray(initCount, sizeof(jthread)); 1270 if (reqList == NULL) { 1271 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"request list"); 1272 } 1273 1274 /* 1275 * Go through the initial list and see if we have anything to suspend. 1276 */ 1277 for (i = 0; i < initCount; i++) { 1278 ThreadNode *node; 1279 1280 /* 1281 * If the thread is not between its start and end events, we should 1282 * still suspend it. To keep track of things, add the thread 1283 * to a separate list of threads so that we'll resume it later. 1284 */ 1285 node = findThread(&runningThreads, initList[i]); 1286 if (node == NULL) { 1287 node = insertThread(env, &otherThreads, initList[i]); 1288 } 1289 1290 if (node->isDebugThread) { 1291 /* Ignore requests for suspending debugger threads */ 1292 continue; 1293 } 1294 1295 /* 1296 * Just increment the suspend count if we are waiting 1297 * for a deferred suspend or if this is a nested suspend. 1298 */ 1299 if (node->suspendOnStart || node->suspendCount > 0) { 1300 node->suspendCount++; 1301 continue; 1302 } 1303 1304 if (node->suspendCount == 0) { 1305 /* thread is not suspended yet so put it on the request list */ 1306 reqList[reqCnt++] = initList[i]; 1307 } 1308 } 1309 1310 if (reqCnt > 0) { 1311 jvmtiError *results = newArray(reqCnt, sizeof(jvmtiError)); 1312 1313 if (results == NULL) { 1314 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"suspend list results"); 1315 } 1316 1317 /* 1318 * We have something to suspend so try to do it. 1319 */ 1320 error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThreadList) 1321 (gdata->jvmti, reqCnt, reqList, results); 1322 for (i = 0; i < reqCnt; i++) { 1323 ThreadNode *node; 1324 1325 node = findThread(NULL, reqList[i]); 1326 if (node == NULL) { 1327 EXIT_ERROR(AGENT_ERROR_INVALID_THREAD,"missing entry in thread tables"); 1328 } 1329 LOG_MISC(("thread=%p suspended as part of list", node->thread)); 1330 1331 if (results[i] == JVMTI_ERROR_NONE) { 1332 /* thread was suspended as requested */ 1333 node->toBeResumed = JNI_TRUE; 1334 } else if (results[i] == JVMTI_ERROR_THREAD_SUSPENDED) { 1335 /* 1336 * If the thread was suspended by another app thread, 1337 * do nothing and report no error (we won't resume it later). 1338 */ 1339 results[i] = JVMTI_ERROR_NONE; 1340 } else if (results[i] == JVMTI_ERROR_THREAD_NOT_ALIVE) { 1341 /* 1342 * This error means that the suspend request failed 1343 * because the thread is either a zombie or not yet 1344 * started. In either case, we ignore the error. If the 1345 * thread is a zombie, suspend/resume are no-ops. If the 1346 * thread is not started, it will be suspended for real 1347 * during the processing of its thread start event. 1348 */ 1349 node->suspendOnStart = JNI_TRUE; 1350 results[i] = JVMTI_ERROR_NONE; 1351 } 1352 1353 /* count real, app and deferred (suspendOnStart) suspensions */ 1354 if (results[i] == JVMTI_ERROR_NONE) { 1355 node->suspendCount++; 1356 } 1357 } 1358 deleteArray(results); 1359 } 1360 deleteArray(reqList); 1361 1362 debugMonitorNotifyAll(threadLock); 1363 1364 return error; 1365 } 1366 1367 1368 static jvmtiError 1369 commonResume(jthread thread) 1370 { 1371 jvmtiError error; 1372 ThreadNode *node; 1373 1374 /* 1375 * The thread is normally between its start and end events, but if 1376 * not, check the auxiliary list used by threadControl_suspendThread. 1377 */ 1378 node = findThread(NULL, thread); 1379 1380 /* 1381 * If the node is in neither list, the debugger never suspended 1382 * this thread, so do nothing. 1383 */ 1384 error = JVMTI_ERROR_NONE; 1385 if (node != NULL) { 1386 error = resumeThreadByNode(node); 1387 } 1388 return error; 1389 } 1390 1391 1392 jvmtiError 1393 threadControl_suspendThread(jthread thread, jboolean deferred) 1394 { 1395 jvmtiError error; 1396 JNIEnv *env; 1397 1398 env = getEnv(); 1399 1400 log_debugee_location("threadControl_suspendThread()", thread, NULL, 0); 1401 1402 preSuspend(); 1403 error = commonSuspend(env, thread, deferred); 1404 postSuspend(); 1405 1406 return error; 1407 } 1408 1409 jvmtiError 1410 threadControl_resumeThread(jthread thread, jboolean do_unblock) 1411 { 1412 jvmtiError error; 1413 JNIEnv *env; 1414 1415 env = getEnv(); 1416 1417 log_debugee_location("threadControl_resumeThread()", thread, NULL, 0); 1418 1419 eventHandler_lock(); /* for proper lock order */ 1420 debugMonitorEnter(threadLock); 1421 error = commonResume(thread); 1422 removeResumed(env, &otherThreads); 1423 debugMonitorExit(threadLock); 1424 eventHandler_unlock(); 1425 1426 if (do_unblock) { 1427 /* let eventHelper.c: commandLoop() know we resumed one thread */ 1428 unblockCommandLoop(); 1429 } 1430 1431 return error; 1432 } 1433 1434 jvmtiError 1435 threadControl_suspendCount(jthread thread, jint *count) 1436 { 1437 jvmtiError error; 1438 ThreadNode *node; 1439 1440 debugMonitorEnter(threadLock); 1441 1442 node = findThread(&runningThreads, thread); 1443 if (node == NULL) { 1444 node = findThread(&otherThreads, thread); 1445 } 1446 1447 error = JVMTI_ERROR_NONE; 1448 if (node != NULL) { 1449 *count = node->suspendCount; 1450 } else { 1451 /* 1452 * If the node is in neither list, the debugger never suspended 1453 * this thread, so the suspend count is 0. 1454 */ 1455 *count = 0; 1456 } 1457 1458 debugMonitorExit(threadLock); 1459 1460 return error; 1461 } 1462 1463 static jboolean 1464 contains(JNIEnv *env, jthread *list, jint count, jthread item) 1465 { 1466 int i; 1467 1468 for (i = 0; i < count; i++) { 1469 if (isSameObject(env, list[i], item)) { 1470 return JNI_TRUE; 1471 } 1472 } 1473 return JNI_FALSE; 1474 } 1475 1476 1477 typedef struct { 1478 jthread *list; 1479 jint count; 1480 } SuspendAllArg; 1481 1482 static jvmtiError 1483 suspendAllHelper(JNIEnv *env, ThreadNode *node, void *arg) 1484 { 1485 SuspendAllArg *saArg = (SuspendAllArg *)arg; 1486 jvmtiError error = JVMTI_ERROR_NONE; 1487 jthread *list = saArg->list; 1488 jint count = saArg->count; 1489 if (!contains(env, list, count, node->thread)) { 1490 error = commonSuspend(env, node->thread, JNI_FALSE); 1491 } 1492 return error; 1493 } 1494 1495 jvmtiError 1496 threadControl_suspendAll(void) 1497 { 1498 jvmtiError error; 1499 JNIEnv *env; 1500 1501 env = getEnv(); 1502 1503 log_debugee_location("threadControl_suspendAll()", NULL, NULL, 0); 1504 1505 preSuspend(); 1506 1507 /* 1508 * Get a list of all threads and suspend them. 1509 */ 1510 WITH_LOCAL_REFS(env, 1) { 1511 1512 jthread *threads; 1513 jint count; 1514 1515 threads = allThreads(&count); 1516 if (threads == NULL) { 1517 error = AGENT_ERROR_OUT_OF_MEMORY; 1518 goto err; 1519 } 1520 if (canSuspendResumeThreadLists()) { 1521 error = commonSuspendList(env, count, threads); 1522 if (error != JVMTI_ERROR_NONE) { 1523 goto err; 1524 } 1525 } else { 1526 1527 int i; 1528 1529 for (i = 0; i < count; i++) { 1530 error = commonSuspend(env, threads[i], JNI_FALSE); 1531 1532 if (error != JVMTI_ERROR_NONE) { 1533 goto err; 1534 } 1535 } 1536 } 1537 1538 /* 1539 * Update the suspend count of any threads not yet (or no longer) 1540 * in the thread list above. 1541 */ 1542 { 1543 SuspendAllArg arg; 1544 arg.list = threads; 1545 arg.count = count; 1546 error = enumerateOverThreadList(env, &otherThreads, 1547 suspendAllHelper, &arg); 1548 } 1549 1550 if (error == JVMTI_ERROR_NONE) { 1551 suspendAllCount++; 1552 } 1553 1554 err: ; 1555 1556 } END_WITH_LOCAL_REFS(env) 1557 1558 postSuspend(); 1559 1560 return error; 1561 } 1562 1563 static jvmtiError 1564 resumeHelper(JNIEnv *env, ThreadNode *node, void *ignored) 1565 { 1566 /* 1567 * Since this helper is called with the threadLock held, we 1568 * don't need to recheck to see if the node is still on one 1569 * of the two thread lists. 1570 */ 1571 return resumeThreadByNode(node); 1572 } 1573 1574 jvmtiError 1575 threadControl_resumeAll(void) 1576 { 1577 jvmtiError error; 1578 JNIEnv *env; 1579 1580 env = getEnv(); 1581 1582 log_debugee_location("threadControl_resumeAll()", NULL, NULL, 0); 1583 1584 eventHandler_lock(); /* for proper lock order */ 1585 debugMonitorEnter(threadLock); 1586 1587 /* 1588 * Resume only those threads that the debugger has suspended. All 1589 * such threads must have a node in one of the thread lists, so there's 1590 * no need to get the whole thread list from JVMTI (unlike 1591 * suspendAll). 1592 */ 1593 if (canSuspendResumeThreadLists()) { 1594 error = commonResumeList(env); 1595 } else { 1596 error = enumerateOverThreadList(env, &runningThreads, 1597 resumeHelper, NULL); 1598 } 1599 if ((error == JVMTI_ERROR_NONE) && (otherThreads.first != NULL)) { 1600 error = enumerateOverThreadList(env, &otherThreads, 1601 resumeHelper, NULL); 1602 removeResumed(env, &otherThreads); 1603 } 1604 1605 if (suspendAllCount > 0) { 1606 suspendAllCount--; 1607 } 1608 1609 debugMonitorExit(threadLock); 1610 eventHandler_unlock(); 1611 /* let eventHelper.c: commandLoop() know we are resuming */ 1612 unblockCommandLoop(); 1613 1614 return error; 1615 } 1616 1617 1618 StepRequest * 1619 threadControl_getStepRequest(jthread thread) 1620 { 1621 ThreadNode *node; 1622 StepRequest *step; 1623 1624 step = NULL; 1625 1626 debugMonitorEnter(threadLock); 1627 1628 node = findThread(&runningThreads, thread); 1629 if (node != NULL) { 1630 step = &node->currentStep; 1631 } 1632 1633 debugMonitorExit(threadLock); 1634 1635 return step; 1636 } 1637 1638 InvokeRequest * 1639 threadControl_getInvokeRequest(jthread thread) 1640 { 1641 ThreadNode *node; 1642 InvokeRequest *request; 1643 1644 request = NULL; 1645 1646 debugMonitorEnter(threadLock); 1647 1648 node = findThread(&runningThreads, thread); 1649 if (node != NULL) { 1650 request = &node->currentInvoke; 1651 } 1652 1653 debugMonitorExit(threadLock); 1654 1655 return request; 1656 } 1657 1658 jvmtiError 1659 threadControl_addDebugThread(jthread thread) 1660 { 1661 jvmtiError error; 1662 1663 debugMonitorEnter(threadLock); 1664 if (debugThreadCount >= MAX_DEBUG_THREADS) { 1665 error = AGENT_ERROR_OUT_OF_MEMORY; 1666 } else { 1667 JNIEnv *env; 1668 1669 env = getEnv(); 1670 debugThreads[debugThreadCount] = NULL; 1671 saveGlobalRef(env, thread, &(debugThreads[debugThreadCount])); 1672 if (debugThreads[debugThreadCount] == NULL) { 1673 error = AGENT_ERROR_OUT_OF_MEMORY; 1674 } else { 1675 debugThreadCount++; 1676 error = JVMTI_ERROR_NONE; 1677 } 1678 } 1679 debugMonitorExit(threadLock); 1680 return error; 1681 } 1682 1683 static jvmtiError 1684 threadControl_removeDebugThread(jthread thread) 1685 { 1686 jvmtiError error; 1687 JNIEnv *env; 1688 int i; 1689 1690 error = AGENT_ERROR_INVALID_THREAD; 1691 env = getEnv(); 1692 1693 debugMonitorEnter(threadLock); 1694 for (i = 0; i< debugThreadCount; i++) { 1695 if (isSameObject(env, thread, debugThreads[i])) { 1696 int j; 1697 1698 tossGlobalRef(env, &(debugThreads[i])); 1699 for (j = i+1; j < debugThreadCount; j++) { 1700 debugThreads[j-1] = debugThreads[j]; 1701 } 1702 debugThreadCount--; 1703 error = JVMTI_ERROR_NONE; 1704 break; 1705 } 1706 } 1707 debugMonitorExit(threadLock); 1708 return error; 1709 } 1710 1711 jboolean 1712 threadControl_isDebugThread(jthread thread) 1713 { 1714 int i; 1715 jboolean rc; 1716 JNIEnv *env; 1717 1718 rc = JNI_FALSE; 1719 env = getEnv(); 1720 1721 debugMonitorEnter(threadLock); 1722 for (i = 0; i < debugThreadCount; i++) { 1723 if (isSameObject(env, thread, debugThreads[i])) { 1724 rc = JNI_TRUE; 1725 break; 1726 } 1727 } 1728 debugMonitorExit(threadLock); 1729 return rc; 1730 } 1731 1732 static void 1733 initLocks(void) 1734 { 1735 if (popFrameEventLock == NULL) { 1736 popFrameEventLock = debugMonitorCreate("JDWP PopFrame Event Lock"); 1737 popFrameProceedLock = debugMonitorCreate("JDWP PopFrame Proceed Lock"); 1738 } 1739 } 1740 1741 static jboolean 1742 getPopFrameThread(jthread thread) 1743 { 1744 jboolean popFrameThread; 1745 1746 debugMonitorEnter(threadLock); 1747 { 1748 ThreadNode *node; 1749 1750 node = findThread(NULL, thread); 1751 if (node == NULL) { 1752 popFrameThread = JNI_FALSE; 1753 } else { 1754 popFrameThread = node->popFrameThread; 1755 } 1756 } 1757 debugMonitorExit(threadLock); 1758 1759 return popFrameThread; 1760 } 1761 1762 static void 1763 setPopFrameThread(jthread thread, jboolean value) 1764 { 1765 debugMonitorEnter(threadLock); 1766 { 1767 ThreadNode *node; 1768 1769 node = findThread(NULL, thread); 1770 if (node == NULL) { 1771 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table"); 1772 } else { 1773 node->popFrameThread = value; 1774 } 1775 } 1776 debugMonitorExit(threadLock); 1777 } 1778 1779 static jboolean 1780 getPopFrameEvent(jthread thread) 1781 { 1782 jboolean popFrameEvent; 1783 1784 debugMonitorEnter(threadLock); 1785 { 1786 ThreadNode *node; 1787 1788 node = findThread(NULL, thread); 1789 if (node == NULL) { 1790 popFrameEvent = JNI_FALSE; 1791 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table"); 1792 } else { 1793 popFrameEvent = node->popFrameEvent; 1794 } 1795 } 1796 debugMonitorExit(threadLock); 1797 1798 return popFrameEvent; 1799 } 1800 1801 static void 1802 setPopFrameEvent(jthread thread, jboolean value) 1803 { 1804 debugMonitorEnter(threadLock); 1805 { 1806 ThreadNode *node; 1807 1808 node = findThread(NULL, thread); 1809 if (node == NULL) { 1810 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table"); 1811 } else { 1812 node->popFrameEvent = value; 1813 node->frameGeneration++; /* Increment on each resume */ 1814 } 1815 } 1816 debugMonitorExit(threadLock); 1817 } 1818 1819 static jboolean 1820 getPopFrameProceed(jthread thread) 1821 { 1822 jboolean popFrameProceed; 1823 1824 debugMonitorEnter(threadLock); 1825 { 1826 ThreadNode *node; 1827 1828 node = findThread(NULL, thread); 1829 if (node == NULL) { 1830 popFrameProceed = JNI_FALSE; 1831 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table"); 1832 } else { 1833 popFrameProceed = node->popFrameProceed; 1834 } 1835 } 1836 debugMonitorExit(threadLock); 1837 1838 return popFrameProceed; 1839 } 1840 1841 static void 1842 setPopFrameProceed(jthread thread, jboolean value) 1843 { 1844 debugMonitorEnter(threadLock); 1845 { 1846 ThreadNode *node; 1847 1848 node = findThread(NULL, thread); 1849 if (node == NULL) { 1850 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"entry in thread table"); 1851 } else { 1852 node->popFrameProceed = value; 1853 } 1854 } 1855 debugMonitorExit(threadLock); 1856 } 1857 1858 /** 1859 * Special event handler for events on the popped thread 1860 * that occur during the pop operation. 1861 */ 1862 static void 1863 popFrameCompleteEvent(jthread thread) 1864 { 1865 debugMonitorEnter(popFrameProceedLock); 1866 { 1867 /* notify that we got the event */ 1868 debugMonitorEnter(popFrameEventLock); 1869 { 1870 setPopFrameEvent(thread, JNI_TRUE); 1871 debugMonitorNotify(popFrameEventLock); 1872 } 1873 debugMonitorExit(popFrameEventLock); 1874 1875 /* make sure we get suspended again */ 1876 setPopFrameProceed(thread, JNI_FALSE); 1877 while (getPopFrameProceed(thread) == JNI_FALSE) { 1878 debugMonitorWait(popFrameProceedLock); 1879 } 1880 } 1881 debugMonitorExit(popFrameProceedLock); 1882 } 1883 1884 /** 1885 * Pop one frame off the stack of thread. 1886 * popFrameEventLock is already held 1887 */ 1888 static jvmtiError 1889 popOneFrame(jthread thread) 1890 { 1891 jvmtiError error; 1892 1893 error = JVMTI_FUNC_PTR(gdata->jvmti,PopFrame)(gdata->jvmti, thread); 1894 if (error != JVMTI_ERROR_NONE) { 1895 return error; 1896 } 1897 1898 /* resume the popped thread so that the pop occurs and so we */ 1899 /* will get the event (step or method entry) after the pop */ 1900 LOG_MISC(("thread=%p resumed in popOneFrame", thread)); 1901 error = JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)(gdata->jvmti, thread); 1902 if (error != JVMTI_ERROR_NONE) { 1903 return error; 1904 } 1905 1906 /* wait for the event to occur */ 1907 setPopFrameEvent(thread, JNI_FALSE); 1908 while (getPopFrameEvent(thread) == JNI_FALSE) { 1909 debugMonitorWait(popFrameEventLock); 1910 } 1911 1912 /* make sure not to suspend until the popped thread is on the wait */ 1913 debugMonitorEnter(popFrameProceedLock); 1914 { 1915 /* return popped thread to suspended state */ 1916 LOG_MISC(("thread=%p suspended in popOneFrame", thread)); 1917 error = JVMTI_FUNC_PTR(gdata->jvmti,SuspendThread)(gdata->jvmti, thread); 1918 1919 /* notify popped thread so it can proceed when resumed */ 1920 setPopFrameProceed(thread, JNI_TRUE); 1921 debugMonitorNotify(popFrameProceedLock); 1922 } 1923 debugMonitorExit(popFrameProceedLock); 1924 1925 return error; 1926 } 1927 1928 /** 1929 * pop frames of the stack of 'thread' until 'frame' is popped. 1930 */ 1931 jvmtiError 1932 threadControl_popFrames(jthread thread, FrameNumber fnum) 1933 { 1934 jvmtiError error; 1935 jvmtiEventMode prevStepMode; 1936 jint framesPopped = 0; 1937 jint popCount; 1938 jboolean prevInvokeRequestMode; 1939 1940 log_debugee_location("threadControl_popFrames()", thread, NULL, 0); 1941 1942 initLocks(); 1943 1944 /* compute the number of frames to pop */ 1945 popCount = fnum+1; 1946 if (popCount < 1) { 1947 return AGENT_ERROR_NO_MORE_FRAMES; 1948 } 1949 1950 /* enable instruction level single step, but first note prev value */ 1951 prevStepMode = threadControl_getInstructionStepMode(thread); 1952 1953 /* 1954 * Fix bug 6517249. The pop processing will disable invokes, 1955 * so remember if invokes are enabled now and restore 1956 * that state after we finish popping. 1957 */ 1958 prevInvokeRequestMode = invoker_isEnabled(thread); 1959 1960 error = threadControl_setEventMode(JVMTI_ENABLE, 1961 EI_SINGLE_STEP, thread); 1962 if (error != JVMTI_ERROR_NONE) { 1963 return error; 1964 } 1965 1966 /* Inform eventHandler logic we are in a popFrame for this thread */ 1967 debugMonitorEnter(popFrameEventLock); 1968 { 1969 setPopFrameThread(thread, JNI_TRUE); 1970 /* pop frames using single step */ 1971 while (framesPopped++ < popCount) { 1972 error = popOneFrame(thread); 1973 if (error != JVMTI_ERROR_NONE) { 1974 break; 1975 } 1976 } 1977 setPopFrameThread(thread, JNI_FALSE); 1978 } 1979 debugMonitorExit(popFrameEventLock); 1980 1981 /* Reset StepRequest info (fromLine and stackDepth) after popframes 1982 * only if stepping is enabled. 1983 */ 1984 if (prevStepMode == JVMTI_ENABLE) { 1985 stepControl_resetRequest(thread); 1986 } 1987 1988 if (prevInvokeRequestMode) { 1989 invoker_enableInvokeRequests(thread); 1990 } 1991 1992 /* restore state */ 1993 (void)threadControl_setEventMode(prevStepMode, 1994 EI_SINGLE_STEP, thread); 1995 1996 return error; 1997 } 1998 1999 /* Check to see if any events are being consumed by a popFrame(). */ 2000 static jboolean 2001 checkForPopFrameEvents(JNIEnv *env, EventIndex ei, jthread thread) 2002 { 2003 if ( getPopFrameThread(thread) ) { 2004 switch (ei) { 2005 case EI_THREAD_START: 2006 /* Excuse me? */ 2007 EXIT_ERROR(AGENT_ERROR_INTERNAL, "thread start during pop frame"); 2008 break; 2009 case EI_THREAD_END: 2010 /* Thread wants to end? let it. */ 2011 setPopFrameThread(thread, JNI_FALSE); 2012 popFrameCompleteEvent(thread); 2013 break; 2014 case EI_SINGLE_STEP: 2015 /* This is an event we requested to mark the */ 2016 /* completion of the pop frame */ 2017 popFrameCompleteEvent(thread); 2018 return JNI_TRUE; 2019 case EI_BREAKPOINT: 2020 case EI_EXCEPTION: 2021 case EI_FIELD_ACCESS: 2022 case EI_FIELD_MODIFICATION: 2023 case EI_METHOD_ENTRY: 2024 case EI_METHOD_EXIT: 2025 /* Tell event handler to assume event has been consumed. */ 2026 return JNI_TRUE; 2027 default: 2028 break; 2029 } 2030 } 2031 /* Pretend we were never called */ 2032 return JNI_FALSE; 2033 } 2034 2035 struct bag * 2036 threadControl_onEventHandlerEntry(jbyte sessionID, EventIndex ei, jthread thread, jobject currentException) 2037 { 2038 ThreadNode *node; 2039 JNIEnv *env; 2040 struct bag *eventBag; 2041 jthread threadToSuspend; 2042 jboolean consumed; 2043 2044 env = getEnv(); 2045 threadToSuspend = NULL; 2046 2047 log_debugee_location("threadControl_onEventHandlerEntry()", thread, NULL, 0); 2048 2049 /* Events during pop commands may need to be ignored here. */ 2050 consumed = checkForPopFrameEvents(env, ei, thread); 2051 if ( consumed ) { 2052 /* Always restore any exception (see below). */ 2053 if (currentException != NULL) { 2054 JNI_FUNC_PTR(env,Throw)(env, currentException); 2055 } else { 2056 JNI_FUNC_PTR(env,ExceptionClear)(env); 2057 } 2058 return NULL; 2059 } 2060 2061 debugMonitorEnter(threadLock); 2062 2063 /* 2064 * Check the list of unknown threads maintained by suspend 2065 * and resume. If this thread is currently present in the 2066 * list, it should be 2067 * moved to the runningThreads list, since it is a 2068 * well-known thread now. 2069 */ 2070 node = findThread(&otherThreads, thread); 2071 if (node != NULL) { 2072 moveNode(&otherThreads, &runningThreads, node); 2073 } else { 2074 /* 2075 * Get a thread node for the reporting thread. For thread start 2076 * events, or if this event precedes a thread start event, 2077 * the thread node may need to be created. 2078 * 2079 * It is possible for certain events (notably method entry/exit) 2080 * to precede thread start for some VM implementations. 2081 */ 2082 node = insertThread(env, &runningThreads, thread); 2083 } 2084 2085 if (ei == EI_THREAD_START) { 2086 node->isStarted = JNI_TRUE; 2087 processDeferredEventModes(env, thread, node); 2088 } 2089 2090 node->current_ei = ei; 2091 eventBag = node->eventBag; 2092 if (node->suspendOnStart) { 2093 threadToSuspend = node->thread; 2094 } 2095 debugMonitorExit(threadLock); 2096 2097 if (threadToSuspend != NULL) { 2098 /* 2099 * An attempt was made to suspend this thread before it started. 2100 * We must suspend it now, before it starts to run. This must 2101 * be done with no locks held. 2102 */ 2103 eventHelper_suspendThread(sessionID, threadToSuspend); 2104 } 2105 2106 return eventBag; 2107 } 2108 2109 static void 2110 doPendingTasks(JNIEnv *env, ThreadNode *node) 2111 { 2112 /* 2113 * Take care of any pending interrupts/stops, and clear out 2114 * info on pending interrupts/stops. 2115 */ 2116 if (node->pendingInterrupt) { 2117 JVMTI_FUNC_PTR(gdata->jvmti,InterruptThread) 2118 (gdata->jvmti, node->thread); 2119 /* 2120 * TO DO: Log error 2121 */ 2122 node->pendingInterrupt = JNI_FALSE; 2123 } 2124 2125 if (node->pendingStop != NULL) { 2126 JVMTI_FUNC_PTR(gdata->jvmti,StopThread) 2127 (gdata->jvmti, node->thread, node->pendingStop); 2128 /* 2129 * TO DO: Log error 2130 */ 2131 tossGlobalRef(env, &(node->pendingStop)); 2132 } 2133 } 2134 2135 void 2136 threadControl_onEventHandlerExit(EventIndex ei, jthread thread, 2137 struct bag *eventBag) 2138 { 2139 ThreadNode *node; 2140 2141 log_debugee_location("threadControl_onEventHandlerExit()", thread, NULL, 0); 2142 2143 if (ei == EI_THREAD_END) { 2144 eventHandler_lock(); /* for proper lock order */ 2145 } 2146 debugMonitorEnter(threadLock); 2147 2148 node = findThread(&runningThreads, thread); 2149 if (node == NULL) { 2150 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"thread list corrupted"); 2151 } else { 2152 JNIEnv *env; 2153 2154 env = getEnv(); 2155 if (ei == EI_THREAD_END) { 2156 jboolean inResume = (node->resumeFrameDepth > 0); 2157 removeThread(env, &runningThreads, thread); 2158 node = NULL; /* has been freed */ 2159 2160 /* 2161 * Clean up mechanism used to detect end of 2162 * resume. 2163 */ 2164 if (inResume) { 2165 notifyAppResumeComplete(); 2166 } 2167 } else { 2168 /* No point in doing this if the thread is about to die.*/ 2169 doPendingTasks(env, node); 2170 node->eventBag = eventBag; 2171 node->current_ei = 0; 2172 } 2173 } 2174 2175 debugMonitorExit(threadLock); 2176 if (ei == EI_THREAD_END) { 2177 eventHandler_unlock(); 2178 } 2179 } 2180 2181 /* Returns JDWP flavored status and status flags. */ 2182 jvmtiError 2183 threadControl_applicationThreadStatus(jthread thread, 2184 jdwpThreadStatus *pstatus, jint *statusFlags) 2185 { 2186 ThreadNode *node; 2187 jvmtiError error; 2188 jint state; 2189 2190 log_debugee_location("threadControl_applicationThreadStatus()", thread, NULL, 0); 2191 2192 debugMonitorEnter(threadLock); 2193 2194 error = threadState(thread, &state); 2195 *pstatus = map2jdwpThreadStatus(state); 2196 *statusFlags = map2jdwpSuspendStatus(state); 2197 2198 if (error == JVMTI_ERROR_NONE) { 2199 node = findThread(&runningThreads, thread); 2200 if ((node != NULL) && HANDLING_EVENT(node)) { 2201 /* 2202 * While processing an event, an application thread is always 2203 * considered to be running even if its handler happens to be 2204 * cond waiting on an internal debugger monitor, etc. 2205 * 2206 * Leave suspend status untouched since it is not possible 2207 * to distinguish debugger suspends from app suspends. 2208 */ 2209 *pstatus = JDWP_THREAD_STATUS(RUNNING); 2210 } 2211 } 2212 2213 debugMonitorExit(threadLock); 2214 2215 return error; 2216 } 2217 2218 jvmtiError 2219 threadControl_interrupt(jthread thread) 2220 { 2221 ThreadNode *node; 2222 jvmtiError error; 2223 2224 error = JVMTI_ERROR_NONE; 2225 2226 log_debugee_location("threadControl_interrupt()", thread, NULL, 0); 2227 2228 debugMonitorEnter(threadLock); 2229 2230 node = findThread(&runningThreads, thread); 2231 if ((node == NULL) || !HANDLING_EVENT(node)) { 2232 error = JVMTI_FUNC_PTR(gdata->jvmti,InterruptThread) 2233 (gdata->jvmti, thread); 2234 } else { 2235 /* 2236 * Hold any interrupts until after the event is processed. 2237 */ 2238 node->pendingInterrupt = JNI_TRUE; 2239 } 2240 2241 debugMonitorExit(threadLock); 2242 2243 return error; 2244 } 2245 2246 void 2247 threadControl_clearCLEInfo(JNIEnv *env, jthread thread) 2248 { 2249 ThreadNode *node; 2250 2251 debugMonitorEnter(threadLock); 2252 2253 node = findThread(&runningThreads, thread); 2254 if (node != NULL) { 2255 node->cleInfo.ei = 0; 2256 if (node->cleInfo.clazz != NULL) { 2257 tossGlobalRef(env, &(node->cleInfo.clazz)); 2258 } 2259 } 2260 2261 debugMonitorExit(threadLock); 2262 } 2263 2264 jboolean 2265 threadControl_cmpCLEInfo(JNIEnv *env, jthread thread, jclass clazz, 2266 jmethodID method, jlocation location) 2267 { 2268 ThreadNode *node; 2269 jboolean result; 2270 2271 result = JNI_FALSE; 2272 2273 debugMonitorEnter(threadLock); 2274 2275 node = findThread(&runningThreads, thread); 2276 if (node != NULL && node->cleInfo.ei != 0 && 2277 node->cleInfo.method == method && 2278 node->cleInfo.location == location && 2279 (isSameObject(env, node->cleInfo.clazz, clazz))) { 2280 result = JNI_TRUE; /* we have a match */ 2281 } 2282 2283 debugMonitorExit(threadLock); 2284 2285 return result; 2286 } 2287 2288 void 2289 threadControl_saveCLEInfo(JNIEnv *env, jthread thread, EventIndex ei, 2290 jclass clazz, jmethodID method, jlocation location) 2291 { 2292 ThreadNode *node; 2293 2294 debugMonitorEnter(threadLock); 2295 2296 node = findThread(&runningThreads, thread); 2297 if (node != NULL) { 2298 node->cleInfo.ei = ei; 2299 /* Create a class ref that will live beyond */ 2300 /* the end of this call */ 2301 saveGlobalRef(env, clazz, &(node->cleInfo.clazz)); 2302 /* if returned clazz is NULL, we just won't match */ 2303 node->cleInfo.method = method; 2304 node->cleInfo.location = location; 2305 } 2306 2307 debugMonitorExit(threadLock); 2308 } 2309 2310 void 2311 threadControl_setPendingInterrupt(jthread thread) 2312 { 2313 ThreadNode *node; 2314 2315 debugMonitorEnter(threadLock); 2316 2317 node = findThread(&runningThreads, thread); 2318 if (node != NULL) { 2319 node->pendingInterrupt = JNI_TRUE; 2320 } 2321 2322 debugMonitorExit(threadLock); 2323 } 2324 2325 jvmtiError 2326 threadControl_stop(jthread thread, jobject throwable) 2327 { 2328 ThreadNode *node; 2329 jvmtiError error; 2330 2331 error = JVMTI_ERROR_NONE; 2332 2333 log_debugee_location("threadControl_stop()", thread, NULL, 0); 2334 2335 debugMonitorEnter(threadLock); 2336 2337 node = findThread(&runningThreads, thread); 2338 if ((node == NULL) || !HANDLING_EVENT(node)) { 2339 error = JVMTI_FUNC_PTR(gdata->jvmti,StopThread) 2340 (gdata->jvmti, thread, throwable); 2341 } else { 2342 JNIEnv *env; 2343 2344 /* 2345 * Hold any stops until after the event is processed. 2346 */ 2347 env = getEnv(); 2348 saveGlobalRef(env, throwable, &(node->pendingStop)); 2349 } 2350 2351 debugMonitorExit(threadLock); 2352 2353 return error; 2354 } 2355 2356 static jvmtiError 2357 detachHelper(JNIEnv *env, ThreadNode *node, void *arg) 2358 { 2359 invoker_detach(&node->currentInvoke); 2360 return JVMTI_ERROR_NONE; 2361 } 2362 2363 void 2364 threadControl_detachInvokes(void) 2365 { 2366 JNIEnv *env; 2367 2368 env = getEnv(); 2369 invoker_lock(); /* for proper lock order */ 2370 debugMonitorEnter(threadLock); 2371 (void)enumerateOverThreadList(env, &runningThreads, detachHelper, NULL); 2372 debugMonitorExit(threadLock); 2373 invoker_unlock(); 2374 } 2375 2376 static jvmtiError 2377 resetHelper(JNIEnv *env, ThreadNode *node, void *arg) 2378 { 2379 if (node->toBeResumed) { 2380 LOG_MISC(("thread=%p resumed", node->thread)); 2381 (void)JVMTI_FUNC_PTR(gdata->jvmti,ResumeThread)(gdata->jvmti, node->thread); 2382 node->frameGeneration++; /* Increment on each resume */ 2383 } 2384 stepControl_clearRequest(node->thread, &node->currentStep); 2385 node->toBeResumed = JNI_FALSE; 2386 node->suspendCount = 0; 2387 node->suspendOnStart = JNI_FALSE; 2388 2389 return JVMTI_ERROR_NONE; 2390 } 2391 2392 void 2393 threadControl_reset(void) 2394 { 2395 JNIEnv *env; 2396 2397 env = getEnv(); 2398 eventHandler_lock(); /* for proper lock order */ 2399 debugMonitorEnter(threadLock); 2400 (void)enumerateOverThreadList(env, &runningThreads, resetHelper, NULL); 2401 (void)enumerateOverThreadList(env, &otherThreads, resetHelper, NULL); 2402 2403 removeResumed(env, &otherThreads); 2404 2405 freeDeferredEventModes(env); 2406 2407 suspendAllCount = 0; 2408 2409 /* Everything should have been resumed */ 2410 JDI_ASSERT(otherThreads.first == NULL); 2411 2412 debugMonitorExit(threadLock); 2413 eventHandler_unlock(); 2414 } 2415 2416 jvmtiEventMode 2417 threadControl_getInstructionStepMode(jthread thread) 2418 { 2419 ThreadNode *node; 2420 jvmtiEventMode mode; 2421 2422 mode = JVMTI_DISABLE; 2423 2424 debugMonitorEnter(threadLock); 2425 node = findThread(&runningThreads, thread); 2426 if (node != NULL) { 2427 mode = node->instructionStepMode; 2428 } 2429 debugMonitorExit(threadLock); 2430 return mode; 2431 } 2432 2433 jvmtiError 2434 threadControl_setEventMode(jvmtiEventMode mode, EventIndex ei, jthread thread) 2435 { 2436 jvmtiError error; 2437 2438 /* Global event */ 2439 if ( thread == NULL ) { 2440 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode) 2441 (gdata->jvmti, mode, eventIndex2jvmti(ei), thread); 2442 } else { 2443 /* Thread event */ 2444 ThreadNode *node; 2445 2446 debugMonitorEnter(threadLock); 2447 { 2448 node = findThread(&runningThreads, thread); 2449 if ((node == NULL) || (!node->isStarted)) { 2450 JNIEnv *env; 2451 2452 env = getEnv(); 2453 error = addDeferredEventMode(env, mode, ei, thread); 2454 } else { 2455 error = threadSetEventNotificationMode(node, 2456 mode, ei, thread); 2457 } 2458 } 2459 debugMonitorExit(threadLock); 2460 2461 } 2462 return error; 2463 } 2464 2465 /* 2466 * Returns the current thread, if the thread has generated at least 2467 * one event, and has not generated a thread end event. 2468 */ 2469 jthread threadControl_currentThread(void) 2470 { 2471 jthread thread; 2472 2473 debugMonitorEnter(threadLock); 2474 { 2475 ThreadNode *node; 2476 2477 node = findThread(&runningThreads, NULL); 2478 thread = (node == NULL) ? NULL : node->thread; 2479 } 2480 debugMonitorExit(threadLock); 2481 2482 return thread; 2483 } 2484 2485 jlong 2486 threadControl_getFrameGeneration(jthread thread) 2487 { 2488 jlong frameGeneration = -1; 2489 2490 debugMonitorEnter(threadLock); 2491 { 2492 ThreadNode *node; 2493 2494 node = findThread(NULL, thread); 2495 2496 if (node != NULL) { 2497 frameGeneration = node->frameGeneration; 2498 } 2499 } 2500 debugMonitorExit(threadLock); 2501 2502 return frameGeneration; 2503 } 2504