Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
| 6 #if defined(HOST_OS_FUCHSIA) | 6 #if defined(HOST_OS_FUCHSIA) |
| 7 | 7 |
| 8 #include "vm/thread_interrupter.h" | 8 #include "vm/thread_interrupter.h" |
| 9 | 9 |
| 10 #include "platform/assert.h" | 10 #include <magenta/process.h> |
| 11 #include <magenta/status.h> | |
| 12 #include <magenta/syscalls.h> | |
| 13 #include <magenta/syscalls/debug.h> | |
| 14 #include <magenta/types.h> | |
| 15 | |
| 16 #include "vm/flags.h" | |
| 17 #include "vm/instructions.h" | |
| 18 #include "vm/os.h" | |
| 19 #include "vm/profiler.h" | |
| 11 | 20 |
| 12 namespace dart { | 21 namespace dart { |
| 13 | 22 |
| 23 #ifndef PRODUCT | |
| 24 | |
| 25 DECLARE_FLAG(bool, thread_interrupter); | |
| 26 DECLARE_FLAG(bool, trace_thread_interrupter); | |
| 27 | |
| 28 class ThreadInterrupterFuchsia : public AllStatic { | |
| 29 public: | |
| 30 static bool GrabRegisters(mx_handle_t thread, InterruptedThreadState* state) { | |
| 31 // TODO(zra): Enable this when mx_thread_read_state() works on suspended | |
| 32 // threads. | |
| 33 while (false) { | |
| 34 char buf[MX_MAX_THREAD_STATE_SIZE]; | |
| 35 uint32_t regset_size = MX_MAX_THREAD_STATE_SIZE; | |
| 36 mx_status_t status = mx_thread_read_state( | |
| 37 thread, MX_THREAD_STATE_REGSET0, &buf[0], regset_size, ®set_size); | |
| 38 if (status != NO_ERROR) { | |
| 39 OS::Print("ThreadInterrupter failed to get registers: %s\n", | |
| 40 mx_status_get_string(status)); | |
|
siva
2017/05/18 00:11:30
OS::PrintErr here?
zra
2017/05/23 16:09:43
Done.
| |
| 41 return false; | |
| 42 } | |
| 43 #if defined(TARGET_ARCH_X64) | |
| 44 mx_x86_64_general_regs_t* regs = | |
| 45 reinterpret_cast<mx_x86_64_general_regs_t*>(&buf[0]); | |
| 46 state->pc = static_cast<uintptr_t>(regs->rip); | |
| 47 state->fp = static_cast<uintptr_t>(regs->rbp); | |
| 48 state->csp = static_cast<uintptr_t>(regs->rsp); | |
| 49 state->dsp = static_cast<uintptr_t>(regs->rsp); | |
| 50 #elif defined(TARGET_ARCH_ARM64) | |
| 51 mx_aarch64_general_regs_t* regs = | |
| 52 reinterpret_cast<mx_aarch64_general_regs_t*>(&buf[0]); | |
| 53 state->pc = static_cast<uintptr_t>(regs->pc); | |
| 54 state->fp = static_cast<uintptr_t>(regs->r[29]); | |
|
siva
2017/05/18 00:11:30
can we use a name here instead of 29
zra
2017/05/23 16:09:43
Done.
| |
| 55 state->csp = static_cast<uintptr_t>(regs->sp); | |
| 56 state->dsp = static_cast<uintptr_t>(regs->r[SPREG]); | |
| 57 state->lr = static_cast<uintptr_t>(regs->lr); | |
| 58 #else | |
| 59 #error "Unsupported architecture" | |
| 60 #endif | |
| 61 } | |
| 62 return true; | |
| 63 } | |
| 64 | |
| 65 | |
| 66 static void Interrupt(OSThread* os_thread) { | |
| 67 ASSERT(!OSThread::Compare(OSThread::GetCurrentThreadId(), os_thread->id())); | |
| 68 mx_status_t status; | |
| 69 | |
| 70 // Get a handle on the target thread. | |
| 71 mx_koid_t target_thread_koid = os_thread->id(); | |
| 72 if (FLAG_trace_thread_interrupter) { | |
| 73 OS::Print("ThreadInterrupter: interrupting thread with koid=%d\n", | |
| 74 target_thread_koid); | |
| 75 } | |
| 76 mx_handle_t target_thread_handle; | |
| 77 status = mx_object_get_child(mx_process_self(), | |
|
rmacnak
2017/05/18 01:31:27
Why use the koid as the ThreadId and keep creating
zra
2017/05/23 16:09:43
Mostly because it's not entirely clear whether an
| |
| 78 target_thread_koid, | |
| 79 MX_RIGHT_SAME_RIGHTS, | |
| 80 &target_thread_handle); | |
| 81 if (status != NO_ERROR) { | |
| 82 if (FLAG_trace_thread_interrupter) { | |
| 83 OS::Print("ThreadInterrupter failed to get the thread handle: %s\n", | |
| 84 mx_status_get_string(status)); | |
| 85 } | |
| 86 FATAL1("mx_object_get_child failed: %s", mx_status_get_string(status)); | |
| 87 } | |
| 88 if (target_thread_handle == MX_HANDLE_INVALID) { | |
| 89 FATAL("ThreadInterrupter got an invalid target thread handle!"); | |
| 90 } | |
| 91 | |
| 92 // Pause the target thread. | |
| 93 status = mx_task_suspend(target_thread_handle); | |
| 94 if (status != NO_ERROR) { | |
| 95 if (FLAG_trace_thread_interrupter) { | |
| 96 OS::Print("ThreadInterrupter failed to suspend thread %ld: %s\n", | |
| 97 static_cast<intptr_t>(os_thread->id()), | |
| 98 mx_status_get_string(status)); | |
| 99 } | |
| 100 mx_handle_close(target_thread_handle); | |
| 101 FATAL1("mx_task_suspend failed: %s", mx_status_get_string(status)); | |
| 102 } | |
| 103 | |
| 104 // TODO(zra): Enable this when mx_thread_read_state() works on suspended | |
| 105 // threads. | |
| 106 while (false) { | |
| 107 // Grab the target thread's registers. | |
| 108 InterruptedThreadState its; | |
| 109 if (!GrabRegisters(target_thread_handle, &its)) { | |
| 110 // Failed to get thread registers. | |
| 111 status = mx_task_resume(target_thread_handle, 0); | |
| 112 if (status != NO_ERROR) { | |
| 113 FATAL1("mx_task_resume failed: %s", mx_status_get_string(status)); | |
| 114 } | |
| 115 mx_handle_close(target_thread_handle); | |
| 116 return; | |
| 117 } | |
| 118 // Currently we sample only threads that are associated | |
| 119 // with an isolate. It is safe to call 'os_thread->thread()' | |
| 120 // here as the thread which is being queried is suspended. | |
| 121 Thread* thread = os_thread->thread(); | |
| 122 if (thread != NULL) { | |
| 123 Profiler::SampleThread(thread, its); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 // Resume the target thread. | |
| 128 status = mx_task_resume(target_thread_handle, 0); | |
| 129 if (status != NO_ERROR) { | |
| 130 FATAL1("mx_task_resume failed: %s", mx_status_get_string(status)); | |
| 131 } | |
| 132 mx_handle_close(target_thread_handle); | |
| 133 } | |
| 134 }; | |
| 135 | |
| 136 | |
| 14 bool ThreadInterrupter::IsDebuggerAttached() { | 137 bool ThreadInterrupter::IsDebuggerAttached() { |
| 15 return false; | 138 return false; |
| 16 } | 139 } |
| 17 | 140 |
| 141 | |
| 18 void ThreadInterrupter::InterruptThread(OSThread* thread) { | 142 void ThreadInterrupter::InterruptThread(OSThread* thread) { |
| 19 UNIMPLEMENTED(); | 143 if (FLAG_trace_thread_interrupter) { |
| 144 OS::Print("ThreadInterrupter suspending %p\n", | |
| 145 reinterpret_cast<void*>(thread->id())); | |
| 146 } | |
| 147 ThreadInterrupterFuchsia::Interrupt(thread); | |
| 148 if (FLAG_trace_thread_interrupter) { | |
| 149 OS::Print("ThreadInterrupter resuming %p\n", | |
| 150 reinterpret_cast<void*>(thread->id())); | |
| 151 } | |
| 20 } | 152 } |
| 21 | 153 |
| 22 | 154 |
| 23 void ThreadInterrupter::InstallSignalHandler() { | 155 void ThreadInterrupter::InstallSignalHandler() { |
| 24 UNIMPLEMENTED(); | 156 // Nothing to do on Fuchsia. |
| 25 } | 157 } |
| 26 | 158 |
| 27 | 159 |
| 28 void ThreadInterrupter::RemoveSignalHandler() { | 160 void ThreadInterrupter::RemoveSignalHandler() { |
| 29 UNIMPLEMENTED(); | 161 // Nothing to do on Fuchsia. |
| 30 } | 162 } |
| 31 | 163 |
| 164 #endif // !PRODUCT | |
| 165 | |
| 32 } // namespace dart | 166 } // namespace dart |
| 33 | 167 |
| 34 #endif // defined(HOST_OS_FUCHSIA) | 168 #endif // defined(HOST_OS_FUCHSIA) |
| OLD | NEW |