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

Side by Side Diff: runtime/vm/thread_interrupter_fuchsia.cc

Issue 2796143002: [Fuchsia] Implements the thread interrupter for CPU profiling. (Closed)
Patch Set: Format Created 3 years, 7 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/os_thread_fuchsia.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // TODO(MG-430): Currently, CPU profiling for Fuchsia is arranged very similarly
29 // to our Windows profiling. That is, the interrupter thread iterates over
30 // all threads, suspends them, samples various things, and then resumes them.
31 // When MG-430 is resolved, the code below should be rewritten to use whatever
32 // feature is added for it.
33
34 // TODO(zra): The profiler is currently off by default on Fuchsia because
35 // suspending a thread that is in a call to pthread_cond_wait() causes
36 // pthread_cond_wait() to return ETIMEDOUT.
37
38 class ThreadInterrupterFuchsia : public AllStatic {
39 public:
40 static bool GrabRegisters(mx_handle_t thread, InterruptedThreadState* state) {
41 // TODO(zra): Enable this when mx_thread_read_state() works on suspended
42 // threads.
43 while (false) {
44 char buf[MX_MAX_THREAD_STATE_SIZE];
45 uint32_t regset_size = MX_MAX_THREAD_STATE_SIZE;
46 mx_status_t status = mx_thread_read_state(
47 thread, MX_THREAD_STATE_REGSET0, &buf[0], regset_size, &regset_size);
48 if (status != NO_ERROR) {
49 OS::PrintErr("ThreadInterrupter failed to get registers: %s\n",
50 mx_status_get_string(status));
51 return false;
52 }
53 #if defined(TARGET_ARCH_X64)
54 mx_x86_64_general_regs_t* regs =
55 reinterpret_cast<mx_x86_64_general_regs_t*>(&buf[0]);
56 state->pc = static_cast<uintptr_t>(regs->rip);
57 state->fp = static_cast<uintptr_t>(regs->rbp);
58 state->csp = static_cast<uintptr_t>(regs->rsp);
59 state->dsp = static_cast<uintptr_t>(regs->rsp);
60 #elif defined(TARGET_ARCH_ARM64)
61 mx_aarch64_general_regs_t* regs =
62 reinterpret_cast<mx_aarch64_general_regs_t*>(&buf[0]);
63 state->pc = static_cast<uintptr_t>(regs->pc);
64 state->fp = static_cast<uintptr_t>(regs->r[FPREG]);
65 state->csp = static_cast<uintptr_t>(regs->sp);
66 state->dsp = static_cast<uintptr_t>(regs->r[SPREG]);
67 state->lr = static_cast<uintptr_t>(regs->lr);
68 #else
69 #error "Unsupported architecture"
70 #endif
71 }
72 return true;
73 }
74
75
76 static void Interrupt(OSThread* os_thread) {
77 ASSERT(!OSThread::Compare(OSThread::GetCurrentThreadId(), os_thread->id()));
78 mx_status_t status;
79
80 // Get a handle on the target thread.
81 mx_koid_t target_thread_koid = os_thread->id();
82 if (FLAG_trace_thread_interrupter) {
83 OS::Print("ThreadInterrupter: interrupting thread with koid=%d\n",
84 target_thread_koid);
85 }
86 mx_handle_t target_thread_handle;
87 status = mx_object_get_child(mx_process_self(), target_thread_koid,
88 MX_RIGHT_SAME_RIGHTS, &target_thread_handle);
89 if (status != NO_ERROR) {
90 if (FLAG_trace_thread_interrupter) {
91 OS::Print("ThreadInterrupter failed to get the thread handle: %s\n",
92 mx_status_get_string(status));
93 }
94 FATAL1("mx_object_get_child failed: %s", mx_status_get_string(status));
95 }
96 if (target_thread_handle == MX_HANDLE_INVALID) {
97 FATAL("ThreadInterrupter got an invalid target thread handle!");
98 }
99
100 // Pause the target thread.
101 status = mx_task_suspend(target_thread_handle);
102 if (status != NO_ERROR) {
103 if (FLAG_trace_thread_interrupter) {
104 OS::Print("ThreadInterrupter failed to suspend thread %ld: %s\n",
105 static_cast<intptr_t>(os_thread->id()),
106 mx_status_get_string(status));
107 }
108 mx_handle_close(target_thread_handle);
109 FATAL1("mx_task_suspend failed: %s", mx_status_get_string(status));
110 }
111
112 // TODO(zra): Enable this when mx_thread_read_state() works on suspended
113 // threads.
114 while (false) {
115 // Grab the target thread's registers.
116 InterruptedThreadState its;
117 if (!GrabRegisters(target_thread_handle, &its)) {
118 // Failed to get thread registers.
119 status = mx_task_resume(target_thread_handle, 0);
120 if (status != NO_ERROR) {
121 FATAL1("mx_task_resume failed: %s", mx_status_get_string(status));
122 }
123 mx_handle_close(target_thread_handle);
124 return;
125 }
126 // Currently we sample only threads that are associated
127 // with an isolate. It is safe to call 'os_thread->thread()'
128 // here as the thread which is being queried is suspended.
129 Thread* thread = os_thread->thread();
130 if (thread != NULL) {
131 Profiler::SampleThread(thread, its);
132 }
133 }
134
135 // Resume the target thread.
136 status = mx_task_resume(target_thread_handle, 0);
137 if (status != NO_ERROR) {
138 FATAL1("mx_task_resume failed: %s", mx_status_get_string(status));
139 }
140 mx_handle_close(target_thread_handle);
141 }
142 };
143
144
14 bool ThreadInterrupter::IsDebuggerAttached() { 145 bool ThreadInterrupter::IsDebuggerAttached() {
15 return false; 146 return false;
16 } 147 }
17 148
149
18 void ThreadInterrupter::InterruptThread(OSThread* thread) { 150 void ThreadInterrupter::InterruptThread(OSThread* thread) {
19 UNIMPLEMENTED(); 151 if (FLAG_trace_thread_interrupter) {
152 OS::Print("ThreadInterrupter suspending %p\n",
153 reinterpret_cast<void*>(thread->id()));
154 }
155 ThreadInterrupterFuchsia::Interrupt(thread);
156 if (FLAG_trace_thread_interrupter) {
157 OS::Print("ThreadInterrupter resuming %p\n",
158 reinterpret_cast<void*>(thread->id()));
159 }
20 } 160 }
21 161
22 162
23 void ThreadInterrupter::InstallSignalHandler() { 163 void ThreadInterrupter::InstallSignalHandler() {
24 UNIMPLEMENTED(); 164 // Nothing to do on Fuchsia.
25 } 165 }
26 166
27 167
28 void ThreadInterrupter::RemoveSignalHandler() { 168 void ThreadInterrupter::RemoveSignalHandler() {
29 UNIMPLEMENTED(); 169 // Nothing to do on Fuchsia.
30 } 170 }
31 171
172 #endif // !PRODUCT
173
32 } // namespace dart 174 } // namespace dart
33 175
34 #endif // defined(HOST_OS_FUCHSIA) 176 #endif // defined(HOST_OS_FUCHSIA)
OLDNEW
« no previous file with comments | « runtime/vm/os_thread_fuchsia.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698