// Waits until this thread is the one that the proxy considers the current // thread. // NB: if the thread is not the current thread, and we're asked to check // breakpoints, then if there are no breakpoints which could effect this // thread we simply return false and stop processing the current interrupt. bool DebuggerProxy::blockUntilOwn(CmdInterrupt &cmd, bool check) { int64_t self = cmd.getThreadId(); TRACE(2, "DebuggerProxy::blockUntilOwn for thread %" PRIx64 "\n", self); Lock lock(this); if (m_thread && m_thread != self) { if (check && (m_threadMode == Exclusive || !checkBreakPoints(cmd))) { // Flow control commands only belong to sticky thread TRACE(2, "No need to interrupt this thread\n"); return false; } m_threads[self] = createThreadInfo(cmd.desc()); while (!m_stopped && m_thread && m_thread != self) { TRACE(2, "Waiting...\n"); wait(1); // If for whatever reason, m_thread isn't debugging anymore (for example, // it runs in Sticky mode, but it finishes running), kick it out. if (m_thread && !Debugger::IsThreadDebugging(m_thread)) { TRACE(2, "Old thread abandoned debugging, taking over!\n"); m_threadMode = Normal; m_thread = 0; m_newThread.reset(); m_flow.reset(); } } TRACE(2, "Ready to become current thread for this proxy\n"); m_threads.erase(self); if (m_stopped) return false; if (!checkBreakPoints(cmd)) { // The breakpoint might have been removed while I'm waiting return false; } } // This thread is now the one the proxy considers the current thread. if (m_thread == 0) { TRACE(2, "Updating current thread\n"); m_thread = self; } TRACE(2, "Current thread for this proxy tid=%" PRIx64 "\n", self); return true; }
// Forms a list of all threads which are currently blocked within this // proxy. There is the thread currently processing an interrupt, plus // any other threads stacked up in blockUntilOwn() (represented in the // m_threads set). void DebuggerProxy::getThreads(std::vector<DThreadInfoPtr> &threads) { TRACE(2, "DebuggerProxy::getThreads\n"); Lock lock(this); auto& interrupts = RID().interrupts; assertx(!interrupts.empty()); if (!interrupts.empty()) { CmdInterrupt *tint = (CmdInterrupt*)interrupts.top(); assertx(tint); if (tint) { threads.push_back(createThreadInfo(tint->desc())); } } for (std::map<int64_t, DThreadInfoPtr>::const_iterator iter = m_threads.begin(); iter != m_threads.end(); ++iter) { DThreadInfoPtr thread(new DThreadInfo()); *thread = *iter->second; threads.push_back(thread); } }
// Forms a list of all threads which are currently blocked within this // proxy. There is the thread currently processing an interrupt, plus // any other threads stacked up in blockUntilOwn() (represented in the // m_threads set). void DebuggerProxy::getThreads(DThreadInfoPtrVec &threads) { TRACE(2, "DebuggerProxy::getThreads\n"); Lock lock(this); std::stack<void *> &interrupts = ThreadInfo::s_threadInfo->m_reqInjectionData.interrupts; assert(!interrupts.empty()); if (!interrupts.empty()) { CmdInterrupt *tint = (CmdInterrupt*)interrupts.top(); assert(tint); if (tint) { threads.push_back(createThreadInfo(tint->desc())); } } for (std::map<int64_t, DThreadInfoPtr>::const_iterator iter = m_threads.begin(); iter != m_threads.end(); ++iter) { DThreadInfoPtr thread(new DThreadInfo()); *thread = *iter->second; threads.push_back(thread); } }
// Waits until this thread is the one that the proxy considers the current // thread. This also check to see if the given cmd has any breakpoints or // flow control that we should stop for. Note: while stepping, pretty much all // of the stepping logic is handled below here and this will return false if // the stepping operation has not completed. bool DebuggerProxy::blockUntilOwn(CmdInterrupt &cmd, bool check) { TRACE(2, "DebuggerProxy::blockUntilOwn\n"); int64_t self = cmd.getThreadId(); Lock lock(this); if (m_thread && m_thread != self) { if (check && (m_threadMode == Exclusive || !checkBreakPoints(cmd))) { // Flow control commands only belong to sticky thread return false; } m_threads[self] = createThreadInfo(cmd.desc()); while (!m_stopped && m_thread && m_thread != self) { wait(1); // if for whatever reason, m_thread isn't debugging anymore (for example, // it runs in Sticky mode, but it finishes running), kick it out. if (!Debugger::IsThreadDebugging(m_thread)) { m_threadMode = Normal; m_thread = self; m_newThread.reset(); m_flow.reset(); } } m_threads.erase(self); if (m_stopped) return false; if (!checkBreakPoints(cmd)) { // The breakpoint might have been removed while I'm waiting return false; } } else if (check && !checkFlowBreak(cmd)) { return false; } if (m_thread == 0) { m_thread = self; } return true; }