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