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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
6 | 6 |
7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
8 #if defined(TARGET_OS_FUCHSIA) | 8 #if defined(TARGET_OS_FUCHSIA) |
9 | 9 |
10 #include "bin/eventhandler.h" | 10 #include "bin/eventhandler.h" |
11 #include "bin/eventhandler_fuchsia.h" | 11 #include "bin/eventhandler_fuchsia.h" |
12 | 12 |
13 #include <magenta/status.h> | 13 #include <magenta/status.h> |
14 #include <magenta/syscalls.h> | 14 #include <magenta/syscalls.h> |
15 | 15 |
| 16 #include "bin/log.h" |
16 #include "bin/thread.h" | 17 #include "bin/thread.h" |
17 #include "bin/utils.h" | 18 #include "bin/utils.h" |
18 | 19 |
| 20 #if defined(EVENTHANDLER_LOGGING) |
| 21 #define LOG_ERR(msg, ...) Log::PrintErr(msg, ##__VA_ARGS__) |
| 22 #define LOG_INFO(msg, ...) Log::Print(msg, ##__VA_ARGS__) |
| 23 #else |
| 24 #define LOG_ERR(msg, ...) |
| 25 #define LOG_INFO(msg, ...) |
| 26 #endif // defined(EVENTHANDLER_LOGGING) |
| 27 |
19 namespace dart { | 28 namespace dart { |
20 namespace bin { | 29 namespace bin { |
21 | 30 |
| 31 MagentaWaitManyInfo::MagentaWaitManyInfo() |
| 32 : capacity_(kInitialCapacity), |
| 33 size_(0) { |
| 34 descriptor_infos_ = static_cast<DescriptorInfo**>( |
| 35 malloc(kInitialCapacity * sizeof(*descriptor_infos_))); |
| 36 if (descriptor_infos_ == NULL) { |
| 37 FATAL("Failed to allocate descriptor_infos array"); |
| 38 } |
| 39 handles_ = static_cast<mx_handle_t*>( |
| 40 malloc(kInitialCapacity * sizeof(*handles_))); |
| 41 if (handles_ == NULL) { |
| 42 FATAL("Failed to allocate handles array"); |
| 43 } |
| 44 signals_ = static_cast<mx_signals_t*>( |
| 45 malloc(kInitialCapacity * sizeof(*signals_))); |
| 46 if (signals_ == NULL) { |
| 47 FATAL("Failed to allocate signals array"); |
| 48 } |
| 49 signals_states_ = static_cast<mx_signals_state_t*>( |
| 50 malloc(kInitialCapacity * sizeof(*signals_states_))); |
| 51 if (signals_states_ == NULL) { |
| 52 FATAL("Failed to allocate signals_states array"); |
| 53 } |
| 54 } |
| 55 |
| 56 |
| 57 MagentaWaitManyInfo::~MagentaWaitManyInfo() { |
| 58 free(descriptor_infos_); |
| 59 free(handles_); |
| 60 free(signals_); |
| 61 free(signals_states_); |
| 62 } |
| 63 |
| 64 |
| 65 void MagentaWaitManyInfo::AddHandle(mx_handle_t handle, |
| 66 mx_signals_t signals, |
| 67 DescriptorInfo* di) { |
| 68 #if defined(DEBUG) |
| 69 // Check that the handle is not already in the list. |
| 70 for (intptr_t i = 0; i < size_; i++) { |
| 71 if (handles_[i] == handle) { |
| 72 FATAL("The handle is already in the list!"); |
| 73 } |
| 74 } |
| 75 #endif |
| 76 intptr_t new_size = size_ + 1; |
| 77 GrowArraysIfNeeded(new_size); |
| 78 descriptor_infos_[size_] = di; |
| 79 handles_[size_] = handle; |
| 80 signals_[size_] = signals; |
| 81 signals_states_[size_].satisfied = MX_SIGNAL_NONE; |
| 82 signals_states_[size_].satisfiable = MX_SIGNAL_NONE; |
| 83 size_ = new_size; |
| 84 LOG_INFO("AddHandle(%ld, %ld, %p), size = %ld\n", handle, signals, di, size_); |
| 85 } |
| 86 |
| 87 |
| 88 void MagentaWaitManyInfo::RemoveHandle(mx_handle_t handle) { |
| 89 intptr_t idx; |
| 90 for (idx = 1; idx < size_; idx++) { |
| 91 if (handle == handles_[idx]) { |
| 92 break; |
| 93 } |
| 94 } |
| 95 if (idx == size_) { |
| 96 FATAL("Handle is not in the list!"); |
| 97 } |
| 98 |
| 99 if (idx != (size_ - 1)) { |
| 100 descriptor_infos_[idx] = descriptor_infos_[size_ - 1]; |
| 101 handles_[idx] = handles_[size_ - 1]; |
| 102 signals_[idx] = signals_[size_ - 1]; |
| 103 signals_states_[idx] = signals_states_[size_ - 1]; |
| 104 } |
| 105 descriptor_infos_[size_ - 1] = NULL; |
| 106 handles_[size_ - 1] = MX_HANDLE_INVALID; |
| 107 signals_[size_ - 1] = MX_SIGNAL_NONE; |
| 108 signals_states_[size_ - 1].satisfied = MX_SIGNAL_NONE; |
| 109 signals_states_[size_ - 1].satisfiable = MX_SIGNAL_NONE; |
| 110 size_ = size_ - 1; |
| 111 LOG_INFO("RemoveHandle(%ld), size = %ld\n", handle, size_); |
| 112 } |
| 113 |
| 114 |
| 115 void MagentaWaitManyInfo::GrowArraysIfNeeded(intptr_t desired_size) { |
| 116 if (desired_size < capacity_) { |
| 117 return; |
| 118 } |
| 119 intptr_t new_capacity = desired_size + (desired_size >> 1); |
| 120 descriptor_infos_ = static_cast<DescriptorInfo**>( |
| 121 realloc(descriptor_infos_, new_capacity * sizeof(*descriptor_infos_))); |
| 122 if (descriptor_infos_ == NULL) { |
| 123 FATAL("Failed to grow descriptor_infos array"); |
| 124 } |
| 125 handles_ = static_cast<mx_handle_t*>( |
| 126 realloc(handles_, new_capacity * sizeof(*handles_))); |
| 127 if (handles_ == NULL) { |
| 128 FATAL("Failed to grow handles array"); |
| 129 } |
| 130 signals_ = static_cast<mx_signals_t*>( |
| 131 realloc(signals_, new_capacity * sizeof(*signals_))); |
| 132 if (signals_ == NULL) { |
| 133 FATAL("Failed to grow signals array"); |
| 134 } |
| 135 signals_states_ = static_cast<mx_signals_state_t*>( |
| 136 realloc(signals_states_, new_capacity * sizeof(*signals_states_))); |
| 137 if (signals_states_ == NULL) { |
| 138 FATAL("Failed to grow signals_states array"); |
| 139 } |
| 140 capacity_ = new_capacity; |
| 141 LOG_INFO("GrowArraysIfNeeded(%ld), capacity = %ld\n", |
| 142 desired_size, capacity_); |
| 143 } |
| 144 |
| 145 |
22 EventHandlerImplementation::EventHandlerImplementation() { | 146 EventHandlerImplementation::EventHandlerImplementation() { |
23 mx_status_t status = mx_msgpipe_create(interrupt_handles_, 0); | 147 mx_status_t status = mx_msgpipe_create(interrupt_handles_, 0); |
24 if (status != NO_ERROR) { | 148 if (status != NO_ERROR) { |
25 FATAL1("mx_msgpipe_create failed: %s\n", mx_status_get_string(status)); | 149 FATAL1("mx_msgpipe_create failed: %s\n", mx_status_get_string(status)); |
26 } | 150 } |
27 shutdown_ = false; | 151 shutdown_ = false; |
| 152 info_.AddHandle(interrupt_handles_[0], |
| 153 MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, |
| 154 NULL); |
| 155 LOG_INFO("EventHandlerImplementation initialized\n"); |
28 } | 156 } |
29 | 157 |
30 | 158 |
31 EventHandlerImplementation::~EventHandlerImplementation() { | 159 EventHandlerImplementation::~EventHandlerImplementation() { |
32 mx_status_t status = mx_handle_close(interrupt_handles_[0]); | 160 mx_status_t status = mx_handle_close(interrupt_handles_[0]); |
33 if (status != NO_ERROR) { | 161 if (status != NO_ERROR) { |
34 FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status)); | 162 FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status)); |
35 } | 163 } |
36 status = mx_handle_close(interrupt_handles_[1]); | 164 status = mx_handle_close(interrupt_handles_[1]); |
37 if (status != NO_ERROR) { | 165 if (status != NO_ERROR) { |
38 FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status)); | 166 FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status)); |
39 } | 167 } |
| 168 LOG_INFO("EventHandlerImplementation destroyed\n"); |
40 } | 169 } |
41 | 170 |
42 | 171 |
43 void EventHandlerImplementation::WakeupHandler(intptr_t id, | 172 void EventHandlerImplementation::WakeupHandler(intptr_t id, |
44 Dart_Port dart_port, | 173 Dart_Port dart_port, |
45 int64_t data) { | 174 int64_t data) { |
46 InterruptMessage msg; | 175 InterruptMessage msg; |
47 msg.id = id; | 176 msg.id = id; |
48 msg.dart_port = dart_port; | 177 msg.dart_port = dart_port; |
49 msg.data = data; | 178 msg.data = data; |
50 | 179 |
51 mx_status_t status = | 180 mx_status_t status = |
52 mx_msgpipe_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0); | 181 mx_msgpipe_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0); |
53 if (status != NO_ERROR) { | 182 if (status != NO_ERROR) { |
54 FATAL1("mx_msgpipe_write failed: %s\n", mx_status_get_string(status)); | 183 FATAL1("mx_msgpipe_write failed: %s\n", mx_status_get_string(status)); |
55 } | 184 } |
| 185 LOG_INFO("WakeupHandler(%ld, %ld, %lld)\n", id, dart_port, data); |
56 } | 186 } |
57 | 187 |
58 | 188 |
59 void EventHandlerImplementation::HandleInterruptFd() { | 189 void EventHandlerImplementation::HandleInterruptFd() { |
| 190 LOG_INFO("HandleInterruptFd entry\n"); |
60 InterruptMessage msg; | 191 InterruptMessage msg; |
61 uint32_t bytes = kInterruptMessageSize; | 192 uint32_t bytes = kInterruptMessageSize; |
62 mx_status_t status; | 193 mx_status_t status; |
63 while (true) { | 194 while (true) { |
64 status = mx_msgpipe_read( | 195 status = mx_msgpipe_read( |
65 interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0); | 196 interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0); |
66 if (status != NO_ERROR) { | 197 if (status != NO_ERROR) { |
67 break; | 198 break; |
68 } | 199 } |
69 ASSERT(bytes == kInterruptMessageSize); | 200 ASSERT(bytes == kInterruptMessageSize); |
70 if (msg.id == kTimerId) { | 201 if (msg.id == kTimerId) { |
| 202 LOG_INFO("HandleInterruptFd read timer update\n"); |
71 timeout_queue_.UpdateTimeout(msg.dart_port, msg.data); | 203 timeout_queue_.UpdateTimeout(msg.dart_port, msg.data); |
72 } else if (msg.id == kShutdownId) { | 204 } else if (msg.id == kShutdownId) { |
| 205 LOG_INFO("HandleInterruptFd read shutdown\n"); |
73 shutdown_ = true; | 206 shutdown_ = true; |
74 } else { | 207 } else { |
| 208 // TODO(zra): Handle commands to add and remove handles from the |
| 209 // MagentaWaitManyInfo. |
75 UNIMPLEMENTED(); | 210 UNIMPLEMENTED(); |
76 } | 211 } |
77 } | 212 } |
78 // status == ERR_SHOULD_WAIT when we try to read and there are no messages | 213 // status == ERR_SHOULD_WAIT when we try to read and there are no messages |
79 // available, so it is an error if we get here and status != ERR_SHOULD_WAIT. | 214 // available, so it is an error if we get here and status != ERR_SHOULD_WAIT. |
80 if (status != ERR_SHOULD_WAIT) { | 215 if (status != ERR_SHOULD_WAIT) { |
81 FATAL1("mx_msgpipe_read failed: %s\n", mx_status_get_string(status)); | 216 FATAL1("mx_msgpipe_read failed: %s\n", mx_status_get_string(status)); |
82 } | 217 } |
| 218 LOG_INFO("HandleInterruptFd exit\n"); |
| 219 } |
| 220 |
| 221 |
| 222 void EventHandlerImplementation::HandleEvents() { |
| 223 LOG_INFO("HandleEvents entry\n"); |
| 224 for (intptr_t i = 1; i < info_.size(); i++) { |
| 225 if (info_.signals_states()[i].satisfied != MX_SIGNAL_NONE) { |
| 226 // Only the control handle has no descriptor info. |
| 227 ASSERT(info_.descriptor_infos()[i] != NULL); |
| 228 ASSERT(info_.handles()[i] != interrupt_handles_[0]); |
| 229 // TODO(zra): Handle events on other handles. At the moment we are |
| 230 // only interrupted when there is a message on interrupt_handles_[0]. |
| 231 UNIMPLEMENTED(); |
| 232 } |
| 233 } |
| 234 |
| 235 if ((info_.signals_states()[0].satisfied & MX_SIGNAL_PEER_CLOSED) != 0) { |
| 236 FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n"); |
| 237 } |
| 238 if ((info_.signals_states()[0].satisfied & MX_SIGNAL_READABLE) != 0) { |
| 239 LOG_INFO("HandleEvents interrupt_handles_[0] readable\n"); |
| 240 HandleInterruptFd(); |
| 241 } else { |
| 242 LOG_INFO("HandleEvents interrupt_handles_[0] not readable\n"); |
| 243 } |
83 } | 244 } |
84 | 245 |
85 | 246 |
86 void EventHandlerImplementation::HandleEvents() { | |
87 // TODO(zra): Handle events from other handles. At the moment we are only | |
88 // interrupted when there is a message on interrupt_handles_[0]. | |
89 HandleInterruptFd(); | |
90 } | |
91 | |
92 | |
93 int64_t EventHandlerImplementation::GetTimeout() const { | 247 int64_t EventHandlerImplementation::GetTimeout() const { |
94 if (!timeout_queue_.HasTimeout()) { | 248 if (!timeout_queue_.HasTimeout()) { |
95 return kInfinityTimeout; | 249 return kInfinityTimeout; |
96 } | 250 } |
97 int64_t millis = timeout_queue_.CurrentTimeout() - | 251 int64_t millis = timeout_queue_.CurrentTimeout() - |
98 TimerUtils::GetCurrentMonotonicMillis(); | 252 TimerUtils::GetCurrentMonotonicMillis(); |
99 return (millis < 0) ? 0 : millis; | 253 return (millis < 0) ? 0 : millis; |
100 } | 254 } |
101 | 255 |
102 | 256 |
(...skipping 10 matching lines...) Expand all Loading... |
113 | 267 |
114 | 268 |
115 void EventHandlerImplementation::Poll(uword args) { | 269 void EventHandlerImplementation::Poll(uword args) { |
116 EventHandler* handler = reinterpret_cast<EventHandler*>(args); | 270 EventHandler* handler = reinterpret_cast<EventHandler*>(args); |
117 EventHandlerImplementation* handler_impl = &handler->delegate_; | 271 EventHandlerImplementation* handler_impl = &handler->delegate_; |
118 ASSERT(handler_impl != NULL); | 272 ASSERT(handler_impl != NULL); |
119 | 273 |
120 while (!handler_impl->shutdown_) { | 274 while (!handler_impl->shutdown_) { |
121 int64_t millis = handler_impl->GetTimeout(); | 275 int64_t millis = handler_impl->GetTimeout(); |
122 ASSERT((millis == kInfinityTimeout) || (millis >= 0)); | 276 ASSERT((millis == kInfinityTimeout) || (millis >= 0)); |
123 | |
124 mx_time_t timeout = | 277 mx_time_t timeout = |
125 millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond; | 278 millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond; |
126 mx_signals_state_t signals_state; | 279 const MagentaWaitManyInfo& info = handler_impl->info(); |
127 mx_status_t status = mx_handle_wait_one( | 280 uint32_t result_index; |
128 handler_impl->interrupt_handles_[0], | 281 LOG_INFO("mx_handle_wait_many(%ld, %p, %p, %lld, %p, %p)\n", |
129 MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, | 282 info.size(), info.handles(), info.signals(), timeout, &result_index, |
| 283 info.signals_states()); |
| 284 mx_status_t status = mx_handle_wait_many( |
| 285 info.size(), |
| 286 info.handles(), |
| 287 info.signals(), |
130 timeout, | 288 timeout, |
131 &signals_state); | 289 &result_index, |
| 290 info.signals_states()); |
132 if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) { | 291 if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) { |
133 FATAL1("mx_handle_wait_one failed: %s\n", mx_status_get_string(status)); | 292 FATAL1("mx_handle_wait_many failed: %s\n", mx_status_get_string(status)); |
134 } else { | 293 } else { |
| 294 LOG_INFO("mx_handle_wait_many returned: %ld\n", status); |
135 handler_impl->HandleTimeout(); | 295 handler_impl->HandleTimeout(); |
136 if ((signals_state.satisfied & MX_SIGNAL_READABLE) != 0) { | 296 handler_impl->HandleEvents(); |
137 handler_impl->HandleEvents(); | |
138 } | |
139 if ((signals_state.satisfied & MX_SIGNAL_PEER_CLOSED) != 0) { | |
140 FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n"); | |
141 } | |
142 } | 297 } |
143 } | 298 } |
144 handler->NotifyShutdownDone(); | 299 handler->NotifyShutdownDone(); |
| 300 LOG_INFO("EventHandlerImplementation notifying about shutdown\n"); |
145 } | 301 } |
146 | 302 |
147 | 303 |
148 void EventHandlerImplementation::Start(EventHandler* handler) { | 304 void EventHandlerImplementation::Start(EventHandler* handler) { |
149 int result = Thread::Start(&EventHandlerImplementation::Poll, | 305 int result = Thread::Start(&EventHandlerImplementation::Poll, |
150 reinterpret_cast<uword>(handler)); | 306 reinterpret_cast<uword>(handler)); |
151 if (result != 0) { | 307 if (result != 0) { |
152 FATAL1("Failed to start event handler thread %d", result); | 308 FATAL1("Failed to start event handler thread %d", result); |
153 } | 309 } |
154 } | 310 } |
155 | 311 |
156 | 312 |
157 void EventHandlerImplementation::Shutdown() { | 313 void EventHandlerImplementation::Shutdown() { |
158 SendData(kShutdownId, 0, 0); | 314 SendData(kShutdownId, 0, 0); |
159 } | 315 } |
160 | 316 |
161 | 317 |
162 void EventHandlerImplementation::SendData(intptr_t id, | 318 void EventHandlerImplementation::SendData(intptr_t id, |
163 Dart_Port dart_port, | 319 Dart_Port dart_port, |
164 int64_t data) { | 320 int64_t data) { |
165 WakeupHandler(id, dart_port, data); | 321 WakeupHandler(id, dart_port, data); |
166 } | 322 } |
167 | 323 |
168 } // namespace bin | 324 } // namespace bin |
169 } // namespace dart | 325 } // namespace dart |
170 | 326 |
171 #endif // defined(TARGET_OS_FUCHSIA) | 327 #endif // defined(TARGET_OS_FUCHSIA) |
172 | 328 |
173 #endif // !defined(DART_IO_DISABLED) | 329 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |