diff options
Diffstat (limited to 'lldb/source/Host')
22 files changed, 868 insertions, 500 deletions
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index d296295245f..0051f902c71 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -11,6 +11,8 @@ add_host_subdirectory(common common/FileSpec.cpp common/Host.cpp common/HostInfoBase.cpp + common/HostNativeThreadBase.cpp + common/HostThread.cpp common/IOObject.cpp common/Mutex.cpp common/NativeBreakpoint.cpp @@ -25,34 +27,41 @@ add_host_subdirectory(common common/SoftwareBreakpoint.cpp common/Symbols.cpp common/Terminal.cpp + common/ThisThread.cpp + common/ThreadLauncher.cpp common/TimeValue.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Windows") add_host_subdirectory(windows + windows/Condition.cpp + windows/EditLineWin.cpp windows/FileSystem.cpp windows/Host.cpp windows/HostInfoWindows.cpp windows/HostProcessWindows.cpp - windows/ProcessRunLock.cpp + windows/HostThreadWindows.cpp windows/Mutex.cpp - windows/Condition.cpp + windows/ProcessRunLock.cpp + windows/ThisThread.cpp windows/Windows.cpp - windows/EditLineWin.cpp ) else() add_host_subdirectory(posix posix/FileSystem.cpp posix/HostInfoPosix.cpp posix/HostProcessPosix.cpp + posix/HostThreadPosix.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR}) add_host_subdirectory(macosx macosx/Host.mm - macosx/Symbols.cpp macosx/HostInfoMacOSX.mm + macosx/HostThreadMacOSX.mm + macosx/Symbols.cpp + macosx/ThisThread.cpp macosx/cfcpp/CFCBundle.cpp macosx/cfcpp/CFCData.cpp macosx/cfcpp/CFCMutableArray.cpp @@ -65,11 +74,15 @@ else() add_host_subdirectory(linux linux/Host.cpp linux/HostInfoLinux.cpp + linux/HostThreadLinux.cpp + linux/ThisThread.cpp ) elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") add_host_subdirectory(freebsd freebsd/Host.cpp freebsd/HostInfoFreeBSD.cpp + freebsd/HostThreadFreeBSD.cpp + freebsd/ThisThread.cpp ) endif() endif() diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 00c2fa37b38..ce1af3288fc 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -48,6 +48,10 @@ #include <pthread_np.h> #endif +#if defined(__linux__) +#include "Plugins/Process/Linux/ProcFileReader.h" +#endif + // C++ includes #include <limits> @@ -66,6 +70,7 @@ #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Mutex.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/lldb-private-forward.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Process.h" @@ -95,13 +100,6 @@ extern "C" using namespace lldb; using namespace lldb_private; -// Define maximum thread name length -#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__NetBSD__) -uint32_t const Host::MAX_THREAD_NAME_LENGTH = 16; -#else -uint32_t const Host::MAX_THREAD_NAME_LENGTH = std::numeric_limits<uint32_t>::max (); -#endif - #if !defined (__APPLE__) && !defined (_WIN32) struct MonitorInfo { @@ -114,16 +112,9 @@ struct MonitorInfo static thread_result_t MonitorChildProcessThreadFunction (void *arg); -lldb::thread_t -Host::StartMonitoringChildProcess -( - Host::MonitorChildProcessCallback callback, - void *callback_baton, - lldb::pid_t pid, - bool monitor_signals -) +HostThread +Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals) { - lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; MonitorInfo * info_ptr = new MonitorInfo(); info_ptr->pid = pid; @@ -132,24 +123,8 @@ Host::StartMonitoringChildProcess info_ptr->monitor_signals = monitor_signals; char thread_name[256]; - - if (Host::MAX_THREAD_NAME_LENGTH <= 16) - { - // On some platforms, the thread name is limited to 16 characters. We need to - // abbreviate there or the pid info would get truncated. - ::snprintf (thread_name, sizeof(thread_name), "wait4(%" PRIu64 ")", pid); - } - else - { - ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); - } - - thread = ThreadCreate (thread_name, - MonitorChildProcessThreadFunction, - info_ptr, - NULL); - - return thread; + ::snprintf(thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid); + return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); } //------------------------------------------------------------------ @@ -429,11 +404,6 @@ Host::WillTerminate () #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) // see macosx/Host.mm void -Host::ThreadCreated (const char *thread_name) -{ -} - -void Host::Backtrace (Stream &strm, uint32_t max_frames) { // TODO: Is there a way to backtrace the current process on other systems? @@ -448,101 +418,8 @@ Host::GetEnvironment (StringList &env) #endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__FreeBSD_kernel__) && !defined (__linux__) -struct HostThreadCreateInfo -{ - std::string thread_name; - thread_func_t thread_fptr; - thread_arg_t thread_arg; - - HostThreadCreateInfo (const char *name, thread_func_t fptr, thread_arg_t arg) : - thread_name (name ? name : ""), - thread_fptr (fptr), - thread_arg (arg) - { - } -}; - -static thread_result_t -#ifdef _WIN32 -__stdcall -#endif -ThreadCreateTrampoline (thread_arg_t arg) -{ - HostThreadCreateInfo *info = (HostThreadCreateInfo *)arg; - Host::ThreadCreated (info->thread_name.c_str()); - thread_func_t thread_fptr = info->thread_fptr; - thread_arg_t thread_arg = info->thread_arg; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("thread created"); - - delete info; - return thread_fptr (thread_arg); -} - -lldb::thread_t -Host::ThreadCreate -( - const char *thread_name, - thread_func_t thread_fptr, - thread_arg_t thread_arg, - Error *error -) -{ - lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; - - // Host::ThreadCreateTrampoline will delete this pointer for us. - HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo (thread_name, thread_fptr, thread_arg); - -#ifdef _WIN32 - thread = ::_beginthreadex(0, 0, ThreadCreateTrampoline, info_ptr, 0, NULL); - int err = thread <= 0 ? GetLastError() : 0; -#else - int err = ::pthread_create (&thread, NULL, ThreadCreateTrampoline, info_ptr); -#endif - if (err == 0) - { - if (error) - error->Clear(); - return thread; - } - - if (error) - error->SetError (err, eErrorTypePOSIX); - - return LLDB_INVALID_HOST_THREAD; -} - #ifndef _WIN32 -bool -Host::ThreadCancel (lldb::thread_t thread, Error *error) -{ - int err = ::pthread_cancel (thread); - if (error) - error->SetError(err, eErrorTypePOSIX); - return err == 0; -} - -bool -Host::ThreadDetach (lldb::thread_t thread, Error *error) -{ - int err = ::pthread_detach (thread); - if (error) - error->SetError(err, eErrorTypePOSIX); - return err == 0; -} - -bool -Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) -{ - int err = ::pthread_join (thread, thread_result_ptr); - if (error) - error->SetError(err, eErrorTypePOSIX); - return err == 0; -} - lldb::thread_key_t Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { @@ -563,99 +440,6 @@ Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) ::pthread_setspecific (key, value); } -bool -Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) -{ -#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 - lldb::pid_t curr_pid = Host::GetCurrentProcessID(); - lldb::tid_t curr_tid = Host::GetCurrentThreadID(); - if (pid == LLDB_INVALID_PROCESS_ID) - pid = curr_pid; - - if (tid == LLDB_INVALID_THREAD_ID) - tid = curr_tid; - - // Set the pthread name if possible - if (pid == curr_pid && tid == curr_tid) - { - if (::pthread_setname_np (name) == 0) - return true; - } - return false; -#elif defined (__FreeBSD__) - lldb::pid_t curr_pid = Host::GetCurrentProcessID(); - lldb::tid_t curr_tid = Host::GetCurrentThreadID(); - if (pid == LLDB_INVALID_PROCESS_ID) - pid = curr_pid; - - if (tid == LLDB_INVALID_THREAD_ID) - tid = curr_tid; - - // Set the pthread name if possible - if (pid == curr_pid && tid == curr_tid) - { - ::pthread_set_name_np (::pthread_self(), name); - return true; - } - return false; -#elif defined (__linux__) || defined (__GLIBC__) - void *fn = dlsym (RTLD_DEFAULT, "pthread_setname_np"); - if (fn) - { - lldb::pid_t curr_pid = Host::GetCurrentProcessID(); - lldb::tid_t curr_tid = Host::GetCurrentThreadID(); - if (pid == LLDB_INVALID_PROCESS_ID) - pid = curr_pid; - - if (tid == LLDB_INVALID_THREAD_ID) - tid = curr_tid; - - if (pid == curr_pid && tid == curr_tid) - { - int (*pthread_setname_np_func)(pthread_t thread, const char *name); - *reinterpret_cast<void **> (&pthread_setname_np_func) = fn; - - if (pthread_setname_np_func (::pthread_self(), name) == 0) - return true; - } - } - return false; -#else - return false; -#endif -} - -bool -Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, - const char *thread_name, size_t len) -{ - std::unique_ptr<char[]> namebuf(new char[len+1]); - - // Thread names are coming in like '<lldb.comm.debugger.edit>' and - // '<lldb.comm.debugger.editline>'. So just chopping the end of the string - // off leads to a lot of similar named threads. Go through the thread name - // and search for the last dot and use that. - const char *lastdot = ::strrchr (thread_name, '.'); - - if (lastdot && lastdot != thread_name) - thread_name = lastdot + 1; - ::strncpy (namebuf.get(), thread_name, len); - namebuf[len] = 0; - - int namebuflen = strlen(namebuf.get()); - if (namebuflen > 0) - { - if (namebuf[namebuflen - 1] == '(' || namebuf[namebuflen - 1] == '>') - { - // Trim off trailing '(' and '>' characters for a bit more cleanup. - namebuflen--; - namebuf[namebuflen] = 0; - } - return Host::SetThreadName (pid, tid, namebuf.get()); - } - return false; -} - #endif #if !defined (__APPLE__) // see Host.mm diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp index 4eb43bfaf6f..9af71ec9bcc 100644 --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -94,6 +94,12 @@ HostInfoBase::GetNumberCPUS() return g_fields->m_number_cpus; } +uint32_t +HostInfoBase::GetMaxThreadNameLength() +{ + return 0; +} + llvm::StringRef HostInfoBase::GetVendorString() { diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp new file mode 100644 index 00000000000..7a2bd6d217f --- /dev/null +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -0,0 +1,92 @@ +//===-- HostNativeThreadBase.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Log.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/HostNativeThreadBase.h" +#include "lldb/Host/ThisThread.h" +#include "lldb/Host/ThreadLauncher.h" +#include "llvm/ADT/StringExtras.h" + +using namespace lldb; +using namespace lldb_private; + +HostNativeThreadBase::HostNativeThreadBase() + : m_thread(LLDB_INVALID_HOST_THREAD) + , m_state(eThreadStateInvalid) + , m_result(0) +{ +} + +HostNativeThreadBase::HostNativeThreadBase(thread_t thread) + : m_thread(thread) + , m_state((thread == LLDB_INVALID_HOST_THREAD) ? eThreadStateInvalid : eThreadStateRunning) + , m_result(0) +{ +} + +void +HostNativeThreadBase::SetState(ThreadState state) +{ + m_state = state; +} + +ThreadState +HostNativeThreadBase::GetState() const +{ + return m_state; +} + +lldb::thread_t +HostNativeThreadBase::GetSystemHandle() const +{ + return m_thread; +} + +lldb::thread_result_t +HostNativeThreadBase::GetResult() const +{ + return m_result; +} + +void +HostNativeThreadBase::Reset() +{ + m_thread = LLDB_INVALID_HOST_THREAD; + m_state = eThreadStateInvalid; + m_result = 0; +} + +lldb::thread_t +HostNativeThreadBase::Release() +{ + lldb::thread_t result = m_thread; + m_thread = LLDB_INVALID_HOST_THREAD; + m_state = eThreadStateInvalid; + m_result = 0; + + return result; +} + +lldb::thread_result_t +HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) +{ + ThreadLauncher::HostThreadCreateInfo *info = (ThreadLauncher::HostThreadCreateInfo *)arg; + ThisThread::SetName(info->thread_name.c_str(), HostInfo::GetMaxThreadNameLength()); + + thread_func_t thread_fptr = info->thread_fptr; + thread_arg_t thread_arg = info->thread_arg; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + if (log) + log->Printf("thread created"); + + delete info; + return thread_fptr(thread_arg); +} diff --git a/lldb/source/Host/common/HostThread.cpp b/lldb/source/Host/common/HostThread.cpp new file mode 100644 index 00000000000..82eacc9473a --- /dev/null +++ b/lldb/source/Host/common/HostThread.cpp @@ -0,0 +1,84 @@ +//===-- HostThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostThread.h" + +using namespace lldb; +using namespace lldb_private; + +HostThread::HostThread() + : m_native_thread(new HostNativeThread) +{ +} + +HostThread::HostThread(lldb::thread_t thread) + : m_native_thread(new HostNativeThread(thread)) +{ +} + +Error +HostThread::Join(lldb::thread_result_t *result) +{ + return m_native_thread->Join(result); +} + +Error +HostThread::Cancel() +{ + return m_native_thread->Cancel(); +} + +void +HostThread::Reset() +{ + return m_native_thread->Reset(); +} + +lldb::thread_t +HostThread::Release() +{ + return m_native_thread->Release(); +} + +void +HostThread::SetState(ThreadState state) +{ + m_native_thread->SetState(state); +} + +ThreadState +HostThread::GetState() const +{ + return m_native_thread->GetState(); +} + +HostNativeThreadBase & +HostThread::GetNativeThread() +{ + return *m_native_thread; +} + +const HostNativeThreadBase & +HostThread::GetNativeThread() const +{ + return *m_native_thread; +} + +lldb::thread_result_t +HostThread::GetResult() const +{ + return m_native_thread->GetResult(); +} + +bool +HostThread::EqualsThread(lldb::thread_t thread) const +{ + return m_native_thread->GetSystemHandle() == thread; +} diff --git a/lldb/source/Host/common/ThisThread.cpp b/lldb/source/Host/common/ThisThread.cpp new file mode 100644 index 00000000000..5802781f50b --- /dev/null +++ b/lldb/source/Host/common/ThisThread.cpp @@ -0,0 +1,52 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/STLExtras.h" + +#include <algorithm> + +using namespace lldb; +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name, int max_length) +{ + std::string truncated_name(name.data()); + + // Thread names are coming in like '<lldb.comm.debugger.edit>' and + // '<lldb.comm.debugger.editline>'. So just chopping the end of the string + // off leads to a lot of similar named threads. Go through the thread name + // and search for the last dot and use that. + + if (max_length > 0 && truncated_name.length() > max_length) + { + // First see if we can get lucky by removing any initial or final braces. + std::string::size_type begin = truncated_name.find_first_not_of("(<"); + std::string::size_type end = truncated_name.find_last_not_of(")>."); + if (end - begin > max_length) + { + // We're still too long. Since this is a dotted component, use everything after the last + // dot, up to a maximum of |length| characters. + std::string::size_type last_dot = truncated_name.find_last_of("."); + if (last_dot != std::string::npos) + begin = last_dot + 1; + + end = std::min(end, begin + max_length); + } + + std::string::size_type count = end - begin + 1; + truncated_name = truncated_name.substr(begin, count); + } + + SetName(truncated_name.c_str()); +} diff --git a/lldb/source/Host/common/ThreadLauncher.cpp b/lldb/source/Host/common/ThreadLauncher.cpp new file mode 100644 index 00000000000..350d4491b6c --- /dev/null +++ b/lldb/source/Host/common/ThreadLauncher.cpp @@ -0,0 +1,48 @@ +//===-- ThreadLauncher.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// lldb Includes +#include "lldb/Core/Log.h" +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/ThisThread.h" +#include "lldb/Host/ThreadLauncher.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/windows.h" +#endif + +using namespace lldb; +using namespace lldb_private; + +HostThread +ThreadLauncher::LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function, lldb::thread_arg_t thread_arg, Error *error_ptr) +{ + Error error; + if (error_ptr) + error_ptr->Clear(); + + // Host::ThreadCreateTrampoline will delete this pointer for us. + HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo(name.data(), thread_function, thread_arg); + lldb::thread_t thread; +#ifdef _WIN32 + thread = (lldb::thread_t)::_beginthreadex(0, 0, HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL); + if (thread == (lldb::thread_t)(-1L)) + error.SetError(::GetLastError(), eErrorTypeWin32); +#else + int err = ::pthread_create(&thread, NULL, HostNativeThread::ThreadCreateTrampoline, info_ptr); + error.SetError(err, eErrorTypePOSIX); +#endif + if (error_ptr) + *error_ptr = error; + if (!error.Success()) + thread = LLDB_INVALID_HOST_THREAD; + + return HostThread(thread); +} diff --git a/lldb/source/Host/freebsd/Host.cpp b/lldb/source/Host/freebsd/Host.cpp index dc092e86d78..5f065e2810f 100644 --- a/lldb/source/Host/freebsd/Host.cpp +++ b/lldb/source/Host/freebsd/Host.cpp @@ -50,80 +50,6 @@ extern "C" { using namespace lldb; using namespace lldb_private; -class FreeBSDThread -{ -public: - FreeBSDThread(const char *thread_name) - { - Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); - } - static void PThreadDestructor (void *v) - { - delete (FreeBSDThread*)v; - } -}; - -static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; -static pthread_key_t g_thread_create_key = 0; - -static void -InitThreadCreated() -{ - ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor); -} - -void -Host::ThreadCreated (const char *thread_name) -{ - ::pthread_once (&g_thread_create_once, InitThreadCreated); - if (g_thread_create_key) - { - ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name)); - } - - Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); -} - -std::string -Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) -{ - struct kinfo_proc *kp = nullptr, *nkp; - size_t len = 0; - int error; - int name[4] = { - CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)pid - }; - - while (1) { - error = sysctl(name, 4, kp, &len, nullptr, 0); - if (kp == nullptr || (error != 0 && errno == ENOMEM)) { - // Add extra space in case threads are added before next call. - len += sizeof(*kp) + len / 10; - nkp = (struct kinfo_proc *)realloc(kp, len); - if (nkp == nullptr) - { - free(kp); - return std::string(); - } - kp = nkp; - continue; - } - if (error != 0) - len = 0; - break; - } - - std::string thread_name; - for (size_t i = 0; i < len / sizeof(*kp); i++) { - if (kp[i].ki_tid == (int)tid) { - thread_name = kp[i].ki_tdname; - break; - } - } - free(kp); - return thread_name; -} - void Host::Backtrace (Stream &strm, uint32_t max_frames) { diff --git a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp index 78458259f0a..d51109320c3 100644 --- a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp +++ b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -17,6 +17,12 @@ using namespace lldb_private; +uint32_t +HostInfoFreeBSD::GetMaxThreadNameLength() +{ + return 16; +} + bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) { diff --git a/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp b/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp new file mode 100644 index 00000000000..ce2d44e24ad --- /dev/null +++ b/lldb/source/Host/freebsd/HostThreadFreeBSD.cpp @@ -0,0 +1,80 @@ +//===-- HostThreadFreeBSD.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// lldb Includes +#include "lldb/Host/freebsd/HostThreadFreeBSD.h" + +// C includes +#include <pthread.h> +#include <pthread_np.h> +#include <stdlib.h> +#include <sys/sysctl.h> + +// C++ includes +#include <string> + +using namespace lldb_private; + +HostThreadFreeBSD::HostThreadFreeBSD() +{ +} + +HostThreadFreeBSD::HostThreadFreeBSD(lldb::thread_t thread) + : HostThreadPosix(thread) +{ +} + +void +HostThreadFreeBSD::SetName(lldb::thread_t thread, llvm::StringRef name) +{ + ::pthread_set_name_np(thread, name); +} + +void +HostThreadFreeBSD::GetName(lldb::thread_t thread, llvm::SmallVectorImpl<char> &name) +{ + name.clear(); + int pid = Host::GetCurrentProcessID(); + + struct kinfo_proc *kp = nullptr, *nkp; + size_t len = 0; + int error; + int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)pid}; + + while (1) + { + error = sysctl(ctl, 4, kp, &len, nullptr, 0); + if (kp == nullptr || (error != 0 && errno == ENOMEM)) + { + // Add extra space in case threads are added before next call. + len += sizeof(*kp) + len / 10; + nkp = (struct kinfo_proc *)realloc(kp, len); + if (nkp == nullptr) + { + free(kp); + return; + } + kp = nkp; + continue; + } + if (error != 0) + len = 0; + break; + } + + for (size_t i = 0; i < len / sizeof(*kp); i++) + { + if (kp[i].ki_tid == (int)thread) + { + name.append(kp[i].ki_tdname, strlen(kp[i].ki_tdname)); + break; + } + } + free(kp); +} diff --git a/lldb/source/Host/freebsd/ThisThread.cpp b/lldb/source/Host/freebsd/ThisThread.cpp new file mode 100644 index 00000000000..6a506187aaf --- /dev/null +++ b/lldb/source/Host/freebsd/ThisThread.cpp @@ -0,0 +1,29 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/linux/HostThreadLinux.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/SmallVector.h" + +#include <pthread.h> + +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name) +{ + HostThread::SetName(::pthread_self(), name); +} + +void +ThisThread::GetName(llvm::SmallVectorImpl<char> &name) +{ + HostThread::GetName(::pthread_self(), name); +} diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp index 0bad90ee22e..3d90fbb16c5 100644 --- a/lldb/source/Host/linux/Host.cpp +++ b/lldb/source/Host/linux/Host.cpp @@ -373,31 +373,6 @@ Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) } void -Host::ThreadCreated (const char *thread_name) -{ - if (!Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name)) - { - Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); - } -} - -std::string -Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) -{ - assert(pid != LLDB_INVALID_PROCESS_ID); - assert(tid != LLDB_INVALID_THREAD_ID); - - // Read /proc/$TID/comm file. - lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (tid, "comm"); - const char *comm_str = (const char *)buf_sp->GetBytes(); - const char *cr_str = ::strchr(comm_str, '\n'); - size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str); - - std::string thread_name(comm_str, length); - return thread_name; -} - -void Host::Backtrace (Stream &strm, uint32_t max_frames) { if (max_frames > 0) diff --git a/lldb/source/Host/linux/HostInfoLinux.cpp b/lldb/source/Host/linux/HostInfoLinux.cpp index 6d55c503a0f..c18975ca160 100644 --- a/lldb/source/Host/linux/HostInfoLinux.cpp +++ b/lldb/source/Host/linux/HostInfoLinux.cpp @@ -47,6 +47,12 @@ HostInfoLinux::Initialize() g_fields = new HostInfoLinuxFields(); } +uint32_t +HostInfoLinux::GetMaxThreadNameLength() +{ + return 16; +} + bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) { diff --git a/lldb/source/Host/linux/HostThreadLinux.cpp b/lldb/source/Host/linux/HostThreadLinux.cpp new file mode 100644 index 00000000000..619bd245ab2 --- /dev/null +++ b/lldb/source/Host/linux/HostThreadLinux.cpp @@ -0,0 +1,47 @@ +//===-- HostThreadLinux.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/DataBuffer.h" +#include "lldb/Host/linux/HostThreadLinux.h" +#include "Plugins/Process/Linux/ProcFileReader.h" + +#include "llvm/ADT/SmallVector.h" + +#include <pthread.h> + +using namespace lldb_private; + +HostThreadLinux::HostThreadLinux() + : HostThreadPosix() +{ +} + +HostThreadLinux::HostThreadLinux(lldb::thread_t thread) + : HostThreadPosix(thread) +{ +} + +void +HostThreadLinux::SetName(lldb::thread_t thread, llvm::StringRef name) +{ + ::pthread_setname_np(thread, name.data()); +} + +void +HostThreadLinux::GetName(lldb::thread_t thread, llvm::SmallVectorImpl<char> &name) +{ + // Read /proc/$TID/comm file. + lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer(thread, "comm"); + const char *comm_str = (const char *)buf_sp->GetBytes(); + const char *cr_str = ::strchr(comm_str, '\n'); + size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str); + + name.clear(); + name.append(comm_str, comm_str + length); +} diff --git a/lldb/source/Host/linux/ThisThread.cpp b/lldb/source/Host/linux/ThisThread.cpp new file mode 100644 index 00000000000..1c68c8ba16d --- /dev/null +++ b/lldb/source/Host/linux/ThisThread.cpp @@ -0,0 +1,29 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/SmallVector.h" + +#include <pthread.h> + +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name) +{ + HostNativeThread::SetName(::pthread_self(), name); +} + +void +ThisThread::GetName(llvm::SmallVectorImpl<char> &name) +{ + HostNativeThread::GetName(::pthread_self(), name); +} diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index efc95c70bbb..37ff095817d 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -47,7 +47,9 @@ #include "lldb/Core/StreamString.h" #include "lldb/Host/Endian.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Utility/CleanUp.h" @@ -77,107 +79,6 @@ extern "C" using namespace lldb; using namespace lldb_private; -static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; -static pthread_key_t g_thread_create_key = 0; - -class MacOSXDarwinThread -{ -public: - MacOSXDarwinThread(const char *thread_name) : - m_pool (nil) - { - // Register our thread with the collector if garbage collection is enabled. - if (objc_collectingEnabled()) - { -#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 - // On Leopard and earlier there is no way objc_registerThreadWithCollector - // function, so we do it manually. - auto_zone_register_thread(auto_zone()); -#else - // On SnowLeopard and later we just call the thread registration function. - objc_registerThreadWithCollector(); -#endif - } - else - { - m_pool = [[NSAutoreleasePool alloc] init]; - } - - - Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); - } - - ~MacOSXDarwinThread() - { - if (m_pool) - { - [m_pool drain]; - m_pool = nil; - } - } - - static void PThreadDestructor (void *v) - { - if (v) - delete static_cast<MacOSXDarwinThread*>(v); - ::pthread_setspecific (g_thread_create_key, NULL); - } - -protected: - NSAutoreleasePool * m_pool; -private: - DISALLOW_COPY_AND_ASSIGN (MacOSXDarwinThread); -}; - -static void -InitThreadCreated() -{ - ::pthread_key_create (&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor); -} - -void -Host::ThreadCreated (const char *thread_name) -{ - ::pthread_once (&g_thread_create_once, InitThreadCreated); - if (g_thread_create_key) - { - ::pthread_setspecific (g_thread_create_key, new MacOSXDarwinThread(thread_name)); - } -} - -std::string -Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) -{ - std::string thread_name; -#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 - // We currently can only get the name of a thread in the current process. - if (pid == Host::GetCurrentProcessID()) - { - char pthread_name[1024]; - if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0) - { - if (pthread_name[0]) - { - thread_name = pthread_name; - } - } - else - { - dispatch_queue_t current_queue = ::dispatch_get_current_queue (); - if (current_queue != NULL) - { - const char *queue_name = dispatch_queue_get_label (current_queue); - if (queue_name && queue_name[0]) - { - thread_name = queue_name; - } - } - } - } -#endif - return thread_name; -} - bool Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory) { @@ -642,28 +543,23 @@ LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &lau // in a shell and the shell will fork/exec a couple of times before we get // to the process that we wanted to launch. So when our process actually // gets launched, we will handshake with it and get the process ID for it. - lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name, - AcceptPIDFromInferior, - connect_url, - &lldb_error); - + HostThread accept_thread = ThreadLauncher::LaunchThread(unix_socket_name, AcceptPIDFromInferior, connect_url, &lldb_error); [applescript executeAndReturnError:nil]; thread_result_t accept_thread_result = NULL; - if (Host::ThreadJoin (accept_thread, &accept_thread_result, &lldb_error)) + lldb_error = accept_thread.Join(&accept_thread_result); + if (lldb_error.Success() && accept_thread_result) { - if (accept_thread_result) - { - pid = (intptr_t)accept_thread_result; - - // Wait for process to be stopped at the entry point by watching - // for the process status to be set to SSTOP which indicates it it - // SIGSTOP'ed at the entry point - WaitForProcessToSIGSTOP (pid, 5); - } + pid = (intptr_t)accept_thread_result; + + // Wait for process to be stopped at the entry point by watching + // for the process status to be set to SSTOP which indicates it it + // SIGSTOP'ed at the entry point + WaitForProcessToSIGSTOP(pid, 5); } - ::unlink (unix_socket_name); + + FileSystem::Unlink(unix_socket_name); [applescript release]; if (pid != LLDB_INVALID_PROCESS_ID) launch_info.SetProcessID (pid); @@ -1492,13 +1388,9 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info) return error; } -lldb::thread_t -Host::StartMonitoringChildProcess (Host::MonitorChildProcessCallback callback, - void *callback_baton, - lldb::pid_t pid, - bool monitor_signals) +HostThread +Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals) { - lldb::thread_t thread = LLDB_INVALID_HOST_THREAD; unsigned long mask = DISPATCH_PROC_EXIT; if (monitor_signals) mask |= DISPATCH_PROC_SIGNAL; @@ -1584,7 +1476,7 @@ Host::StartMonitoringChildProcess (Host::MonitorChildProcessCallback callback, ::dispatch_resume (source); } - return thread; + return HostThread(); } //---------------------------------------------------------------------- diff --git a/lldb/source/Host/macosx/HostThreadMacOSX.mm b/lldb/source/Host/macosx/HostThreadMacOSX.mm new file mode 100644 index 00000000000..c84a78efd9e --- /dev/null +++ b/lldb/source/Host/macosx/HostThreadMacOSX.mm @@ -0,0 +1,102 @@ +//===-- HostThreadMacOSX.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/macosx/HostThreadMacOSX.h" +#include "lldb/Host/Host.h" + +#include <CoreFoundation/CoreFoundation.h> +#include <Foundation/Foundation.h> + +#include <objc/objc-auto.h> +#include <pthread.h> + +using namespace lldb_private; + +namespace +{ + +pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; +pthread_key_t g_thread_create_key = 0; + +class MacOSXDarwinThread +{ + public: + MacOSXDarwinThread() + : m_pool(nil) + { + // Register our thread with the collector if garbage collection is enabled. + if (objc_collectingEnabled()) + { +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 + // On Leopard and earlier there is no way objc_registerThreadWithCollector + // function, so we do it manually. + auto_zone_register_thread(auto_zone()); +#else + // On SnowLeopard and later we just call the thread registration function. + objc_registerThreadWithCollector(); +#endif + } + else + { + m_pool = [[NSAutoreleasePool alloc] init]; + } + } + + ~MacOSXDarwinThread() + { + if (m_pool) + { + [m_pool drain]; + m_pool = nil; + } + } + + static void + PThreadDestructor(void *v) + { + if (v) + delete static_cast<MacOSXDarwinThread *>(v); + ::pthread_setspecific(g_thread_create_key, NULL); + } + + protected: + NSAutoreleasePool *m_pool; + + private: + DISALLOW_COPY_AND_ASSIGN(MacOSXDarwinThread); +}; + +void +InitThreadCreated() +{ + ::pthread_key_create(&g_thread_create_key, MacOSXDarwinThread::PThreadDestructor); +} +} // namespace + +HostThreadMacOSX::HostThreadMacOSX() + : HostThreadPosix() +{ +} + +HostThreadMacOSX::HostThreadMacOSX(lldb::thread_t thread) + : HostThreadPosix(thread) +{ +} + +lldb::thread_result_t +HostThreadMacOSX::ThreadCreateTrampoline(lldb::thread_arg_t arg) +{ + ::pthread_once(&g_thread_create_once, InitThreadCreated); + if (g_thread_create_key) + { + ::pthread_setspecific(g_thread_create_key, new MacOSXDarwinThread()); + } + + return HostThreadPosix::ThreadCreateTrampoline(arg); +} diff --git a/lldb/source/Host/macosx/ThisThread.cpp b/lldb/source/Host/macosx/ThisThread.cpp new file mode 100644 index 00000000000..95c7f2bf1e3 --- /dev/null +++ b/lldb/source/Host/macosx/ThisThread.cpp @@ -0,0 +1,39 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ThisThread.h" + +#include <pthread.h> + +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + ::pthread_setname_np(name); +#endif +} + +void +ThisThread::GetName(llvm::SmallVectorImpl<char> &name) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + char pthread_name[1024]; + dispatch_queue_t current_queue = ::dispatch_get_current_queue(); + if (current_queue != NULL) + { + const char *queue_name = dispatch_queue_get_label(current_queue); + if (queue_name && queue_name[0]) + { + name = queue_name; + } + } +#endif +} diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp new file mode 100644 index 00000000000..4e62ad5abce --- /dev/null +++ b/lldb/source/Host/posix/HostThreadPosix.cpp @@ -0,0 +1,63 @@ +//===-- HostThreadPosix.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" +#include "lldb/Host/posix/HostThreadPosix.h" + +#include <pthread.h> + +using namespace lldb_private; + +HostThreadPosix::HostThreadPosix() +{ +} + +HostThreadPosix::HostThreadPosix(lldb::thread_t thread) + : HostNativeThreadBase(thread) +{ +} + +HostThreadPosix::~HostThreadPosix() +{ +} + +Error +HostThreadPosix::Join(lldb::thread_result_t *result) +{ + Error error; + lldb::thread_result_t thread_result; + int err = ::pthread_join(m_thread, &thread_result); + error.SetError(err, lldb::eErrorTypePOSIX); + if (err == 0) + { + m_state = (m_state == eThreadStateCancelling) ? eThreadStateCancelled : eThreadStateExited; + } + return error; +} + +Error +HostThreadPosix::Cancel() +{ + Error error; + int err = ::pthread_cancel(m_thread); + error.SetError(err, lldb::eErrorTypePOSIX); + if (err == 0) + m_state = eThreadStateCancelling; + + return error; +} + +Error +HostThreadPosix::Detach() +{ + Error error; + int err = ::pthread_detach(m_thread); + error.SetError(err, lldb::eErrorTypePOSIX); + return error; +} diff --git a/lldb/source/Host/windows/Host.cpp b/lldb/source/Host/windows/Host.cpp index bc0f48b49c7..4542025f6ee 100644 --- a/lldb/source/Host/windows/Host.cpp +++ b/lldb/source/Host/windows/Host.cpp @@ -110,12 +110,6 @@ Host::GetAuxvData(lldb_private::Process *process) return 0; } -std::string -Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) -{ - return std::string(); -} - lldb::tid_t Host::GetCurrentThreadID() { @@ -128,26 +122,6 @@ Host::GetCurrentThread () return lldb::thread_t(::GetCurrentThread()); } -bool -Host::ThreadCancel (lldb::thread_t thread, Error *error) -{ - int err = ::TerminateThread((HANDLE)thread, 0); - return err == 0; -} - -bool -Host::ThreadDetach (lldb::thread_t thread, Error *error) -{ - return ThreadCancel(thread, error); -} - -bool -Host::ThreadJoin (lldb::thread_t thread, thread_result_t *thread_result_ptr, Error *error) -{ - WaitForSingleObject((HANDLE) thread, INFINITE); - return true; -} - lldb::thread_key_t Host::ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback) { @@ -166,19 +140,6 @@ Host::ThreadLocalStorageSet(lldb::thread_key_t key, void *value) ::TlsSetValue (key, value); } -bool -Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name) -{ - return false; -} - -bool -Host::SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, - const char *thread_name, size_t len) -{ - return false; -} - void Host::Kill(lldb::pid_t pid, int signo) { @@ -260,14 +221,8 @@ Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) return true; } -lldb::thread_t -Host::StartMonitoringChildProcess -( - Host::MonitorChildProcessCallback callback, - void *callback_baton, - lldb::pid_t pid, - bool monitor_signals -) +HostThread +Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, void *callback_baton, lldb::pid_t pid, bool monitor_signals) { - return LLDB_INVALID_HOST_THREAD; + return HostThread(); }
\ No newline at end of file diff --git a/lldb/source/Host/windows/HostThreadWindows.cpp b/lldb/source/Host/windows/HostThreadWindows.cpp new file mode 100644 index 00000000000..5d526cc2530 --- /dev/null +++ b/lldb/source/Host/windows/HostThreadWindows.cpp @@ -0,0 +1,80 @@ +//===-- HostThreadWindows.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" + +#include "lldb/Host/windows/windows.h" +#include "lldb/Host/windows/HostThreadWindows.h" + +#include "llvm/ADT/STLExtras.h" + +using namespace lldb; +using namespace lldb_private; + +HostThreadWindows::HostThreadWindows() + : HostNativeThreadBase() +{ +} + +HostThreadWindows::HostThreadWindows(lldb::thread_t thread) + : HostNativeThreadBase(thread) +{ +} + +HostThreadWindows::~HostThreadWindows() +{ + Reset(); +} + +Error +HostThreadWindows::Join(lldb::thread_result_t *result) +{ + Error error; + if (WAIT_OBJECT_0 != ::WaitForSingleObject(m_thread, INFINITE)) + { + error.SetError(::GetLastError(), lldb::eErrorTypeWin32); + return error; + } + + m_state = (m_state == eThreadStateCancelling) ? eThreadStateCancelled : eThreadStateExited; + + if (result) + { + DWORD dword_result = 0; + if (!::GetExitCodeThread(m_thread, &dword_result)) + *result = 0; + *result = dword_result; + } + return error; +} + +Error +HostThreadWindows::Cancel() +{ + Error error; + + DWORD result = ::QueueUserAPC(::ExitThread, m_thread, 0); + error.SetError(result, eErrorTypeWin32); + return error; +} + +lldb::tid_t +HostThreadWindows::GetThreadId() const +{ + return ::GetThreadId(m_thread); +} + +void +HostThreadWindows::Reset() +{ + if (m_thread != LLDB_INVALID_HOST_THREAD) + ::CloseHandle(m_thread); + + HostNativeThreadBase::Reset(); +} diff --git a/lldb/source/Host/windows/ThisThread.cpp b/lldb/source/Host/windows/ThisThread.cpp new file mode 100644 index 00000000000..9c37d7c57e7 --- /dev/null +++ b/lldb/source/Host/windows/ThisThread.cpp @@ -0,0 +1,60 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Error.h" + +#include "lldb/Host/windows/windows.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" + +using namespace lldb; +using namespace lldb_private; + +namespace +{ +static const DWORD MS_VC_EXCEPTION = 0x406D1388; + +#pragma pack(push, 8) +struct THREADNAME_INFO +{ + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to thread name + DWORD dwThreadId; // Thread ID (-1 == current thread) + DWORD dwFlags; // Reserved. Do not use. +}; +#pragma pack(pop) +} + +void +ThisThread::SetName(llvm::StringRef name) +{ +// Other compilers don't yet support SEH, so we can only set the thread if compiling with MSVC. +// TODO(zturner): Once clang-cl supports SEH, relax this conditional. +#if defined(_MSC_VER) + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name.data(); + info.dwThreadId = ::GetCurrentThreadId(); + info.dwFlags = 0; + + __try { ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); } + __except(EXCEPTION_EXECUTE_HANDLER) {} +#endif +} + +void +ThisThread::GetName(llvm::SmallVectorImpl<char> &name) +{ + // Getting the thread name is not supported on Windows. + // TODO(zturner): In SetName(), make a TLS entry that contains the thread's name, and in this function + // try to extract that TLS entry. + name.clear(); +} |