• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
getStackDepth(jthread thread)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
threadState(jthread thread,jint * pstate)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
setThreadLocalStorage(jthread thread,ThreadNode * node)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 *
getThreadLocalStorage(jthread thread)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 *
nonTlsSearch(JNIEnv * env,ThreadList * list,jthread thread)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 *
findThread(ThreadList * list,jthread thread)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
removeNode(ThreadList * list,ThreadNode * node)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
addNode(ThreadList * list,ThreadNode * node)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 *
insertThread(JNIEnv * env,ThreadList * list,jthread thread)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
clearThread(JNIEnv * env,ThreadNode * node)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
removeThread(JNIEnv * env,ThreadList * list,jthread thread)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
removeResumed(JNIEnv * env,ThreadList * list)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
moveNode(ThreadList * source,ThreadList * dest,ThreadNode * node)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
enumerateOverThreadList(JNIEnv * env,ThreadList * list,ThreadEnumerateFunction function,void * arg)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
insertEventMode(DeferredEventModeList * list,DeferredEventMode * eventMode)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
removeEventMode(DeferredEventModeList * list,DeferredEventMode * eventMode,DeferredEventMode * prev)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
addDeferredEventMode(JNIEnv * env,jvmtiEventMode mode,EventIndex ei,jthread thread)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
freeDeferredEventModes(JNIEnv * env)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
threadSetEventNotificationMode(ThreadNode * node,jvmtiEventMode mode,EventIndex ei,jthread thread)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
processDeferredEventModes(JNIEnv * env,jthread thread,ThreadNode * node)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
getLocks(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
releaseLocks(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
threadControl_initialize(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
getResumee(jthread resumingThread)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
pendingAppResume(jboolean includeSuspended)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
notifyAppResumeComplete(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
handleAppResumeCompletion(JNIEnv * env,EventInfo * evinfo,HandlerNode * handlerNode,struct bag * eventBag)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
blockOnDebuggerSuspend(jthread thread)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
trackAppResume(jthread thread)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
handleAppResumeBreakpoint(JNIEnv * env,EventInfo * evinfo,HandlerNode * handlerNode,struct bag * eventBag)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
threadControl_onConnect(void)771 threadControl_onConnect(void)
772 {
773     breakpointHandlerNode = eventHandler_createInternalBreakpoint(
774                  handleAppResumeBreakpoint, NULL,
775                  gdata->threadClass, gdata->threadResume, resumeLocation);
776 }
777 
778 void
threadControl_onDisconnect(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
threadControl_onHook(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
commonSuspendByNode(ThreadNode * node)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
deferredSuspendThreadByNode(ThreadNode * node)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
suspendThreadByNode(ThreadNode * node)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
resumeThreadByNode(ThreadNode * node)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
preSuspend(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
postSuspend(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
commonSuspend(JNIEnv * env,jthread thread,jboolean deferred)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
resumeCopyHelper(JNIEnv * env,ThreadNode * node,void * arg)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
resumeCountHelper(JNIEnv * env,ThreadNode * node,void * arg)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 *
newArray(jint length,size_t nbytes)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
deleteArray(void * ptr)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
commonResumeList(JNIEnv * env)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
commonSuspendList(JNIEnv * env,jint initCount,jthread * initList)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
commonResume(jthread thread)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
threadControl_suspendThread(jthread thread,jboolean deferred)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
threadControl_resumeThread(jthread thread,jboolean do_unblock)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
threadControl_suspendCount(jthread thread,jint * count)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
contains(JNIEnv * env,jthread * list,jint count,jthread item)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
suspendAllHelper(JNIEnv * env,ThreadNode * node,void * arg)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
threadControl_suspendAll(void)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
resumeHelper(JNIEnv * env,ThreadNode * node,void * ignored)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
threadControl_resumeAll(void)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 *
threadControl_getStepRequest(jthread thread)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 *
threadControl_getInvokeRequest(jthread thread)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
threadControl_addDebugThread(jthread thread)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
threadControl_removeDebugThread(jthread thread)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
threadControl_isDebugThread(jthread thread)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
initLocks(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
getPopFrameThread(jthread thread)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
setPopFrameThread(jthread thread,jboolean value)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
getPopFrameEvent(jthread thread)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
setPopFrameEvent(jthread thread,jboolean value)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
getPopFrameProceed(jthread thread)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
setPopFrameProceed(jthread thread,jboolean value)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
popFrameCompleteEvent(jthread thread)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
popOneFrame(jthread thread)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
threadControl_popFrames(jthread thread,FrameNumber fnum)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
checkForPopFrameEvents(JNIEnv * env,EventIndex ei,jthread thread)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 *
threadControl_onEventHandlerEntry(jbyte sessionID,EventIndex ei,jthread thread,jobject currentException)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
doPendingTasks(JNIEnv * env,ThreadNode * node)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
threadControl_onEventHandlerExit(EventIndex ei,jthread thread,struct bag * eventBag)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
threadControl_applicationThreadStatus(jthread thread,jdwpThreadStatus * pstatus,jint * statusFlags)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
threadControl_interrupt(jthread thread)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
threadControl_clearCLEInfo(JNIEnv * env,jthread thread)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
threadControl_cmpCLEInfo(JNIEnv * env,jthread thread,jclass clazz,jmethodID method,jlocation location)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
threadControl_saveCLEInfo(JNIEnv * env,jthread thread,EventIndex ei,jclass clazz,jmethodID method,jlocation location)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
threadControl_setPendingInterrupt(jthread thread)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
threadControl_stop(jthread thread,jobject throwable)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
detachHelper(JNIEnv * env,ThreadNode * node,void * arg)2357 detachHelper(JNIEnv *env, ThreadNode *node, void *arg)
2358 {
2359     invoker_detach(&node->currentInvoke);
2360     return JVMTI_ERROR_NONE;
2361 }
2362 
2363 void
threadControl_detachInvokes(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
resetHelper(JNIEnv * env,ThreadNode * node,void * arg)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
threadControl_reset(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
threadControl_getInstructionStepMode(jthread thread)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
threadControl_setEventMode(jvmtiEventMode mode,EventIndex ei,jthread thread)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  */
threadControl_currentThread(void)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
threadControl_getFrameGeneration(jthread thread)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