mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1150252 - Make profiler sampler use pthread_kill on macos. r=mstange
This commit is contained in:
parent
7e7adb15c5
commit
106995796d
@ -217,10 +217,10 @@ private:
|
||||
void* const mStackTop;
|
||||
ThreadResponsiveness mRespInfo;
|
||||
|
||||
// Only Linux is using a signal sender, instead of stopping the thread, so we
|
||||
// Linux and OSX use a signal sender, instead of stopping the thread, so we
|
||||
// need some space to store the data which cannot be collected in the signal
|
||||
// handler code.
|
||||
#ifdef XP_LINUX
|
||||
#if defined(XP_LINUX) || defined(XP_MACOSX)
|
||||
public:
|
||||
int64_t mRssMemory;
|
||||
int64_t mUssMemory;
|
||||
|
@ -57,11 +57,38 @@ struct SamplerRegistry {
|
||||
|
||||
Sampler *SamplerRegistry::sampler = NULL;
|
||||
|
||||
// The following variables are used to communicate between the signal
|
||||
// sender thread and the signal handler on the sampled thread.
|
||||
//
|
||||
// sCurrentThreadProfile is used to pass the current thread profile INTO
|
||||
// the signal handler. sSignalHandlingDone is used by the handler to
|
||||
// indicate when it's finished. The signal-sender thread spins on
|
||||
// sSignalHandlingDone (using sched_yield). This is to avoid usage of
|
||||
// synchronization primitives like condvars in the signal handler code.
|
||||
static mozilla::Atomic<ThreadProfile*> sCurrentThreadProfile;
|
||||
static mozilla::Atomic<bool> sSignalHandlingDone;
|
||||
|
||||
#ifdef DEBUG
|
||||
// 0 is never a valid thread id on MacOSX since a pthread_t is a pointer.
|
||||
static const pthread_t kNoThread = (pthread_t) 0;
|
||||
#endif
|
||||
|
||||
static void SetSampleContext(TickSample* sample, void* context)
|
||||
{
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
||||
#if defined(SPS_PLAT_amd64_darwin)
|
||||
sample->pc = reinterpret_cast<Address>(mcontext->__ss.__rip);
|
||||
sample->sp = reinterpret_cast<Address>(mcontext->__ss.__rsp);
|
||||
sample->fp = reinterpret_cast<Address>(mcontext->__ss.__rbp);
|
||||
#elif defined(SPS_PLAT_x86_darwin)
|
||||
sample->pc = reinterpret_cast<Address>(mcontext->__ss.__eip);
|
||||
sample->sp = reinterpret_cast<Address>(mcontext->__ss.__esp);
|
||||
sample->fp = reinterpret_cast<Address>(mcontext->__ss.__ebp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OS::Startup() {
|
||||
}
|
||||
|
||||
@ -133,6 +160,48 @@ void Thread::Join() {
|
||||
pthread_join(thread_, NULL);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||
if (!Sampler::GetActiveSampler()) {
|
||||
sSignalHandlingDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
TickSample sample_obj;
|
||||
TickSample* sample = &sample_obj;
|
||||
sample->context = context;
|
||||
|
||||
// If profiling, we extract the current pc and sp.
|
||||
if (Sampler::GetActiveSampler()->IsProfiling()) {
|
||||
SetSampleContext(sample, context);
|
||||
}
|
||||
sample->threadProfile = sCurrentThreadProfile;
|
||||
sample->timestamp = mozilla::TimeStamp::Now();
|
||||
sample->rssMemory = sample->threadProfile->mRssMemory;
|
||||
sample->ussMemory = sample->threadProfile->mUssMemory;
|
||||
|
||||
Sampler::GetActiveSampler()->Tick(sample);
|
||||
|
||||
sCurrentThreadProfile = NULL;
|
||||
sSignalHandlingDone = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static void ProfilerSignalThread(ThreadProfile *profile,
|
||||
bool isFirstProfiledThread)
|
||||
{
|
||||
if (isFirstProfiledThread && Sampler::GetActiveSampler()->ProfileMemory()) {
|
||||
profile->mRssMemory = nsMemoryReporterManager::ResidentFast();
|
||||
profile->mUssMemory = nsMemoryReporterManager::ResidentUnique();
|
||||
} else {
|
||||
profile->mRssMemory = 0;
|
||||
profile->mUssMemory = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class PlatformData : public Malloced {
|
||||
public:
|
||||
PlatformData() : profiled_thread_(mach_thread_self())
|
||||
@ -226,6 +295,9 @@ class SamplerThread : public Thread {
|
||||
info->Profile()->GetThreadResponsiveness()->Update();
|
||||
|
||||
ThreadProfile* thread_profile = info->Profile();
|
||||
sCurrentThreadProfile = thread_profile;
|
||||
|
||||
ProfilerSignalThread(sCurrentThreadProfile, isFirstProfiledThread);
|
||||
|
||||
SampleContext(SamplerRegistry::sampler, thread_profile,
|
||||
isFirstProfiledThread);
|
||||
@ -246,58 +318,15 @@ class SamplerThread : public Thread {
|
||||
void SampleContext(Sampler* sampler, ThreadProfile* thread_profile,
|
||||
bool isFirstProfiledThread)
|
||||
{
|
||||
thread_act_t profiled_thread =
|
||||
thread_profile->GetPlatformData()->profiled_thread();
|
||||
pthread_t profiled_pthread =
|
||||
thread_profile->GetPlatformData()->profiled_pthread();
|
||||
|
||||
TickSample sample_obj;
|
||||
TickSample* sample = &sample_obj;
|
||||
|
||||
if (isFirstProfiledThread && Sampler::GetActiveSampler()->ProfileMemory()) {
|
||||
sample->rssMemory = nsMemoryReporterManager::ResidentFast();
|
||||
} else {
|
||||
sample->rssMemory = 0;
|
||||
MOZ_ASSERT(sSignalHandlingDone == false);
|
||||
pthread_kill(profiled_pthread, SIGPROF);
|
||||
while (!sSignalHandlingDone) {
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
// Unique Set Size is not supported on Mac.
|
||||
sample->ussMemory = 0;
|
||||
|
||||
if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
|
||||
|
||||
#if V8_HOST_ARCH_X64
|
||||
thread_state_flavor_t flavor = x86_THREAD_STATE64;
|
||||
x86_thread_state64_t state;
|
||||
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
|
||||
#if __DARWIN_UNIX03
|
||||
#define REGISTER_FIELD(name) __r ## name
|
||||
#else
|
||||
#define REGISTER_FIELD(name) r ## name
|
||||
#endif // __DARWIN_UNIX03
|
||||
#elif V8_HOST_ARCH_IA32
|
||||
thread_state_flavor_t flavor = i386_THREAD_STATE;
|
||||
i386_thread_state_t state;
|
||||
mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
|
||||
#if __DARWIN_UNIX03
|
||||
#define REGISTER_FIELD(name) __e ## name
|
||||
#else
|
||||
#define REGISTER_FIELD(name) e ## name
|
||||
#endif // __DARWIN_UNIX03
|
||||
#else
|
||||
#error Unsupported Mac OS X host architecture.
|
||||
#endif // V8_HOST_ARCH
|
||||
|
||||
if (thread_get_state(profiled_thread,
|
||||
flavor,
|
||||
reinterpret_cast<natural_t*>(&state),
|
||||
&count) == KERN_SUCCESS) {
|
||||
sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
|
||||
sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
|
||||
sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
|
||||
sample->timestamp = mozilla::TimeStamp::Now();
|
||||
sample->threadProfile = thread_profile;
|
||||
|
||||
sampler->Tick(sample);
|
||||
}
|
||||
thread_resume(profiled_thread);
|
||||
sSignalHandlingDone = false;
|
||||
}
|
||||
|
||||
int intervalMicro_;
|
||||
@ -330,8 +359,29 @@ Sampler::~Sampler() {
|
||||
|
||||
void Sampler::Start() {
|
||||
ASSERT(!IsActive());
|
||||
|
||||
// Initialize signal handler communication
|
||||
sCurrentThreadProfile = NULL;
|
||||
sSignalHandlingDone = false;
|
||||
|
||||
// Request profiling signals.
|
||||
LOG("Request signal");
|
||||
struct sigaction sa;
|
||||
sa.sa_sigaction = ProfilerSignalHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
if (sigaction(SIGPROF, &sa, &old_sigprof_signal_handler_) != 0) {
|
||||
LOG("Error installing signal");
|
||||
return;
|
||||
}
|
||||
signal_handler_installed_ = true;
|
||||
|
||||
// Start a thread that sends SIGPROF signal to VM thread.
|
||||
// Sending the signal ourselves instead of relying on itimer provides
|
||||
// much better accuracy.
|
||||
SetActive(true);
|
||||
SamplerThread::AddActiveSampler(this);
|
||||
LOG("Profiler thread started");
|
||||
}
|
||||
|
||||
|
||||
@ -339,6 +389,12 @@ void Sampler::Stop() {
|
||||
ASSERT(IsActive());
|
||||
SetActive(false);
|
||||
SamplerThread::RemoveActiveSampler(this);
|
||||
|
||||
// Restore old signal handler
|
||||
if (signal_handler_installed_) {
|
||||
sigaction(SIGPROF, &old_sigprof_signal_handler_, 0);
|
||||
signal_handler_installed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_t
|
||||
|
@ -397,6 +397,10 @@ class Sampler {
|
||||
bool signal_sender_launched_;
|
||||
pthread_t signal_sender_thread_;
|
||||
#endif
|
||||
#if defined(SPS_OS_darwin)
|
||||
bool signal_handler_installed_;
|
||||
struct sigaction old_sigprof_signal_handler_;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ThreadInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user