diff options
author | Chris Lattner <sabre@nondot.org> | 2010-06-08 16:52:24 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-06-08 16:52:24 +0000 |
commit | 30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c (patch) | |
tree | f70013106f6a461a14abcd71c65f48a95a2979a6 /lldb/tools/debugserver/source/RNBContext.cpp | |
parent | 312c4c799da215b337f790fda330f70c4aa757cf (diff) | |
download | bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.tar.gz bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.zip |
Initial checkin of lldb code from internal Apple repo.
llvm-svn: 105619
Diffstat (limited to 'lldb/tools/debugserver/source/RNBContext.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/RNBContext.cpp | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/lldb/tools/debugserver/source/RNBContext.cpp b/lldb/tools/debugserver/source/RNBContext.cpp new file mode 100644 index 00000000000..7ef9d32c74e --- /dev/null +++ b/lldb/tools/debugserver/source/RNBContext.cpp @@ -0,0 +1,230 @@ +//===-- RNBContext.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Created by Greg Clayton on 12/12/07. +// +//===----------------------------------------------------------------------===// + +#include "RNBContext.h" +#include "RNBRemote.h" +#include "DNB.h" +#include "DNBLog.h" +#include "CFString.h" +#include <sstream> + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +RNBContext::~RNBContext() +{ + SetProcessID (INVALID_NUB_PROCESS); +} + +//---------------------------------------------------------------------- +// RNBContext constructor +//---------------------------------------------------------------------- + +const char * +RNBContext::EnvironmentAtIndex (int index) +{ + if (index < m_env_vec.size()) + return m_env_vec[index].c_str(); + else + return NULL; +} + + +const char * +RNBContext::ArgumentAtIndex (int index) +{ + if (index < m_arg_vec.size()) + return m_arg_vec[index].c_str(); + else + return NULL; +} + +void +RNBContext::SetProcessID (nub_process_t pid) +{ + // Delete and events we created + if (m_pid != INVALID_NUB_PROCESS) + { + StopProcessStatusThread (); + // Unregister this context as a client of the process's events. + } + // Assign our new process ID + m_pid = pid; + + if (pid != INVALID_NUB_PROCESS) + { + StartProcessStatusThread (); + } +} + +void +RNBContext::StartProcessStatusThread() +{ + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); + if ((m_events.GetEventBits() & event_proc_thread_running) == 0) + { + int err = ::pthread_create (&m_pid_pthread, NULL, ThreadFunctionProcessStatus, this); + if (err == 0) + { + // Our thread was successfully kicked off, wait for it to + // set the started event so we can safely continue + m_events.WaitForSetEvents (event_proc_thread_running); + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread got started!", __FUNCTION__); + } + else + { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread failed to start: err = %i", __FUNCTION__, err); + m_events.ResetEvents (event_proc_thread_running); + m_events.SetEvents (event_proc_thread_exiting); + } + } +} + +void +RNBContext::StopProcessStatusThread() +{ + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); + if ((m_events.GetEventBits() & event_proc_thread_running) == event_proc_thread_running) + { + struct timespec timeout_abstime; + DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); + // Wait for 2 seconds for the rx thread to exit + if (m_events.WaitForSetEvents(RNBContext::event_proc_thread_exiting, &timeout_abstime) == RNBContext::event_proc_thread_exiting) + { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread stopped as requeseted", __FUNCTION__); + } + else + { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread did not stop in 2 seconds...", __FUNCTION__); + // Kill the RX thread??? + } + } +} + +//---------------------------------------------------------------------- +// This thread's sole purpose is to watch for any status changes in the +// child process. +//---------------------------------------------------------------------- +void* +RNBContext::ThreadFunctionProcessStatus(void *arg) +{ + RNBRemoteSP remoteSP(g_remoteSP); + RNBRemote* remote = remoteSP.get(); + if (remote == NULL) + return NULL; + RNBContext& ctx = remote->Context(); + + nub_process_t pid = ctx.ProcessID(); + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", __FUNCTION__, arg, pid); + ctx.Events().SetEvents (RNBContext::event_proc_thread_running); + bool done = false; + while (!done) + { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable, true)...", __FUNCTION__); + nub_event_t pid_status_event = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable, true, NULL); + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable, true) => 0x%8.8x", __FUNCTION__, pid_status_event); + + if (pid_status_event == 0) + { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back from DNBProcessWaitForEvent....", __FUNCTION__, pid); + // done = true; + } + else + { + if (pid_status_event & eEventStdioAvailable) + { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got stdio available event....", __FUNCTION__, pid); + ctx.Events().SetEvents (RNBContext::event_proc_stdio_available); + // Wait for the main thread to consume this notification if it requested we wait for it + ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available); + } + + + if (pid_status_event & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) + { + nub_state_t pid_state = DNBProcessGetState(pid); + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got process state change: %s", __FUNCTION__, pid, DNBStateAsString(pid_state)); + + // Let the main thread know there is a process state change to see + ctx.Events().SetEvents (RNBContext::event_proc_state_changed); + // Wait for the main thread to consume this notification if it requested we wait for it + ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed); + + switch (pid_state) + { + case eStateStopped: + break; + + case eStateInvalid: + case eStateExited: + done = true; + break; + } + } + + // Reset any events that we consumed. + DNBProcessResetEvents(pid, pid_status_event); + + } + } + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", __FUNCTION__, arg, pid); + ctx.Events().ResetEvents(event_proc_thread_running); + ctx.Events().SetEvents(event_proc_thread_exiting); + return NULL; +} + + +const char* +RNBContext::EventsAsString (nub_event_t events, std::string& s) +{ + s.clear(); + if (events & event_proc_state_changed) + s += "proc_state_changed "; + if (events & event_proc_thread_running) + s += "proc_thread_running "; + if (events & event_proc_thread_exiting) + s += "proc_thread_exiting "; + if (events & event_proc_stdio_available) + s += "proc_stdio_available "; + if (events & event_read_packet_available) + s += "read_packet_available "; + if (events & event_read_thread_running) + s += "read_thread_running "; + if (events & event_read_thread_running) + s += "read_thread_running "; + return s.c_str(); +} + +const char * +RNBContext::LaunchStatusAsString (std::string& s) +{ + s.clear(); + + const char *err_str = m_launch_status.AsString(); + if (err_str) + s = err_str; + else + { + char error_num_str[64]; + snprintf(error_num_str, sizeof(error_num_str), "%u", m_launch_status.Error()); + s = error_num_str; + } + return s.c_str(); +} + +bool +RNBContext::ProcessStateRunning() const +{ + nub_state_t pid_state = DNBProcessGetState(m_pid); + return pid_state == eStateRunning || pid_state == eStateStepping; +} |