michael@0: /* -*- Mode: C++; tab-width: 2; 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 MOZ_UNWINDER_THREAD_2_H michael@0: #define MOZ_UNWINDER_THREAD_2_H michael@0: michael@0: #include "GeckoProfilerImpl.h" michael@0: #include "ProfileEntry.h" michael@0: michael@0: #include "PlatformMacros.h" michael@0: #if defined(SPS_OS_android) || defined(SPS_OS_linux) michael@0: # include "LulMain.h" michael@0: #endif michael@0: michael@0: /* Top level exports of UnwinderThread.cpp. */ michael@0: michael@0: // Abstract type. A buffer which is used to transfer information between michael@0: // the sampled thread(s) and the unwinder thread(s). michael@0: typedef michael@0: struct _UnwinderThreadBuffer michael@0: UnwinderThreadBuffer; michael@0: michael@0: // RUNS IN SIGHANDLER CONTEXT michael@0: // Called in the sampled thread (signal) context. Adds a ProfileEntry michael@0: // into an UnwinderThreadBuffer that the thread has previously obtained michael@0: // by a call to utb__acquire_empty_buffer. michael@0: void utb__addEntry(/*MOD*/UnwinderThreadBuffer* utb, michael@0: ProfileEntry ent); michael@0: michael@0: // Create the unwinder thread. At the moment there can be only one. michael@0: void uwt__init(); michael@0: michael@0: // Request the unwinder thread to exit, and wait until it has done so. michael@0: // This must be called before stopping the profiler because we hold a michael@0: // reference to the profile which is owned by the profiler. michael@0: void uwt__stop(); michael@0: michael@0: // Release the unwinder resources. This must be called after profiling michael@0: // has stop. At this point we know the profiler doesn't hold any buffer michael@0: // and can safely release any resources. michael@0: void uwt__deinit(); michael@0: michael@0: // Registers a sampler thread for profiling. Threads must be michael@0: // registered before calls to call utb__acquire_empty_buffer or michael@0: // utb__release_full_buffer have any effect. If stackTop is michael@0: // nullptr, the call is ignored. michael@0: void uwt__register_thread_for_profiling(void* stackTop); michael@0: michael@0: // Deregister a sampler thread for profiling. michael@0: void uwt__unregister_thread_for_profiling(); michael@0: michael@0: // RUNS IN SIGHANDLER CONTEXT michael@0: // Called in the sampled thread (signal) context. Get an empty buffer michael@0: // into which ProfileEntries can be put. It may return nullptr if no michael@0: // empty buffers can be found, which will be the case if the unwinder michael@0: // thread(s) have fallen behind for some reason. In this case the michael@0: // sampled thread must simply give up and return from the signal michael@0: // handler immediately, else it risks deadlock. michael@0: // michael@0: // If the calling thread has not previously registered itself for michael@0: // profiling via uwt__register_thread_for_profiling, this routine michael@0: // returns nullptr. michael@0: UnwinderThreadBuffer* uwt__acquire_empty_buffer(); michael@0: michael@0: // RUNS IN SIGHANDLER CONTEXT michael@0: // Called in the sampled thread (signal) context. Release a buffer michael@0: // that the sampled thread has acquired, handing the contents to michael@0: // the unwinder thread, and, if necessary, passing sufficient michael@0: // information (stack top chunk, + registers) to also do a native michael@0: // unwind. If 'ucV' is nullptr, no native unwind is done. If non-nullptr, michael@0: // it is assumed to point to a ucontext_t* that holds the initial michael@0: // register state for the unwind. The results of all of this are michael@0: // dumped into |aProfile| (by the unwinder thread, not the calling thread). michael@0: void uwt__release_full_buffer(ThreadProfile* aProfile, michael@0: UnwinderThreadBuffer* utb, michael@0: void* /* ucontext_t*, really */ ucV); michael@0: michael@0: struct LinkedUWTBuffer; michael@0: michael@0: // Get an empty buffer for synchronous unwinding. michael@0: // This function is NOT signal-safe. michael@0: LinkedUWTBuffer* utb__acquire_sync_buffer(void* stackTop); michael@0: michael@0: void utb__finish_sync_buffer(ThreadProfile* aProfile, michael@0: UnwinderThreadBuffer* utb, michael@0: void* /* ucontext_t*, really */ ucV); michael@0: michael@0: // Free an empty buffer that was previously allocated by michael@0: // utb__acquire_sync_buffer. michael@0: void utb__release_sync_buffer(LinkedUWTBuffer* utb); michael@0: michael@0: // This typedef must match uwt__release_full_buffer and uwt__finish_sync_buffer michael@0: typedef void (*UTB_RELEASE_FUNC)(ThreadProfile*,UnwinderThreadBuffer*,void*); michael@0: michael@0: #if defined(SPS_OS_android) || defined(SPS_OS_linux) michael@0: // Notify |aLUL| of the objects in the current process, so as to get michael@0: // it to read unwind data for them. This has to be externally visible michael@0: // so it can be used in LUL unit tests, tools/profiler/tests/gtest/LulTest.cpp. michael@0: void read_procmaps(lul::LUL* aLUL); michael@0: #endif michael@0: michael@0: #endif /* ndef MOZ_UNWINDER_THREAD_2_H */