From c89021d16202600e8822dfed25c18c07dfed43c8 Mon Sep 17 00:00:00 2001 From: "sgjesse@chromium.org" Date: Tue, 4 Jan 2011 09:09:50 +0000 Subject: [PATCH] Added labelled thread names to help with some debugging activity. Right now, the only platform that it works on is linux (using the prctl API to set the names of the threads). Other platforms are setup to build properly if the flag is set, but their thread names are not currently set. Patch by Mark Lam from Hewlett-Packard Development Company, LP Review URL: http://codereview.chromium.org/6070009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6141 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/cpu-profiler.cc | 3 ++- src/d8-debug.h | 6 ++++-- src/d8.cc | 3 ++- src/debug-agent.h | 6 ++++-- src/debug.cc | 3 ++- src/log.cc | 3 ++- src/platform-freebsd.cc | 12 ++++++++++++ src/platform-linux.cc | 14 ++++++++++++++ src/platform-macos.cc | 32 ++++++++++++++++++++++++++++++++ src/platform-nullos.cc | 13 +++++++++++++ src/platform-openbsd.cc | 12 ++++++++++++ src/platform-solaris.cc | 12 ++++++++++++ src/platform-win32.cc | 13 +++++++++++++ src/platform.h | 13 +++++++++++++ src/top.cc | 4 +++- src/v8threads.cc | 3 ++- 16 files changed, 142 insertions(+), 10 deletions(-) diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc index f13c0eefa..fcf539f3b 100644 --- a/src/cpu-profiler.cc +++ b/src/cpu-profiler.cc @@ -47,7 +47,8 @@ static const int kTickSamplesBufferChunksCount = 16; ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator) - : generator_(generator), + : Thread("v8:ProfEvntProc"), + generator_(generator), running_(true), ticks_buffer_(sizeof(TickSampleEventRecord), kTickSamplesBufferChunkSize, diff --git a/src/d8-debug.h b/src/d8-debug.h index c7acc2f79..4e33e6f4c 100644 --- a/src/d8-debug.h +++ b/src/d8-debug.h @@ -98,7 +98,8 @@ class RemoteDebugger { class ReceiverThread: public i::Thread { public: explicit ReceiverThread(RemoteDebugger* remote_debugger) - : remote_debugger_(remote_debugger) {} + : Thread("d8:ReceiverThrd"), + remote_debugger_(remote_debugger) {} ~ReceiverThread() {} void Run(); @@ -112,7 +113,8 @@ class ReceiverThread: public i::Thread { class KeyboardThread: public i::Thread { public: explicit KeyboardThread(RemoteDebugger* remote_debugger) - : remote_debugger_(remote_debugger) {} + : Thread("d8:KeyboardThrd"), + remote_debugger_(remote_debugger) {} ~KeyboardThread() {} void Run(); diff --git a/src/d8.cc b/src/d8.cc index 5a1e63a76..f0da7ac8b 100644 --- a/src/d8.cc +++ b/src/d8.cc @@ -599,7 +599,8 @@ void Shell::RunShell() { class ShellThread : public i::Thread { public: ShellThread(int no, i::Vector files) - : no_(no), files_(files) { } + : Thread("d8:ShellThread"), + no_(no), files_(files) { } virtual void Run(); private: int no_; diff --git a/src/debug-agent.h b/src/debug-agent.h index 364799436..4cedb8318 100644 --- a/src/debug-agent.h +++ b/src/debug-agent.h @@ -44,7 +44,8 @@ class DebuggerAgentSession; class DebuggerAgent: public Thread { public: explicit DebuggerAgent(const char* name, int port) - : name_(StrDup(name)), port_(port), + : Thread(name), + name_(StrDup(name)), port_(port), server_(OS::CreateSocket()), terminate_(false), session_access_(OS::CreateMutex()), session_(NULL), terminate_now_(OS::CreateSemaphore(0)), @@ -90,7 +91,8 @@ class DebuggerAgent: public Thread { class DebuggerAgentSession: public Thread { public: DebuggerAgentSession(DebuggerAgent* agent, Socket* client) - : agent_(agent), client_(client) {} + : Thread("v8:DbgAgntSessn"), + agent_(agent), client_(client) {} void DebuggerMessage(Vector message); void Shutdown(); diff --git a/src/debug.cc b/src/debug.cc index ca3c1db79..c41e545c8 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -3037,7 +3037,8 @@ void LockingCommandMessageQueue::Clear() { MessageDispatchHelperThread::MessageDispatchHelperThread() - : sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()), + : Thread("v8:MsgDispHelpr"), + sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()), already_signalled_(false) { } diff --git a/src/log.cc b/src/log.cc index db9ff7a1f..6eb3c9b0b 100644 --- a/src/log.cc +++ b/src/log.cc @@ -276,7 +276,8 @@ void SlidingStateWindow::AddState(StateTag state) { // Profiler implementation. // Profiler::Profiler() - : head_(0), + : Thread("v8:Profiler"), + head_(0), tail_(0), overflow_(false), buffer_semaphore_(OS::CreateSemaphore(0)), diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc index b58d0662f..ad1e499ac 100644 --- a/src/platform-freebsd.cc +++ b/src/platform-freebsd.cc @@ -411,6 +411,12 @@ bool ThreadHandle::IsValid() const { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { + set_name("v8:"); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + set_names(name); } @@ -430,6 +436,12 @@ static void* ThreadEntry(void* arg) { } +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + void Thread::Start() { pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); ASSERT(IsValid()); diff --git a/src/platform-linux.cc b/src/platform-linux.cc index 7efb25de9..755e8cdaf 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -551,6 +552,12 @@ bool ThreadHandle::IsValid() const { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { + set_name("v8:"); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + set_name(name); } @@ -563,6 +570,7 @@ static void* ThreadEntry(void* arg) { // This is also initialized by the first argument to pthread_create() but we // don't know which thread will run first (the original thread or the new // one) so we initialize it here too. + prctl(PR_SET_NAME, thread->name(), 0, 0, 0); thread->thread_handle_data()->thread_ = pthread_self(); ASSERT(thread->IsValid()); thread->Run(); @@ -570,6 +578,12 @@ static void* ThreadEntry(void* arg) { } +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + void Thread::Start() { pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); ASSERT(IsValid()); diff --git a/src/platform-macos.cc b/src/platform-macos.cc index 85c708824..21e464a80 100644 --- a/src/platform-macos.cc +++ b/src/platform-macos.cc @@ -28,6 +28,8 @@ // Platform specific code for MacOS goes here. For the POSIX comaptible parts // the implementation is in platform-posix.cc. +#include +#include #include #include #include @@ -411,6 +413,12 @@ bool ThreadHandle::IsValid() const { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { + set_name("v8:"); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + set_name(name); } @@ -418,18 +426,42 @@ Thread::~Thread() { } + +static void SetThreadName(const char* name) { + // pthread_setname_np is only available in 10.6 or later, so test + // for it at runtime. + int (*dynamic_pthread_setname_np)(const char*); + *reinterpret_cast(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + if (!dynamic_pthread_setname_np) + return; + + // Mac OS X does not expose the length limit of the name, so hardcode it. + const int kMaxNameLength = 63; + std::string shortened_name = std::string(name).substr(0, kMaxNameLength); + dynamic_pthread_setname_np(shortened_name.c_str()); +} + + static void* ThreadEntry(void* arg) { Thread* thread = reinterpret_cast(arg); // This is also initialized by the first argument to pthread_create() but we // don't know which thread will run first (the original thread or the new // one) so we initialize it here too. thread->thread_handle_data()->thread_ = pthread_self(); + SetThreadName(thread->name()); ASSERT(thread->IsValid()); thread->Run(); return NULL; } +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + void Thread::Start() { pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); } diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc index 72ea0e576..f1b769598 100644 --- a/src/platform-nullos.cc +++ b/src/platform-nullos.cc @@ -335,6 +335,13 @@ bool ThreadHandle::IsValid() const { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { + set_name("v8:"); + UNIMPLEMENTED(); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + set_name(name); UNIMPLEMENTED(); } @@ -344,6 +351,12 @@ Thread::~Thread() { } +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + void Thread::Start() { UNIMPLEMENTED(); } diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc index b698d16b9..5de608190 100644 --- a/src/platform-openbsd.cc +++ b/src/platform-openbsd.cc @@ -387,6 +387,12 @@ bool ThreadHandle::IsValid() const { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { + set_name("v8:"); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + set_name(name); } @@ -406,6 +412,12 @@ static void* ThreadEntry(void* arg) { } +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + void Thread::Start() { pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); ASSERT(IsValid()); diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc index f84e80d1f..04c25a902 100644 --- a/src/platform-solaris.cc +++ b/src/platform-solaris.cc @@ -401,6 +401,12 @@ bool ThreadHandle::IsValid() const { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { + set_name("v8:"); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + set_name(name); } @@ -420,6 +426,12 @@ static void* ThreadEntry(void* arg) { } +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + void Thread::Start() { pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); ASSERT(IsValid()); diff --git a/src/platform-win32.cc b/src/platform-win32.cc index 4438045ea..af2438e11 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -1463,6 +1463,19 @@ class Thread::PlatformData : public Malloced { Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { data_ = new PlatformData(kNoThread); + set_name("v8:"); +} + + +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { + data_ = new PlatformData(kNoThread); + set_name(name); +} + + +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; } diff --git a/src/platform.h b/src/platform.h index 5a3e4a3fb..faf1aee91 100644 --- a/src/platform.h +++ b/src/platform.h @@ -387,6 +387,7 @@ class Thread: public ThreadHandle { // Create new thread. Thread(); + explicit Thread(const char* name); virtual ~Thread(); // Start new thread by calling the Run() method in the new thread. @@ -395,6 +396,10 @@ class Thread: public ThreadHandle { // Wait until thread terminates. void Join(); + inline const char* name() const { + return name_; + } + // Abstract method for run handler. virtual void Run() = 0; @@ -417,8 +422,16 @@ class Thread: public ThreadHandle { static void YieldCPU(); private: + void set_name(const char *name); + class PlatformData; PlatformData* data_; + + // The thread name length is limited to 16 based on Linux's implementation of + // prctl(). + static const int kMaxThreadNameLength = 16; + char name_[kMaxThreadNameLength]; + DISALLOW_COPY_AND_ASSIGN(Thread); }; diff --git a/src/top.cc b/src/top.cc index 3d86d11b7..98c673c1b 100644 --- a/src/top.cc +++ b/src/top.cc @@ -170,7 +170,9 @@ void Top::InitializeThreadLocal() { // into for use by a stacks only core dump (aka minidump). class PreallocatedMemoryThread: public Thread { public: - PreallocatedMemoryThread() : keep_running_(true) { + PreallocatedMemoryThread() + : Thread("v8:PreallocMem"), + keep_running_(true) { wait_for_ever_semaphore_ = OS::CreateSemaphore(0); data_ready_semaphore_ = OS::CreateSemaphore(0); } diff --git a/src/v8threads.cc b/src/v8threads.cc index b6e656d25..8a5fe6902 100644 --- a/src/v8threads.cc +++ b/src/v8threads.cc @@ -380,7 +380,8 @@ ContextSwitcher* ContextSwitcher::singleton_ = NULL; ContextSwitcher::ContextSwitcher(int every_n_ms) - : keep_going_(true), + : Thread("v8:CtxtSwitcher"), + keep_going_(true), sleep_ms_(every_n_ms) { } -- 2.34.1