2362N/A * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A * Collection of info for properly handling co-located events. 0N/A * If the ei field is non-zero, then one of the possible 0N/A * co-located events has been posted and the other fields describe 0N/A * the event's location. 0N/A * The main data structure in threadControl is the ThreadNode. 0N/A * This is a per-thread structure that is allocated on the 0N/A * first event that occurs in a thread. It is freed after the 0N/A * thread's thread end event has completed processing. The 0N/A * structure contains state information on its thread including 0N/A * suspend counts. It also acts as a repository for other 0N/A * per-thread state such as the current method invocation or 0N/A * suspendCount is the number of outstanding suspends 0N/A * from the debugger. suspends from the app itself are 0N/A * not included in this count. 0N/A * popFrameEventLock is used to notify that the event has been received 0N/A * popFrameProceedLock is used to assure that the event thread is 0N/A * re-suspended immediately after the event is acknowledged. 0N/A * Threads which have issued thread start events and not yet issued thread 0N/A * end events are maintained in the "runningThreads" list. All other threads known 0N/A * to this module are kept in the "otherThreads" list. 0N/A/* Get the state of the thread direct from JVMTI */ 0N/A/* Set TLS on a specific jthread to the ThreadNode* */ 0N/A /* Just return, thread hasn't started yet */ 0N/A /* The jthread object must be valid, so this must be a fatal error */ 0N/A/* Get TLS on a specific jthread, which is the ThreadNode* */ 0N/A /* Just return NULL, thread hasn't started yet */ 0N/A /* The jthread object must be valid, so this must be a fatal error */ 0N/A/* Search list for nodes that don't have TLS set and match this thread. 0N/A * It assumed that this logic is never dealing with terminated threads, 0N/A * since the ThreadEnd events always delete the ThreadNode while the 0N/A * jthread is still alive. So we can only look at the ThreadNode's that 0N/A * have never had their TLS set, making the search much faster. 0N/A * But keep in mind, this kind of search should rarely be needed. 0N/A * These functions maintain the linked list of currently running threads. 0N/A * All assume that the threadLock is held before calling. 0N/A * If list==NULL, search both lists. 0N/A /* Get thread local storage for quick thread -> node access */ 0N/A /* In some rare cases we might get NULL, so we check the list manually for 0N/A * any threads that we could match. 0N/A /* Here we make another attempt to set TLS, it's ok if this fails */ 0N/A /* If a list is supplied, only return ones in this list */ 0N/A/* Remove a ThreadNode from a ThreadList */ 0N/A/* Add a ThreadNode to a ThreadList */ 0N/A * Init all flags false, all refs NULL, all counts 0 0N/A * Remember if it is a debug thread 0N/A * If there is a pending suspendAll, all new threads should 0N/A * be initialized as if they were suspended by the suspendAll, 0N/A * and the thread will need to be suspended when it starts. 0N/A /* Set thread local storage for quick thread -> node access. 0N/A * Some threads may not be in a state that allows setting of TLS, 0N/A * which is ok, see findThread, it deals with threads without TLS set. 0N/A /* Clear out TLS on this thread (just a cleanup action) */ 0N/A /* record single step mode */ 0N/A * Anything which might be locked as part of the handling of 0N/A * a JVMTI event (which means: might be locked by an application 0N/A * thread) needs to be grabbed here. This allows thread control 0N/A * code to safely suspend and resume the application threads 0N/A * while ensuring they don't hold a critical lock. 0N/A /* Get the java.lang.Thread.resume() method beginning location */ 0N/A * Hold up any attempt to resume as long as the debugger 0N/A * has suspended the resumee. 0N/A * Track the resuming thread by marking it as being within 0N/A * a resume and by setting up for notification on 0N/A * a frame pop or exception. We won't allow the debugger 0N/A * to suspend threads while any thread is within a 0N/A * call to resume. This (along with the block above) 0N/A * ensures that when the debugger 0N/A * suspends a thread it will remain suspended. 0N/A * As soon as the event hook is in place, we need to initialize 0N/A * the thread list with already-existing threads. The threadLock 0N/A * has been held since initialize, so we don't need to worry about 0N/A * insertions or deletions from the event handlers while we do this 0N/A * Prevent any event processing until OnHook has been called 0N/A * This is a tiny bit risky. We have to assume that the 0N/A * pre-existing threads have been started because we 0N/A * can't rely on a thread start event for them. The chances 0N/A * of a problem related to this are pretty slim though, and 0N/A * there's really no choice because without setting this flag 0N/A * there is no way to enable stepping and other events on 0N/A * the threads that already exist (e.g. the finalizer thread). 0N/A * Mark for resume only if suspend succeeded 0N/A * If the thread was suspended by another app thread, 0N/A * do nothing and report no error (we won't resume it later). 0N/A * Deferred suspends happen when the suspend is attempted on a thread 0N/A * that is not started. Bookkeeping (suspendCount,etc.) 0N/A * is handled by the original request, and once the thread actually 0N/A * starts, an actual suspend is attempted. This function does the 0N/A * deferred suspend without changing the bookkeeping that is already 0N/A /* Ignore requests for suspending debugger threads */ 0N/A * Do the actual suspend only if a subsequent resume hasn't 0N/A * made it irrelevant. 0N/A * Attempt to clean up from any error by decrementing the 0N/A * suspend count. This compensates for the increment that 0N/A * happens when suspendOnStart is set to true. 0N/A /* Ignore requests for suspending debugger threads */ 0N/A * Just increment the suspend count if we are waiting 0N/A * for a deferred suspend. 0N/A * This error means that the thread is either a zombie or not yet 0N/A * started. In either case, we ignore the error. If the thread 0N/A * started, it will be suspended for real during the processing 0N/A * of its thread start event. 0N/A /* never suspended by debugger => don't ever try to resume */ 0N/A * We successfully "suspended" this thread, but 0N/A * we never received a THREAD_START event for it. 0N/A * Since the thread never ran, we can ignore our 0N/A * failure to resume the thread. 0N/A * Suspends and resumes add and subtract from a count respectively. 0N/A * The thread is only suspended when the count goes from 0 to 1 and 0N/A * resumed only when the count goes from 1 to 0. 0N/A * These functions suspend and resume application threads 0N/A * without changing the 0N/A * state of threads that were already suspended beforehand. 0N/A * They must not be called from an application thread because 0N/A * that thread may be suspended somewhere in the middle of things. 0N/A * Delay any suspend while a call to java.lang.Thread.resume is in 0N/A * progress (not including those in suspended threads). The wait is 0N/A * timed because the threads suspended through 0N/A * it may change the result of pendingAppResume() 0N/A * This is ugly but we need to release the locks from getLocks 0N/A * or else the notify will never happen. The locks must be 0N/A * released and reacquired in the right order. else deadlocks 0N/A * can happen. It is possible that, during this dance, the 0N/A * notify will be missed, but since the wait needs to be timed 0N/A * anyway, it won't be a disaster. Note that this code will 0N/A * execute only on very rare occasions anyway. 0N/A * This function must be called after preSuspend and before postSuspend. 0N/A * If the thread is not between its start and end events, we should 0N/A * still suspend it. To keep track of things, add the thread 0N/A * to a separate list of threads so that we'll resume it later. 0N/A /* never suspended by debugger => don't ever try to resume */ 0N/A /* nested suspend so just undo one level */ 0N/A * This thread was marked for suspension since its THREAD_START 0N/A * event came in during a suspendAll, but the helper hasn't 0N/A * completed the job yet. We decrement the count so the helper 0N/A * won't suspend this thread after we are done with the resumeAll. 0N/A * Another case to be handled here is when the debugger suspends 0N/A * the thread while the app has it suspended. In this case, 0N/A * the toBeResumed flag has been cleared indicating that 0N/A * the thread should not be resumed when the debugger does a resume. 0N/A * In this case, we also have to decrement the suspend count. 0N/A * If we don't then when the app resumes the thread and our Thread.resume 0N/A * bkpt handler is called, blockOnDebuggerSuspend will not resume 0N/A * the thread because suspendCount will be 1 meaning that the 0N/A * debugger has the thread suspended. See bug 6224859. 0N/A /* nothing to hard resume so we're done */ 0N/A * This is tricky. A suspendCount of 1 and toBeResumed means that 0N/A * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called 0N/A * on this thread. The check for !suspendOnStart is paranoia that 0N/A * we inherited from resumeThreadByNode(). 0N/A /* never suspended by debugger => don't ever try to resume */ 0N/A * This is tricky. A suspendCount of 1 and toBeResumed means that 0N/A * JVM/DI SuspendThread() or JVM/DI SuspendThreadList() was called 0N/A * on this thread. The check for !suspendOnStart is paranoia that 0N/A * we inherited from resumeThreadByNode(). 0N/A * This function must be called with the threadLock held. 0N/A * Two facts conspire to make this routine complicated: 0N/A * 1) the VM doesn't support nested external suspend 0N/A * 2) the original resumeAll code structure doesn't retrieve the 0N/A * entire thread list from JVMTI so we use the runningThreads 0N/A * list and two helpers to get the job done. 0N/A * Because we hold the threadLock, state seen by resumeCountHelper() 0N/A * is the same state seen in resumeCopyHelper(). resumeCountHelper() 0N/A * just counts up the number of threads to be hard resumed. 0N/A * resumeCopyHelper() does the accounting for nested suspends and 0N/A * special cases and, finally, populates the list of hard resume 0N/A * threads to be passed to ResumeThreadList(). 0N/A * At first glance, you might think that the accounting could be done 0N/A * in resumeCountHelper(), but then resumeCopyHelper() would see 0N/A * "post-resume" state in the accounting values (suspendCount and 0N/A * toBeResumed) and would not be able to distinguish between a thread 0N/A * that needs a hard resume versus a thread that is already running. 0N/A /* count number of threads to hard resume */ 0N/A /* nothing to hard resume so do just the accounting part */ 0N/A /* copy the jthread values for threads to hard resume */ 0N/A * resumeThreadByNode() assumes that JVM/DI ResumeThread() 0N/A * always works and does all the accounting updates. We do 0N/A * the same here. We also don't clear the error. 0N/A * This function must be called after preSuspend and before postSuspend. 0N/A * Go through the initial list and see if we have anything to suspend. 0N/A * If the thread is not between its start and end events, we should 0N/A * still suspend it. To keep track of things, add the thread 0N/A * to a separate list of threads so that we'll resume it later. 0N/A /* Ignore requests for suspending debugger threads */ 0N/A * Just increment the suspend count if we are waiting 0N/A * for a deferred suspend or if this is a nested suspend. 0N/A /* thread is not suspended yet so put it on the request list */ 0N/A * We have something to suspend so try to do it. 0N/A /* thread was suspended as requested */ 0N/A * If the thread was suspended by another app thread, 0N/A * do nothing and report no error (we won't resume it later). 0N/A * This error means that the suspend request failed 0N/A * because the thread is either a zombie or not yet 0N/A * started. In either case, we ignore the error. If the 0N/A * thread is not started, it will be suspended for real 0N/A * during the processing of its thread start event. 0N/A /* count real, app and deferred (suspendOnStart) suspensions */ 0N/A * The thread is normally between its start and end events, but if 0N/A * not, check the auxiliary list used by threadControl_suspendThread. 0N/A * If the node is in neither list, the debugger never suspended 0N/A * this thread, so do nothing. 0N/A * If the node is in neither list, the debugger never suspended 0N/A * this thread, so the suspend count is 0. 0N/A * Get a list of all threads and suspend them. 0N/A * Update the suspend count of any threads not yet (or no longer) 0N/A * in the thread list above. 0N/A * Since this helper is called with the threadLock held, we 0N/A * don't need to recheck to see if the node is still on one 0N/A * of the two thread lists. 0N/A * Resume only those threads that the debugger has suspended. All 0N/A * such threads must have a node in one of the thread lists, so there's 0N/A * no need to get the whole thread list from JVMTI (unlike 0N/A * Special event handler for events on the popped thread 0N/A * that occur during the pop operation. 0N/A /* notify that we got the event */ 0N/A /* make sure we get suspended again */ 0N/A * Pop one frame off the stack of thread. 0N/A * popFrameEventLock is already held 0N/A /* resume the popped thread so that the pop occurs and so we */ 0N/A /* will get the event (step or method entry) after the pop */ 0N/A /* wait for the event to occur */ 0N/A /* make sure not to suspend until the popped thread is on the wait */ 0N/A /* return popped thread to suspended state */ 0N/A /* notify popped thread so it can proceed when resumed */ 0N/A * pop frames of the stack of 'thread' until 'frame' is popped. 0N/A /* compute the number of frames to pop */ 0N/A /* enable instruction level single step, but first note prev value */ 0N/A * Fix bug 6517249. The pop processing will disable invokes, 0N/A * so remember if invokes are enabled now and restore 0N/A * that state after we finish popping. 0N/A /* Inform eventHandler logic we are in a popFrame for this thread */ 0N/A /* pop frames using single step */ 0N/A /* Reset StepRequest info (fromLine and stackDepth) after popframes 0N/A * only if stepping is enabled. 0N/A/* Check to see if any events are being consumed by a popFrame(). */ 0N/A /* Thread wants to end? let it. */ 0N/A /* This is an event we requested to mark the */ 0N/A /* completion of the pop frame */ 0N/A /* Tell event handler to assume event has been consumed. */ 0N/A /* Pretend we were never called */ 0N/A /* Events during pop commands may need to be ignored here. */ 0N/A /* Always restore any exception (see below). */ 0N/A * Check the list of unknown threads maintained by suspend 0N/A * and resume. If this thread is currently present in the 0N/A * list, it should be 0N/A * moved to the runningThreads list, since it is a 0N/A * well-known thread now. 0N/A * Get a thread node for the reporting thread. For thread start 0N/A * events, or if this event precedes a thread start event, 0N/A * the thread node may need to be created. 0N/A * It is possible for certain events (notably method entry/exit) 0N/A * to precede thread start for some VM implementations. 0N/A * An attempt was made to suspend this thread before it started. 0N/A * We must suspend it now, before it starts to run. This must 0N/A * be done with no locks held. 0N/A * Clean up mechanism used to detect end of 0N/A /* No point in doing this if the thread is about to die.*/ 0N/A/* Returns JDWP flavored status and status flags. */ 0N/A * While processing an event, an application thread is always 0N/A * considered to be running even if its handler happens to be 0N/A * cond waiting on an internal debugger monitor, etc. 0N/A * Leave suspend status untouched since it is not possible 0N/A * to distinguish debugger suspends from app suspends. 0N/A * Hold any interrupts until after the event is processed. 0N/A /* Create a class ref that will live beyond */ 0N/A /* the end of this call */ 0N/A /* if returned clazz is NULL, we just won't match */ 0N/A * Hold any stops until after the event is processed. 0N/A /* Everything should have been resumed */ 0N/A * Returns the current thread, if the thread has generated at least 0N/A * one event, and has not generated a thread end event.