michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_ThreadStackHelper_h michael@0: #define mozilla_ThreadStackHelper_h michael@0: michael@0: #include "mozilla/ThreadHangStats.h" michael@0: michael@0: #include "GeckoProfiler.h" michael@0: michael@0: #include michael@0: michael@0: #if defined(XP_LINUX) michael@0: #include michael@0: #include michael@0: #include michael@0: #elif defined(XP_WIN) michael@0: #include michael@0: #elif defined(XP_MACOSX) michael@0: #include michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: michael@0: /** michael@0: * ThreadStackHelper is used to retrieve the profiler pseudo-stack of a michael@0: * thread, as an alternative of using the profiler to take a profile. michael@0: * The target thread first declares an ThreadStackHelper instance; michael@0: * then another thread can call ThreadStackHelper::GetStack to retrieve michael@0: * the pseudo-stack of the target thread at that instant. michael@0: * michael@0: * Only non-copying labels are included in the stack, which means labels michael@0: * with custom text and markers are not included. michael@0: */ michael@0: class ThreadStackHelper michael@0: { michael@0: public: michael@0: typedef Telemetry::HangHistogram::Stack Stack; michael@0: michael@0: private: michael@0: #ifdef MOZ_ENABLE_PROFILER_SPS michael@0: const PseudoStack* const mPseudoStack; michael@0: #endif michael@0: Stack mStackBuffer; michael@0: size_t mMaxStackSize; michael@0: michael@0: bool PrepareStackBuffer(Stack& aStack); michael@0: void FillStackBuffer(); michael@0: michael@0: public: michael@0: /** michael@0: * Initialize ThreadStackHelper. Must be called from main thread. michael@0: */ michael@0: static void Startup(); michael@0: /** michael@0: * Uninitialize ThreadStackHelper. Must be called from main thread. michael@0: */ michael@0: static void Shutdown(); michael@0: michael@0: /** michael@0: * Create a ThreadStackHelper instance targeting the current thread. michael@0: */ michael@0: ThreadStackHelper(); michael@0: michael@0: ~ThreadStackHelper(); michael@0: michael@0: /** michael@0: * Retrieve the current pseudostack of the thread associated michael@0: * with this ThreadStackHelper. michael@0: * michael@0: * @param aStack Stack instance to be filled. michael@0: */ michael@0: void GetStack(Stack& aStack); michael@0: michael@0: #if defined(XP_LINUX) michael@0: private: michael@0: static int sInitialized; michael@0: static sem_t sSem; michael@0: static struct sigaction sOldSigAction; michael@0: static ThreadStackHelper* sCurrent; michael@0: michael@0: static void SigAction(int aSignal, siginfo_t* aInfo, void* aContext); michael@0: michael@0: pid_t mThreadID; michael@0: michael@0: #elif defined(XP_WIN) michael@0: private: michael@0: bool mInitialized; michael@0: HANDLE mThreadID; michael@0: michael@0: #elif defined(XP_MACOSX) michael@0: private: michael@0: thread_act_t mThreadID; michael@0: michael@0: #endif michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_ThreadStackHelper_h