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