Chromium Code Reviews| Index: src/platform-linux.cc |
| diff --git a/src/platform-linux.cc b/src/platform-linux.cc |
| index ec48d6305e3de2ea4b51f0571a1c7a83bb0ae619..2030775ee0a57bdc135870d4aa6fe0a9ba4e8c2d 100644 |
| --- a/src/platform-linux.cc |
| +++ b/src/platform-linux.cc |
| @@ -1022,62 +1022,6 @@ static int GetThreadID() { |
| } |
| -static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
| - USE(info); |
| - if (signal != SIGPROF) return; |
| - Isolate* isolate = Isolate::UncheckedCurrent(); |
| - if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { |
| - // We require a fully initialized and entered isolate. |
| - return; |
| - } |
| - if (v8::Locker::IsActive() && |
| - !isolate->thread_manager()->IsLockedByCurrentThread()) { |
| - return; |
| - } |
| - |
| - Sampler* sampler = isolate->logger()->sampler(); |
| - if (sampler == NULL || !sampler->IsActive()) return; |
| - |
| - TickSample sample_obj; |
| - TickSample* sample = CpuProfiler::TickSampleEvent(isolate); |
| - if (sample == NULL) sample = &sample_obj; |
| - |
| - // Extracting the sample from the context is extremely machine dependent. |
| - ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
| - mcontext_t& mcontext = ucontext->uc_mcontext; |
| - sample->state = isolate->current_vm_state(); |
| -#if V8_HOST_ARCH_IA32 |
| - sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
| - sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
| - sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
| -#elif V8_HOST_ARCH_X64 |
| - sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
| - sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
| - sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
| -#elif V8_HOST_ARCH_ARM |
| -#if defined(__GLIBC__) && !defined(__UCLIBC__) && \ |
| - (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
| - // Old GLibc ARM versions used a gregs[] array to access the register |
| - // values from mcontext_t. |
| - sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
| - sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
| - sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
| -#else |
| - sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); |
| - sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); |
| - sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); |
| -#endif // defined(__GLIBC__) && !defined(__UCLIBC__) && |
| - // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
| -#elif V8_HOST_ARCH_MIPS |
| - sample->pc = reinterpret_cast<Address>(mcontext.pc); |
| - sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
| - sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
| -#endif // V8_HOST_ARCH_* |
| - sampler->SampleStack(sample); |
| - sampler->Tick(sample); |
| -} |
| - |
| - |
| class Sampler::PlatformData : public Malloced { |
| public: |
| PlatformData() : vm_tid_(GetThreadID()) {} |
| @@ -1089,6 +1033,9 @@ class Sampler::PlatformData : public Malloced { |
| }; |
| +static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context); |
|
Markus (顧孟勤)
2012/12/13 08:49:45
Our style guide for some reason prefers that we do
Sven Panne
2012/12/13 09:34:54
The Google C++ style guide allows both possibiliti
Markus (顧孟勤)
2012/12/13 09:56:50
Ah, sanity prevails. And yes, I agree that the pre
|
| + |
| + |
| class SignalSender : public Thread { |
| public: |
| enum SleepInterval { |
| @@ -1122,6 +1069,23 @@ class SignalSender : public Thread { |
| } |
| } |
| + static void CallOldSignalHandler(int signal, siginfo_t* info, void* context) { |
| + // Only invoke the old signal handler if it did not have SIGPROF masked. |
| + if (sigismember(&old_signal_handler_.sa_mask, SIGPROF)) |
|
Markus (顧孟勤)
2012/12/13 08:49:45
I don't believe this is the correct mask. See belo
|
| + return; |
| + if (!(old_signal_handler_.sa_flags & SA_SIGINFO)) { |
| + // It's safe to ignore the old signal handler if it's one of these values. |
|
Markus (顧孟勤)
2012/12/13 08:49:45
Your code is arguably the right thing to do ... ev
|
| + if (old_signal_handler_.sa_handler == SIG_IGN || |
| + old_signal_handler_.sa_handler == SIG_DFL) { |
| + return; |
| + } |
| + // Sorry, we only support other 3-arg signal handlers (sigaction). Crash |
| + // loudly if someone tries to use a different signal handler. |
| + *(reinterpret_cast<volatile char*>(NULL) + 74) = 0x34; |
| + } |
| + old_signal_handler_.sa_sigaction(signal, info, context); |
| + } |
| + |
| static void AddActiveSampler(Sampler* sampler) { |
| ScopedLock lock(mutex_); |
| SamplerRegistry::AddActiveSampler(sampler); |
| @@ -1255,6 +1219,65 @@ struct sigaction SignalSender::old_signal_handler_; |
| bool SignalSender::signal_handler_installed_ = false; |
| +static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
| + int curr_errno = errno; |
| + USE(info); |
| + if (signal != SIGPROF) return; |
|
Markus (顧孟勤)
2012/12/13 08:49:45
You should probably restore "errno" for each of th
|
| + SignalSender::CallOldSignalHandler(signal, info, context); |
| + Isolate* isolate = Isolate::UncheckedCurrent(); |
| + if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { |
| + // We require a fully initialized and entered isolate. |
| + return; |
| + } |
| + if (v8::Locker::IsActive() && |
| + !isolate->thread_manager()->IsLockedByCurrentThread()) { |
| + return; |
| + } |
| + |
| + Sampler* sampler = isolate->logger()->sampler(); |
| + if (sampler == NULL || !sampler->IsActive()) return; |
| + |
| + TickSample sample_obj; |
| + TickSample* sample = CpuProfiler::TickSampleEvent(isolate); |
| + if (sample == NULL) sample = &sample_obj; |
| + |
| + // Extracting the sample from the context is extremely machine dependent. |
| + ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
| + mcontext_t& mcontext = ucontext->uc_mcontext; |
| + sample->state = isolate->current_vm_state(); |
| +#if V8_HOST_ARCH_IA32 |
| + sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
| + sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
| + sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
| +#elif V8_HOST_ARCH_X64 |
| + sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
| + sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
| + sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
| +#elif V8_HOST_ARCH_ARM |
| +#if defined(__GLIBC__) && !defined(__UCLIBC__) && \ |
| + (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
| + // Old GLibc ARM versions used a gregs[] array to access the register |
| + // values from mcontext_t. |
| + sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
| + sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
| + sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
| +#else |
| + sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); |
| + sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); |
| + sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); |
| +#endif // defined(__GLIBC__) && !defined(__UCLIBC__) && |
| + // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
| +#elif V8_HOST_ARCH_MIPS |
| + sample->pc = reinterpret_cast<Address>(mcontext.pc); |
| + sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
| + sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
| +#endif // V8_HOST_ARCH_* |
| + sampler->SampleStack(sample); |
| + sampler->Tick(sample); |
| + errno = curr_errno; |
| +} |
| + |
| + |
| void OS::SetUp() { |
| // Seed the random number generator. We preserve microsecond resolution. |
| uint64_t seed = Ticks() ^ (getpid() << 16); |