Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(588)

Unified Diff: runtime/vm/thread_interrupter_android.cc

Issue 1940883002: Work around a kernel bug on Android. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/signal_handler.h ('k') | runtime/vm/thread_interrupter_linux.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/thread_interrupter_android.cc
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index 82be148cbd07f3b85c7f594eaf585ef9b832ca6b..0cc1b2a71e4285f16b479aadb25c93051e5a7cc4 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -21,29 +21,59 @@ namespace dart {
DECLARE_FLAG(bool, thread_interrupter);
DECLARE_FLAG(bool, trace_thread_interrupter);
-class ThreadInterrupterAndroid : public AllStatic {
- public:
- static void ThreadInterruptSignalHandler(int signal, siginfo_t* info,
- void* context_) {
- if (signal != SIGPROF) {
- return;
- }
- Thread* thread = Thread::Current();
- if (thread == NULL) {
- return;
- }
- // Extract thread state.
- ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
- mcontext_t mcontext = context->uc_mcontext;
- InterruptedThreadState its;
- its.pc = SignalHandler::GetProgramCounter(mcontext);
- its.fp = SignalHandler::GetFramePointer(mcontext);
- its.csp = SignalHandler::GetCStackPointer(mcontext);
- its.dsp = SignalHandler::GetDartStackPointer(mcontext);
- its.lr = SignalHandler::GetLinkRegister(mcontext);
- Profiler::SampleThread(thread, its);
+static void ThreadInterruptSignalHandler(int signal, siginfo_t* info,
+ void* context_) {
+ if (signal != SIGPROF) {
+ return;
}
-};
+ Thread* thread = Thread::Current();
+ if (thread == NULL) {
+ return;
+ }
+ // Extract thread state.
+ ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
+ mcontext_t mcontext = context->uc_mcontext;
+ InterruptedThreadState its;
+ its.pc = SignalHandler::GetProgramCounter(mcontext);
+ its.fp = SignalHandler::GetFramePointer(mcontext);
+ its.csp = SignalHandler::GetCStackPointer(mcontext);
+ its.dsp = SignalHandler::GetDartStackPointer(mcontext);
+ its.lr = SignalHandler::GetLinkRegister(mcontext);
+ Profiler::SampleThread(thread, its);
+}
+
+
+// Work around for a bug in old kernels (only fixed in 3.18 Android kernel):
+// kernel does not clear If-Then execution state bits when entering ARM signal
+// handler which violates requirements imposed by ARM architecture reference.
+// Some CPUs look at these bits even while in ARM mode which causes them
+// to skip some instructions in the prologue of the signal handler.
+// To work around the issue we insert enough NOPs in the prologue to ensure that
+// no actual instructions are skipped and then branch to the actual signal
+// handler.
+// For the kernel patch that fixes the issue see: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6ecf830e5029598732e04067e325d946097519cb
+// Note: this function is marked "naked" because we must guarantee that
+// our NOPs occur before any compiler generated prologue.
+static __attribute__((naked)) void SignalHandlerTrampoline(int signal,
+ siginfo_t* info,
+ void* context_) {
+ // IT (If-Then) instruction makes up to four instructions that follow it
+ // conditional.
+ asm volatile("nop; nop; nop; nop" : : : "memory");
+
+ // Tail-call into the actual signal handler.
+ // Note: this code is split into a separate inline assembly block because
+ // any code that compiler generates to satisfy register constraints must
+ // be generated after four NOPs.
+ register int arg0 asm("r0") = signal;
+ register siginfo_t* arg1 asm("r1") = info;
+ register void* arg2 asm("r2") = context_;
+ asm volatile("bx %3"
Florian Schneider 2016/05/02 13:44:45 Need this only on ARM, not on Android ia32 for exa
+ :
+ : "r"(arg0), "r"(arg1), "r"(arg2),
+ "r"(&ThreadInterruptSignalHandler)
+ : "memory");
+}
void ThreadInterrupter::InterruptThread(OSThread* thread) {
@@ -57,8 +87,7 @@ void ThreadInterrupter::InterruptThread(OSThread* thread) {
void ThreadInterrupter::InstallSignalHandler() {
- SignalHandler::Install(
- ThreadInterrupterAndroid::ThreadInterruptSignalHandler);
+ SignalHandler::Install(&SignalHandlerTrampoline);
}
« no previous file with comments | « runtime/vm/signal_handler.h ('k') | runtime/vm/thread_interrupter_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698