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 |