OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #if !defined(DART_IO_DISABLED) |
| 6 |
| 7 #include "platform/globals.h" |
| 8 #if defined(TARGET_OS_FUCHSIA) |
| 9 |
| 10 #include "bin/eventhandler.h" |
| 11 #include "bin/eventhandler_fuchsia.h" |
| 12 |
| 13 #include <magenta/syscalls.h> |
| 14 #include <runtime/status.h> |
| 15 |
| 16 #include "bin/thread.h" |
| 17 #include "bin/utils.h" |
| 18 |
| 19 namespace dart { |
| 20 namespace bin { |
| 21 |
| 22 EventHandlerImplementation::EventHandlerImplementation() { |
| 23 mx_status_t status = mx_message_pipe_create(interrupt_handles_, 0); |
| 24 if (status != NO_ERROR) { |
| 25 FATAL1("mx_message_pipe_create failed: %s\n", mx_strstatus(status)); |
| 26 } |
| 27 } |
| 28 |
| 29 |
| 30 EventHandlerImplementation::~EventHandlerImplementation() { |
| 31 mx_status_t status = mx_handle_close(interrupt_handles_[0]); |
| 32 if (status != NO_ERROR) { |
| 33 FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status)); |
| 34 } |
| 35 status = mx_handle_close(interrupt_handles_[1]); |
| 36 if (status != NO_ERROR) { |
| 37 FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status)); |
| 38 } |
| 39 } |
| 40 |
| 41 |
| 42 void EventHandlerImplementation::WakeupHandler(intptr_t id, |
| 43 Dart_Port dart_port, |
| 44 int64_t data) { |
| 45 InterruptMessage msg; |
| 46 msg.id = id; |
| 47 msg.dart_port = dart_port; |
| 48 msg.data = data; |
| 49 |
| 50 mx_status_t status = |
| 51 mx_message_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0); |
| 52 if (status != NO_ERROR) { |
| 53 FATAL1("mx_message_write failed: %s\n", mx_strstatus(status)); |
| 54 } |
| 55 } |
| 56 |
| 57 |
| 58 void EventHandlerImplementation::HandleInterruptFd() { |
| 59 InterruptMessage msg; |
| 60 uint32_t bytes = kInterruptMessageSize; |
| 61 mx_status_t status; |
| 62 while (true) { |
| 63 status = mx_message_read( |
| 64 interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0); |
| 65 if (status != NO_ERROR) { |
| 66 break; |
| 67 } |
| 68 ASSERT(bytes == kInterruptMessageSize); |
| 69 if (msg.id == kTimerId) { |
| 70 timeout_queue_.UpdateTimeout(msg.dart_port, msg.data); |
| 71 } else if (msg.id == kShutdownId) { |
| 72 shutdown_ = true; |
| 73 } else { |
| 74 UNIMPLEMENTED(); |
| 75 } |
| 76 } |
| 77 if (status != ERR_BAD_STATE) { |
| 78 FATAL1("mx_message_read failed: %s\n", mx_strstatus(status)); |
| 79 } |
| 80 } |
| 81 |
| 82 |
| 83 void EventHandlerImplementation::HandleEvents() { |
| 84 // TODO(zra): Handle events from other handles. At the moment we are only |
| 85 // interrupted when there is a message on interrupt_handles_[0]. |
| 86 HandleInterruptFd(); |
| 87 } |
| 88 |
| 89 |
| 90 int64_t EventHandlerImplementation::GetTimeout() { |
| 91 if (!timeout_queue_.HasTimeout()) { |
| 92 return kInfinityTimeout; |
| 93 } |
| 94 int64_t millis = timeout_queue_.CurrentTimeout() - |
| 95 TimerUtils::GetCurrentMonotonicMillis(); |
| 96 return (millis < 0) ? 0 : millis; |
| 97 } |
| 98 |
| 99 |
| 100 void EventHandlerImplementation::HandleTimeout() { |
| 101 if (timeout_queue_.HasTimeout()) { |
| 102 int64_t millis = timeout_queue_.CurrentTimeout() - |
| 103 TimerUtils::GetCurrentMonotonicMillis(); |
| 104 if (millis <= 0) { |
| 105 DartUtils::PostNull(timeout_queue_.CurrentPort()); |
| 106 timeout_queue_.RemoveCurrent(); |
| 107 } |
| 108 } |
| 109 } |
| 110 |
| 111 |
| 112 void EventHandlerImplementation::Poll(uword args) { |
| 113 EventHandler* handler = reinterpret_cast<EventHandler*>(args); |
| 114 EventHandlerImplementation* handler_impl = &handler->delegate_; |
| 115 ASSERT(handler_impl != NULL); |
| 116 |
| 117 while (!handler_impl->shutdown_) { |
| 118 int64_t millis = handler_impl->GetTimeout(); |
| 119 ASSERT((millis == kInfinityTimeout) || (millis >= 0)); |
| 120 |
| 121 mx_time_t timeout = |
| 122 millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond; |
| 123 mx_signals_state_t signals_state; |
| 124 mx_status_t status = mx_handle_wait_one( |
| 125 handler_impl->interrupt_handles_[0], |
| 126 MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, |
| 127 timeout, |
| 128 &signals_state); |
| 129 if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) { |
| 130 FATAL1("mx_handle_wait_one failed: %s\n", mx_strstatus(status)); |
| 131 } else { |
| 132 handler_impl->HandleTimeout(); |
| 133 if ((signals_state.satisfied & MX_SIGNAL_READABLE) != 0) { |
| 134 handler_impl->HandleEvents(); |
| 135 } |
| 136 if ((signals_state.satisfied & MX_SIGNAL_PEER_CLOSED) != 0) { |
| 137 FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n"); |
| 138 } |
| 139 } |
| 140 } |
| 141 handler->NotifyShutdownDone(); |
| 142 } |
| 143 |
| 144 |
| 145 void EventHandlerImplementation::Start(EventHandler* handler) { |
| 146 int result = Thread::Start(&EventHandlerImplementation::Poll, |
| 147 reinterpret_cast<uword>(handler)); |
| 148 if (result != 0) { |
| 149 FATAL1("Failed to start event handler thread %d", result); |
| 150 } |
| 151 } |
| 152 |
| 153 |
| 154 void EventHandlerImplementation::Shutdown() { |
| 155 SendData(kShutdownId, 0, 0); |
| 156 } |
| 157 |
| 158 |
| 159 void EventHandlerImplementation::SendData(intptr_t id, |
| 160 Dart_Port dart_port, |
| 161 int64_t data) { |
| 162 WakeupHandler(id, dart_port, data); |
| 163 } |
| 164 |
| 165 } // namespace bin |
| 166 } // namespace dart |
| 167 |
| 168 #endif // defined(TARGET_OS_FUCHSIA) |
| 169 |
| 170 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |