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 } | |
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
| |
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 |