Chromium Code Reviews| Index: runtime/bin/eventhandler_fuchsia.cc |
| diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0cdd868112ebd7c9756762518520effc2681d937 |
| --- /dev/null |
| +++ b/runtime/bin/eventhandler_fuchsia.cc |
| @@ -0,0 +1,170 @@ |
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +#if !defined(DART_IO_DISABLED) |
| + |
| +#include "platform/globals.h" |
| +#if defined(TARGET_OS_FUCHSIA) |
| + |
| +#include "bin/eventhandler.h" |
| +#include "bin/eventhandler_fuchsia.h" |
| + |
| +#include <magenta/syscalls.h> |
| +#include <runtime/status.h> |
| + |
| +#include "bin/thread.h" |
| +#include "bin/utils.h" |
| + |
| +namespace dart { |
| +namespace bin { |
| + |
| +EventHandlerImplementation::EventHandlerImplementation() { |
| + mx_status_t status = mx_message_pipe_create(interrupt_handles_, 0); |
| + if (status != NO_ERROR) { |
| + FATAL1("mx_message_pipe_create failed: %s\n", mx_strstatus(status)); |
| + } |
| +} |
| + |
| + |
| +EventHandlerImplementation::~EventHandlerImplementation() { |
| + mx_status_t status = mx_handle_close(interrupt_handles_[0]); |
| + if (status != NO_ERROR) { |
| + FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status)); |
| + } |
| + status = mx_handle_close(interrupt_handles_[1]); |
| + if (status != NO_ERROR) { |
| + FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status)); |
| + } |
| +} |
| + |
| + |
| +void EventHandlerImplementation::WakeupHandler(intptr_t id, |
| + Dart_Port dart_port, |
| + int64_t data) { |
| + InterruptMessage msg; |
| + msg.id = id; |
| + msg.dart_port = dart_port; |
| + msg.data = data; |
| + |
| + mx_status_t status = |
| + mx_message_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0); |
| + if (status != NO_ERROR) { |
| + FATAL1("mx_message_write failed: %s\n", mx_strstatus(status)); |
| + } |
| +} |
| + |
| + |
| +void EventHandlerImplementation::HandleInterruptFd() { |
| + InterruptMessage msg; |
| + uint32_t bytes = kInterruptMessageSize; |
| + mx_status_t status; |
| + while (true) { |
| + status = mx_message_read( |
| + interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0); |
| + if (status != NO_ERROR) { |
| + break; |
| + } |
| + ASSERT(bytes == kInterruptMessageSize); |
| + if (msg.id == kTimerId) { |
| + timeout_queue_.UpdateTimeout(msg.dart_port, msg.data); |
| + } else if (msg.id == kShutdownId) { |
| + shutdown_ = true; |
| + } else { |
| + UNIMPLEMENTED(); |
| + } |
| + } |
| + if (status != ERR_BAD_STATE) { |
| + FATAL1("mx_message_read failed: %s\n", mx_strstatus(status)); |
| + } |
|
siva
2016/07/22 19:18:22
for status == ERR_BAD_STATE we seem to do nothing,
zra
2016/07/22 20:07:08
status should be ERR_BAD_STATE when we try to read
|
| +} |
| + |
| + |
| +void EventHandlerImplementation::HandleEvents() { |
| + // TODO(zra): Handle events from other handles. At the moment we are only |
| + // interrupted when there is a message on interrupt_handles_[0]. |
| + HandleInterruptFd(); |
| +} |
| + |
| + |
| +int64_t EventHandlerImplementation::GetTimeout() { |
| + if (!timeout_queue_.HasTimeout()) { |
| + return kInfinityTimeout; |
| + } |
| + int64_t millis = timeout_queue_.CurrentTimeout() - |
| + TimerUtils::GetCurrentMonotonicMillis(); |
| + return (millis < 0) ? 0 : millis; |
| +} |
| + |
| + |
| +void EventHandlerImplementation::HandleTimeout() { |
| + if (timeout_queue_.HasTimeout()) { |
| + int64_t millis = timeout_queue_.CurrentTimeout() - |
| + TimerUtils::GetCurrentMonotonicMillis(); |
| + if (millis <= 0) { |
| + DartUtils::PostNull(timeout_queue_.CurrentPort()); |
| + timeout_queue_.RemoveCurrent(); |
| + } |
| + } |
| +} |
| + |
| + |
| +void EventHandlerImplementation::Poll(uword args) { |
| + EventHandler* handler = reinterpret_cast<EventHandler*>(args); |
| + EventHandlerImplementation* handler_impl = &handler->delegate_; |
| + ASSERT(handler_impl != NULL); |
| + |
| + while (!handler_impl->shutdown_) { |
| + int64_t millis = handler_impl->GetTimeout(); |
| + ASSERT((millis == kInfinityTimeout) || (millis >= 0)); |
| + |
| + mx_time_t timeout = |
| + millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond; |
| + mx_signals_state_t signals_state; |
| + mx_status_t status = mx_handle_wait_one( |
| + handler_impl->interrupt_handles_[0], |
| + MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, |
| + timeout, |
| + &signals_state); |
| + if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) { |
| + FATAL1("mx_handle_wait_one failed: %s\n", mx_strstatus(status)); |
| + } else { |
| + handler_impl->HandleTimeout(); |
| + if ((signals_state.satisfied & MX_SIGNAL_READABLE) != 0) { |
| + handler_impl->HandleEvents(); |
| + } |
| + if ((signals_state.satisfied & MX_SIGNAL_PEER_CLOSED) != 0) { |
| + FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n"); |
| + } |
| + } |
| + } |
| + handler->NotifyShutdownDone(); |
| +} |
| + |
| + |
| +void EventHandlerImplementation::Start(EventHandler* handler) { |
| + int result = Thread::Start(&EventHandlerImplementation::Poll, |
| + reinterpret_cast<uword>(handler)); |
| + if (result != 0) { |
| + FATAL1("Failed to start event handler thread %d", result); |
| + } |
| +} |
| + |
| + |
| +void EventHandlerImplementation::Shutdown() { |
| + SendData(kShutdownId, 0, 0); |
| +} |
| + |
| + |
| +void EventHandlerImplementation::SendData(intptr_t id, |
| + Dart_Port dart_port, |
| + int64_t data) { |
| + WakeupHandler(id, dart_port, data); |
| +} |
| + |
| +} // namespace bin |
| +} // namespace dart |
| + |
| +#endif // defined(TARGET_OS_FUCHSIA) |
| + |
| +#endif // !defined(DART_IO_DISABLED) |