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 <magenta/process.h> | 10 #include <magenta/process.h> |
(...skipping 22 matching lines...) Expand all Loading... |
33 // feature is added for it. | 33 // feature is added for it. |
34 | 34 |
35 // A scope within which a target thread is suspended. When the scope is exited, | 35 // A scope within which a target thread is suspended. When the scope is exited, |
36 // the thread is resumed and its handle is closed. | 36 // the thread is resumed and its handle is closed. |
37 class ThreadSuspendScope { | 37 class ThreadSuspendScope { |
38 public: | 38 public: |
39 explicit ThreadSuspendScope(mx_handle_t thread_handle) | 39 explicit ThreadSuspendScope(mx_handle_t thread_handle) |
40 : thread_handle_(thread_handle), suspended_(true) { | 40 : thread_handle_(thread_handle), suspended_(true) { |
41 mx_status_t status = mx_task_suspend(thread_handle); | 41 mx_status_t status = mx_task_suspend(thread_handle); |
42 // If a thread is somewhere where suspend is impossible, mx_task_suspend() | 42 // If a thread is somewhere where suspend is impossible, mx_task_suspend() |
43 // can return ERR_NOT_SUPPORTED. | 43 // can return MX_ERR_NOT_SUPPORTED. |
44 if (status != NO_ERROR) { | 44 if (status != MX_OK) { |
45 if (FLAG_trace_thread_interrupter) { | 45 if (FLAG_trace_thread_interrupter) { |
46 OS::PrintErr("ThreadInterrupter: mx_task_suspend failed: %s\n", | 46 OS::PrintErr("ThreadInterrupter: mx_task_suspend failed: %s\n", |
47 mx_status_get_string(status)); | 47 mx_status_get_string(status)); |
48 } | 48 } |
49 suspended_ = false; | 49 suspended_ = false; |
50 } | 50 } |
51 } | 51 } |
52 | 52 |
53 ~ThreadSuspendScope() { | 53 ~ThreadSuspendScope() { |
54 if (suspended_) { | 54 if (suspended_) { |
55 mx_status_t status = mx_task_resume(thread_handle_, 0); | 55 mx_status_t status = mx_task_resume(thread_handle_, 0); |
56 if (status != NO_ERROR) { | 56 if (status != MX_OK) { |
57 // If we fail to resume a thread, then it's likely the program will | 57 // If we fail to resume a thread, then it's likely the program will |
58 // hang. Crash instead. | 58 // hang. Crash instead. |
59 FATAL1("mx_task_resume failed: %s", mx_status_get_string(status)); | 59 FATAL1("mx_task_resume failed: %s", mx_status_get_string(status)); |
60 } | 60 } |
61 } | 61 } |
62 mx_handle_close(thread_handle_); | 62 mx_handle_close(thread_handle_); |
63 } | 63 } |
64 | 64 |
65 bool suspended() const { return suspended_; } | 65 bool suspended() const { return suspended_; } |
66 | 66 |
67 private: | 67 private: |
68 mx_handle_t thread_handle_; | 68 mx_handle_t thread_handle_; |
69 bool suspended_; | 69 bool suspended_; |
70 | 70 |
71 DISALLOW_ALLOCATION(); | 71 DISALLOW_ALLOCATION(); |
72 DISALLOW_COPY_AND_ASSIGN(ThreadSuspendScope); | 72 DISALLOW_COPY_AND_ASSIGN(ThreadSuspendScope); |
73 }; | 73 }; |
74 | 74 |
75 class ThreadInterrupterFuchsia : public AllStatic { | 75 class ThreadInterrupterFuchsia : public AllStatic { |
76 public: | 76 public: |
77 #if defined(TARGET_ARCH_X64) | 77 #if defined(TARGET_ARCH_X64) |
78 static bool GrabRegisters(mx_handle_t thread, InterruptedThreadState* state) { | 78 static bool GrabRegisters(mx_handle_t thread, InterruptedThreadState* state) { |
79 mx_x86_64_general_regs_t regs; | 79 mx_x86_64_general_regs_t regs; |
80 uint32_t regset_size; | 80 uint32_t regset_size; |
81 mx_status_t status = mx_thread_read_state( | 81 mx_status_t status = mx_thread_read_state( |
82 thread, MX_THREAD_STATE_REGSET0, ®s, sizeof(regs), ®set_size); | 82 thread, MX_THREAD_STATE_REGSET0, ®s, sizeof(regs), ®set_size); |
83 if (status != NO_ERROR) { | 83 if (status != MX_OK) { |
84 if (FLAG_trace_thread_interrupter) { | 84 if (FLAG_trace_thread_interrupter) { |
85 OS::PrintErr("ThreadInterrupter failed to get registers: %s\n", | 85 OS::PrintErr("ThreadInterrupter failed to get registers: %s\n", |
86 mx_status_get_string(status)); | 86 mx_status_get_string(status)); |
87 } | 87 } |
88 return false; | 88 return false; |
89 } | 89 } |
90 state->pc = static_cast<uintptr_t>(regs.rip); | 90 state->pc = static_cast<uintptr_t>(regs.rip); |
91 state->fp = static_cast<uintptr_t>(regs.rbp); | 91 state->fp = static_cast<uintptr_t>(regs.rbp); |
92 state->csp = static_cast<uintptr_t>(regs.rsp); | 92 state->csp = static_cast<uintptr_t>(regs.rsp); |
93 state->dsp = static_cast<uintptr_t>(regs.rsp); | 93 state->dsp = static_cast<uintptr_t>(regs.rsp); |
94 return true; | 94 return true; |
95 } | 95 } |
96 #elif defined(TARGET_ARCH_ARM64) | 96 #elif defined(TARGET_ARCH_ARM64) |
97 static bool GrabRegisters(mx_handle_t thread, InterruptedThreadState* state) { | 97 static bool GrabRegisters(mx_handle_t thread, InterruptedThreadState* state) { |
98 mx_arm64_general_regs_t regs; | 98 mx_arm64_general_regs_t regs; |
99 uint32_t regset_size; | 99 uint32_t regset_size; |
100 mx_status_t status = mx_thread_read_state( | 100 mx_status_t status = mx_thread_read_state( |
101 thread, MX_THREAD_STATE_REGSET0, ®s, sizeof(regs), ®set_size); | 101 thread, MX_THREAD_STATE_REGSET0, ®s, sizeof(regs), ®set_size); |
102 if (status != NO_ERROR) { | 102 if (status != MX_OK) { |
103 if (FLAG_trace_thread_interrupter) { | 103 if (FLAG_trace_thread_interrupter) { |
104 OS::PrintErr("ThreadInterrupter failed to get registers: %s\n", | 104 OS::PrintErr("ThreadInterrupter failed to get registers: %s\n", |
105 mx_status_get_string(status)); | 105 mx_status_get_string(status)); |
106 } | 106 } |
107 return false; | 107 return false; |
108 } | 108 } |
109 state->pc = static_cast<uintptr_t>(regs.pc); | 109 state->pc = static_cast<uintptr_t>(regs.pc); |
110 state->fp = static_cast<uintptr_t>(regs.r[FPREG]); | 110 state->fp = static_cast<uintptr_t>(regs.r[FPREG]); |
111 state->csp = static_cast<uintptr_t>(regs.sp); | 111 state->csp = static_cast<uintptr_t>(regs.sp); |
112 state->dsp = static_cast<uintptr_t>(regs.r[SPREG]); | 112 state->dsp = static_cast<uintptr_t>(regs.r[SPREG]); |
(...skipping 11 matching lines...) Expand all Loading... |
124 | 124 |
125 // Get a handle on the target thread. | 125 // Get a handle on the target thread. |
126 const mx_koid_t target_thread_koid = os_thread->id(); | 126 const mx_koid_t target_thread_koid = os_thread->id(); |
127 if (FLAG_trace_thread_interrupter) { | 127 if (FLAG_trace_thread_interrupter) { |
128 OS::PrintErr("ThreadInterrupter: interrupting thread with koid=%d\n", | 128 OS::PrintErr("ThreadInterrupter: interrupting thread with koid=%d\n", |
129 target_thread_koid); | 129 target_thread_koid); |
130 } | 130 } |
131 mx_handle_t target_thread_handle; | 131 mx_handle_t target_thread_handle; |
132 status = mx_object_get_child(mx_process_self(), target_thread_koid, | 132 status = mx_object_get_child(mx_process_self(), target_thread_koid, |
133 MX_RIGHT_SAME_RIGHTS, &target_thread_handle); | 133 MX_RIGHT_SAME_RIGHTS, &target_thread_handle); |
134 if (status != NO_ERROR) { | 134 if (status != MX_OK) { |
135 if (FLAG_trace_thread_interrupter) { | 135 if (FLAG_trace_thread_interrupter) { |
136 OS::PrintErr("ThreadInterrupter: mx_object_get_child failed: %s\n", | 136 OS::PrintErr("ThreadInterrupter: mx_object_get_child failed: %s\n", |
137 mx_status_get_string(status)); | 137 mx_status_get_string(status)); |
138 } | 138 } |
139 return; | 139 return; |
140 } | 140 } |
141 if (target_thread_handle == MX_HANDLE_INVALID) { | 141 if (target_thread_handle == MX_HANDLE_INVALID) { |
142 if (FLAG_trace_thread_interrupter) { | 142 if (FLAG_trace_thread_interrupter) { |
143 OS::PrintErr( | 143 OS::PrintErr( |
144 "ThreadInterrupter: mx_object_get_child gave an invalid " | 144 "ThreadInterrupter: mx_object_get_child gave an invalid " |
145 "thread handle!"); | 145 "thread handle!"); |
146 } | 146 } |
147 return; | 147 return; |
148 } | 148 } |
149 | 149 |
150 // This scope suspends the thread. When we exit the scope, the thread is | 150 // This scope suspends the thread. When we exit the scope, the thread is |
151 // resumed, and the thread handle is closed. | 151 // resumed, and the thread handle is closed. |
152 ThreadSuspendScope tss(target_thread_handle); | 152 ThreadSuspendScope tss(target_thread_handle); |
153 if (!tss.suspended()) { | 153 if (!tss.suspended()) { |
154 return; | 154 return; |
155 } | 155 } |
156 | 156 |
157 // Check that the thread is suspended. | 157 // Check that the thread is suspended. |
158 status = PollThreadUntilSuspended(target_thread_handle); | 158 status = PollThreadUntilSuspended(target_thread_handle); |
159 if (status != NO_ERROR) { | 159 if (status != MX_OK) { |
160 return; | 160 return; |
161 } | 161 } |
162 | 162 |
163 // Grab the target thread's registers. | 163 // Grab the target thread's registers. |
164 InterruptedThreadState its; | 164 InterruptedThreadState its; |
165 if (!GrabRegisters(target_thread_handle, &its)) { | 165 if (!GrabRegisters(target_thread_handle, &its)) { |
166 return; | 166 return; |
167 } | 167 } |
168 // Currently we sample only threads that are associated | 168 // Currently we sample only threads that are associated |
169 // with an isolate. It is safe to call 'os_thread->thread()' | 169 // with an isolate. It is safe to call 'os_thread->thread()' |
(...skipping 26 matching lines...) Expand all Loading... |
196 | 196 |
197 static mx_status_t PollThreadUntilSuspended(mx_handle_t thread_handle) { | 197 static mx_status_t PollThreadUntilSuspended(mx_handle_t thread_handle) { |
198 const intptr_t kMaxPollAttempts = 10; | 198 const intptr_t kMaxPollAttempts = 10; |
199 intptr_t poll_tries = 0; | 199 intptr_t poll_tries = 0; |
200 while (poll_tries < kMaxPollAttempts) { | 200 while (poll_tries < kMaxPollAttempts) { |
201 mx_info_thread_t thread_info; | 201 mx_info_thread_t thread_info; |
202 mx_status_t status = | 202 mx_status_t status = |
203 mx_object_get_info(thread_handle, MX_INFO_THREAD, &thread_info, | 203 mx_object_get_info(thread_handle, MX_INFO_THREAD, &thread_info, |
204 sizeof(thread_info), NULL, NULL); | 204 sizeof(thread_info), NULL, NULL); |
205 poll_tries++; | 205 poll_tries++; |
206 if (status != NO_ERROR) { | 206 if (status != MX_OK) { |
207 if (FLAG_trace_thread_interrupter) { | 207 if (FLAG_trace_thread_interrupter) { |
208 OS::PrintErr("ThreadInterrupter: mx_object_get_info failed: %s\n", | 208 OS::PrintErr("ThreadInterrupter: mx_object_get_info failed: %s\n", |
209 mx_status_get_string(status)); | 209 mx_status_get_string(status)); |
210 } | 210 } |
211 return status; | 211 return status; |
212 } | 212 } |
213 if (thread_info.state == MX_THREAD_STATE_SUSPENDED) { | 213 if (thread_info.state == MX_THREAD_STATE_SUSPENDED) { |
214 // Success. | 214 // Success. |
215 return NO_ERROR; | 215 return MX_OK; |
216 } | 216 } |
217 if (thread_info.state == MX_THREAD_STATE_RUNNING) { | 217 if (thread_info.state == MX_THREAD_STATE_RUNNING) { |
218 // Poll. | 218 // Poll. |
219 continue; | 219 continue; |
220 } | 220 } |
221 if (FLAG_trace_thread_interrupter) { | 221 if (FLAG_trace_thread_interrupter) { |
222 OS::PrintErr("ThreadInterrupter: Thread is not suspended: %s\n", | 222 OS::PrintErr("ThreadInterrupter: Thread is not suspended: %s\n", |
223 ThreadStateGetString(thread_info.state)); | 223 ThreadStateGetString(thread_info.state)); |
224 } | 224 } |
225 return ERR_BAD_STATE; | 225 return MX_ERR_BAD_STATE; |
226 } | 226 } |
227 if (FLAG_trace_thread_interrupter) { | 227 if (FLAG_trace_thread_interrupter) { |
228 OS::PrintErr("ThreadInterrupter: Exceeded max suspend poll tries\n"); | 228 OS::PrintErr("ThreadInterrupter: Exceeded max suspend poll tries\n"); |
229 } | 229 } |
230 return ERR_BAD_STATE; | 230 return MX_ERR_BAD_STATE; |
231 } | 231 } |
232 }; | 232 }; |
233 | 233 |
234 | 234 |
235 bool ThreadInterrupter::IsDebuggerAttached() { | 235 bool ThreadInterrupter::IsDebuggerAttached() { |
236 return false; | 236 return false; |
237 } | 237 } |
238 | 238 |
239 | 239 |
240 void ThreadInterrupter::InterruptThread(OSThread* thread) { | 240 void ThreadInterrupter::InterruptThread(OSThread* thread) { |
(...skipping 16 matching lines...) Expand all Loading... |
257 | 257 |
258 void ThreadInterrupter::RemoveSignalHandler() { | 258 void ThreadInterrupter::RemoveSignalHandler() { |
259 // Nothing to do on Fuchsia. | 259 // Nothing to do on Fuchsia. |
260 } | 260 } |
261 | 261 |
262 #endif // !PRODUCT | 262 #endif // !PRODUCT |
263 | 263 |
264 } // namespace dart | 264 } // namespace dart |
265 | 265 |
266 #endif // defined(HOST_OS_FUCHSIA) | 266 #endif // defined(HOST_OS_FUCHSIA) |
OLD | NEW |