OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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(TARGET_OS_ANDROID) | 6 #if defined(TARGET_OS_ANDROID) |
7 | 7 |
8 #include "bin/eventhandler.h" | 8 #include "bin/eventhandler.h" |
9 #include "bin/eventhandler_android.h" | |
10 | 9 |
11 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
12 #include <pthread.h> // NOLINT | 11 #include <pthread.h> // NOLINT |
13 #include <stdio.h> // NOLINT | 12 #include <stdio.h> // NOLINT |
14 #include <string.h> // NOLINT | 13 #include <string.h> // NOLINT |
15 #include <sys/epoll.h> // NOLINT | 14 #include <sys/epoll.h> // NOLINT |
16 #include <sys/stat.h> // NOLINT | 15 #include <sys/stat.h> // NOLINT |
17 #include <unistd.h> // NOLINT | 16 #include <unistd.h> // NOLINT |
18 #include <fcntl.h> // NOLINT | 17 #include <fcntl.h> // NOLINT |
19 | 18 |
20 #include "bin/dartutils.h" | 19 #include "bin/dartutils.h" |
21 #include "bin/fdutils.h" | 20 #include "bin/fdutils.h" |
22 #include "bin/log.h" | 21 #include "bin/log.h" |
23 #include "bin/lockers.h" | |
24 #include "bin/socket.h" | |
25 #include "bin/thread.h" | 22 #include "bin/thread.h" |
26 #include "bin/utils.h" | 23 #include "bin/utils.h" |
27 #include "platform/hashmap.h" | 24 #include "platform/hashmap.h" |
28 #include "platform/utils.h" | 25 #include "platform/utils.h" |
29 | 26 |
30 | 27 |
31 // Android doesn't define EPOLLRDHUP. | 28 // Android doesn't define EPOLLRDHUP. |
32 #if !defined(EPOLLRDHUP) | 29 #if !defined(EPOLLRDHUP) |
33 #define EPOLLRDHUP 0x2000 | 30 #define EPOLLRDHUP 0x2000 |
34 #endif // !defined(EPOLLRDHUP) | 31 #endif // !defined(EPOLLRDHUP) |
35 | 32 |
36 | 33 |
37 namespace dart { | 34 namespace dart { |
38 namespace bin { | 35 namespace bin { |
39 | 36 |
| 37 static const int kInterruptMessageSize = sizeof(InterruptMessage); |
| 38 static const int kInfinityTimeout = -1; |
| 39 static const int kTimerId = -1; |
| 40 static const int kShutdownId = -2; |
40 | 41 |
41 intptr_t DescriptorInfo::GetPollEvents() { | 42 |
| 43 intptr_t SocketData::GetPollEvents() { |
42 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are | 44 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are |
43 // triggered anyway. | 45 // triggered anyway. |
44 intptr_t events = 0; | 46 intptr_t events = 0; |
45 if ((Mask() & (1 << kInEvent)) != 0) { | 47 if ((mask_ & (1 << kInEvent)) != 0) { |
46 events |= EPOLLIN; | 48 events |= EPOLLIN; |
47 } | 49 } |
48 if ((Mask() & (1 << kOutEvent)) != 0) { | 50 if ((mask_ & (1 << kOutEvent)) != 0) { |
49 events |= EPOLLOUT; | 51 events |= EPOLLOUT; |
50 } | 52 } |
51 return events; | 53 return events; |
52 } | 54 } |
53 | 55 |
54 | 56 |
55 // Unregister the file descriptor for a DescriptorInfo structure with | 57 // Unregister the file descriptor for a SocketData structure with epoll. |
56 // epoll. | 58 static void RemoveFromEpollInstance(intptr_t epoll_fd_, SocketData* sd) { |
57 static void RemoveFromEpollInstance(intptr_t epoll_fd_, | |
58 DescriptorInfo* di) { | |
59 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | 59 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, |
60 EPOLL_CTL_DEL, | 60 EPOLL_CTL_DEL, |
61 di->fd(), | 61 sd->fd(), |
62 NULL)); | 62 NULL)); |
63 } | 63 } |
64 | 64 |
65 | 65 |
66 static void AddToEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) { | 66 static void AddToEpollInstance(intptr_t epoll_fd_, SocketData* sd) { |
67 struct epoll_event event; | 67 struct epoll_event event; |
68 event.events = EPOLLRDHUP | di->GetPollEvents(); | 68 event.events = EPOLLRDHUP | sd->GetPollEvents(); |
69 if (!di->IsListeningSocket()) { | 69 if (!sd->IsListeningSocket()) { |
70 event.events |= EPOLLET; | 70 event.events |= EPOLLET; |
71 } | 71 } |
72 event.data.ptr = di; | 72 event.data.ptr = sd; |
73 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | 73 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, |
74 EPOLL_CTL_ADD, | 74 EPOLL_CTL_ADD, |
75 di->fd(), | 75 sd->fd(), |
76 &event)); | 76 &event)); |
77 if (status == -1) { | 77 if (status == -1) { |
78 // TODO(kustermann): Verify that the dart end is handling this correctly & | |
79 // adapt this code to work for multiple listening sockets. | |
80 | |
81 // Epoll does not accept the file descriptor. It could be due to | 78 // Epoll does not accept the file descriptor. It could be due to |
82 // already closed file descriptor, or unuspported devices, such | 79 // already closed file descriptor, or unuspported devices, such |
83 // as /dev/null. In such case, mark the file descriptor as closed, | 80 // as /dev/null. In such case, mark the file descriptor as closed, |
84 // so dart will handle it accordingly. | 81 // so dart will handle it accordingly. |
85 DartUtils::PostInt32(di->NextPort(), 1 << kCloseEvent); | 82 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); |
86 } | 83 } |
87 } | 84 } |
88 | 85 |
89 | 86 |
90 EventHandlerImplementation::EventHandlerImplementation() | 87 EventHandlerImplementation::EventHandlerImplementation() |
91 : socket_map_(&HashMap::SamePointerValue, 16) { | 88 : socket_map_(&HashMap::SamePointerValue, 16) { |
92 intptr_t result; | 89 intptr_t result; |
93 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); | 90 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); |
94 if (result != 0) { | 91 if (result != 0) { |
95 FATAL("Pipe creation failed"); | 92 FATAL("Pipe creation failed"); |
96 } | 93 } |
97 FDUtils::SetNonBlocking(interrupt_fds_[0]); | 94 FDUtils::SetNonBlocking(interrupt_fds_[0]); |
98 FDUtils::SetCloseOnExec(interrupt_fds_[0]); | 95 FDUtils::SetCloseOnExec(interrupt_fds_[0]); |
99 FDUtils::SetCloseOnExec(interrupt_fds_[1]); | 96 FDUtils::SetCloseOnExec(interrupt_fds_[1]); |
100 shutdown_ = false; | 97 shutdown_ = false; |
101 // The initial size passed to epoll_create is ignore on newer (>= | 98 // The initial size passed to epoll_create is ignore on newer (>= |
102 // 2.6.8) Linux versions | 99 // 2.6.8) Linux versions |
103 static const int kEpollInitialSize = 64; | 100 static const int kEpollInitialSize = 64; |
104 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); | 101 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); |
105 if (epoll_fd_ == -1) { | 102 if (epoll_fd_ == -1) { |
106 FATAL1("Failed creating epoll file descriptor: %i", errno); | 103 FATAL("Failed creating epoll file descriptor"); |
107 } | 104 } |
108 FDUtils::SetCloseOnExec(epoll_fd_); | 105 FDUtils::SetCloseOnExec(epoll_fd_); |
109 // Register the interrupt_fd with the epoll instance. | 106 // Register the interrupt_fd with the epoll instance. |
110 struct epoll_event event; | 107 struct epoll_event event; |
111 event.events = EPOLLIN; | 108 event.events = EPOLLIN; |
112 event.data.ptr = NULL; | 109 event.data.ptr = NULL; |
113 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | 110 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, |
114 EPOLL_CTL_ADD, | 111 EPOLL_CTL_ADD, |
115 interrupt_fds_[0], | 112 interrupt_fds_[0], |
116 &event)); | 113 &event)); |
117 if (status == -1) { | 114 if (status == -1) { |
118 FATAL("Failed adding interrupt fd to epoll instance"); | 115 FATAL("Failed adding interrupt fd to epoll instance"); |
119 } | 116 } |
120 } | 117 } |
121 | 118 |
122 | 119 |
123 EventHandlerImplementation::~EventHandlerImplementation() { | 120 EventHandlerImplementation::~EventHandlerImplementation() { |
124 VOID_TEMP_FAILURE_RETRY(close(epoll_fd_)); | |
125 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 121 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
126 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 122 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
127 } | 123 } |
128 | 124 |
129 | 125 |
130 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( | 126 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { |
131 intptr_t fd, bool is_listening) { | |
132 ASSERT(fd >= 0); | 127 ASSERT(fd >= 0); |
133 HashMap::Entry* entry = socket_map_.Lookup( | 128 HashMap::Entry* entry = socket_map_.Lookup( |
134 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 129 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); |
135 ASSERT(entry != NULL); | 130 ASSERT(entry != NULL); |
136 DescriptorInfo* di = | 131 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); |
137 reinterpret_cast<DescriptorInfo*>(entry->value); | 132 if (sd == NULL) { |
138 if (di == NULL) { | |
139 // If there is no data in the hash map for this file descriptor a | 133 // If there is no data in the hash map for this file descriptor a |
140 // new DescriptorInfo for the file descriptor is inserted. | 134 // new SocketData for the file descriptor is inserted. |
141 if (is_listening) { | 135 sd = new SocketData(fd); |
142 di = new DescriptorInfoMultiple(fd); | 136 entry->value = sd; |
143 } else { | |
144 di = new DescriptorInfoSingle(fd); | |
145 } | |
146 entry->value = di; | |
147 } | 137 } |
148 ASSERT(fd == di->fd()); | 138 ASSERT(fd == sd->fd()); |
149 return di; | 139 return sd; |
150 } | 140 } |
151 | 141 |
152 | 142 |
153 void EventHandlerImplementation::WakeupHandler(intptr_t id, | 143 void EventHandlerImplementation::WakeupHandler(intptr_t id, |
154 Dart_Port dart_port, | 144 Dart_Port dart_port, |
155 int64_t data) { | 145 int64_t data) { |
156 InterruptMessage msg; | 146 InterruptMessage msg; |
157 msg.id = id; | 147 msg.id = id; |
158 msg.dart_port = dart_port; | 148 msg.dart_port = dart_port; |
159 msg.data = data; | 149 msg.data = data; |
160 // WriteToBlocking will write up to 512 bytes atomically, and since our msg | 150 // WriteToBlocking will write up to 512 bytes atomically, and since our msg |
161 // is smaller than 512, we don't need a thread lock. | 151 // is smaller than 512, we don't need a thread lock. |
162 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'. | 152 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'. |
163 ASSERT(kInterruptMessageSize < PIPE_BUF); | 153 ASSERT(kInterruptMessageSize < PIPE_BUF); |
164 intptr_t result = | 154 intptr_t result = |
165 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); | 155 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); |
166 if (result != kInterruptMessageSize) { | 156 if (result != kInterruptMessageSize) { |
167 if (result == -1) { | 157 if (result == -1) { |
168 perror("Interrupt message failure:"); | 158 perror("Interrupt message failure:"); |
169 } | 159 } |
170 FATAL1("Interrupt message failure. Wrote %" Pd " bytes.", result); | 160 FATAL1("Interrupt message failure. Wrote %d bytes.", result); |
171 } | 161 } |
172 } | 162 } |
173 | 163 |
174 | 164 |
175 void EventHandlerImplementation::HandleInterruptFd() { | 165 void EventHandlerImplementation::HandleInterruptFd() { |
176 const intptr_t MAX_MESSAGES = kInterruptMessageSize; | 166 const intptr_t MAX_MESSAGES = kInterruptMessageSize; |
177 InterruptMessage msg[MAX_MESSAGES]; | 167 InterruptMessage msg[MAX_MESSAGES]; |
178 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( | 168 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( |
179 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); | 169 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); |
180 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { | 170 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { |
181 if (msg[i].id == kTimerId) { | 171 if (msg[i].id == kTimerId) { |
182 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); | 172 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); |
183 } else if (msg[i].id == kShutdownId) { | 173 } else if (msg[i].id == kShutdownId) { |
184 shutdown_ = true; | 174 shutdown_ = true; |
185 } else { | 175 } else { |
186 DescriptorInfo* di = GetDescriptorInfo( | 176 SocketData* sd = GetSocketData(msg[i].id); |
187 msg[i].id, (msg[i].data & (1 << kListeningSocket)) != 0); | 177 |
188 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { | 178 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { |
189 ASSERT(!di->IsListeningSocket()); | |
190 // Close the socket for reading. | 179 // Close the socket for reading. |
191 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD)); | 180 shutdown(sd->fd(), SHUT_RD); |
192 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { | 181 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { |
193 ASSERT(!di->IsListeningSocket()); | |
194 // Close the socket for writing. | 182 // Close the socket for writing. |
195 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR)); | 183 shutdown(sd->fd(), SHUT_WR); |
196 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { | 184 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { |
197 // Close the socket and free system resources and move on to next | 185 // Close the socket and free system resources and move on to |
198 // message. | 186 // next message. |
199 bool no_more_listeners = di->RemovePort(msg[i].dart_port); | 187 RemoveFromEpollInstance(epoll_fd_, sd); |
200 if (no_more_listeners) { | 188 intptr_t fd = sd->fd(); |
201 RemoveFromEpollInstance(epoll_fd_, di); | 189 sd->Close(); |
202 } | 190 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
203 | 191 delete sd; |
204 intptr_t fd = di->fd(); | |
205 if (di->IsListeningSocket()) { | |
206 // We only close the socket file descriptor from the operating | |
207 // system if there are no other dart socket objects which | |
208 // are listening on the same (address, port) combination. | |
209 { | |
210 MutexLocker ml(globalTcpListeningSocketRegistry.mutex()); | |
211 if (globalTcpListeningSocketRegistry.CloseSafe(fd)) { | |
212 socket_map_.Remove( | |
213 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | |
214 di->Close(); | |
215 delete di; | |
216 } | |
217 } | |
218 } else { | |
219 ASSERT(no_more_listeners); | |
220 socket_map_.Remove( | |
221 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | |
222 di->Close(); | |
223 delete di; | |
224 } | |
225 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); | 192 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); |
226 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { | 193 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { |
227 int count = TOKEN_COUNT(msg[i].data); | 194 int count = TOKEN_COUNT(msg[i].data); |
228 if (di->ReturnTokens(msg[i].dart_port, count)) { | 195 |
229 AddToEpollInstance(epoll_fd_, di); | 196 for (int i = 0; i < count; i++) { |
| 197 if (sd->ReturnToken()) { |
| 198 AddToEpollInstance(epoll_fd_, sd); |
| 199 } |
230 } | 200 } |
231 } else { | 201 } else { |
232 ASSERT_NO_COMMAND(msg[i].data); | 202 ASSERT_NO_COMMAND(msg[i].data); |
233 bool had_listeners = di->HasNextPort(); | 203 // Setup events to wait for. |
234 di->SetPortAndMask(msg[i].dart_port, msg[i].data & EVENT_MASK); | 204 sd->SetPortAndMask(msg[i].dart_port, msg[i].data); |
235 bool has_listeners = di->HasNextPort(); | 205 AddToEpollInstance(epoll_fd_, sd); |
236 | |
237 // Add/Remove from epoll set depending on previous and current state. | |
238 if (!had_listeners && has_listeners) { | |
239 AddToEpollInstance(epoll_fd_, di); | |
240 } else if (had_listeners && !has_listeners) { | |
241 RemoveFromEpollInstance(epoll_fd_, di); | |
242 } | |
243 } | 206 } |
244 } | 207 } |
245 } | 208 } |
246 } | 209 } |
247 | 210 |
248 #ifdef DEBUG_POLL | 211 #ifdef DEBUG_POLL |
249 static void PrintEventMask(intptr_t fd, intptr_t events) { | 212 static void PrintEventMask(intptr_t fd, intptr_t events) { |
250 Log::Print("%d ", fd); | 213 Log::Print("%d ", fd); |
251 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN "); | 214 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN "); |
252 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI "); | 215 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI "); |
253 if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT "); | 216 if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT "); |
254 if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR "); | 217 if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR "); |
255 if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP "); | 218 if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP "); |
256 if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP "); | 219 if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP "); |
257 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT | | 220 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT | |
258 EPOLLERR | EPOLLHUP | EPOLLRDHUP; | 221 EPOLLERR | EPOLLHUP | EPOLLRDHUP; |
259 if ((events & ~all_events) != 0) { | 222 if ((events & ~all_events) != 0) { |
260 Log::Print("(and %08x) ", events & ~all_events); | 223 Log::Print("(and %08x) ", events & ~all_events); |
261 } | 224 } |
262 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd)); | 225 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd)); |
263 | 226 |
264 Log::Print("\n"); | 227 Log::Print("\n"); |
265 } | 228 } |
266 #endif | 229 #endif |
267 | 230 |
268 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events, | 231 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events, |
269 DescriptorInfo* di) { | 232 SocketData* sd) { |
270 #ifdef DEBUG_POLL | 233 #ifdef DEBUG_POLL |
271 PrintEventMask(di->fd(), events); | 234 PrintEventMask(sd->fd(), events); |
272 #endif | 235 #endif |
273 if (events & EPOLLERR) { | 236 if (events & EPOLLERR) { |
274 // Return error only if EPOLLIN is present. | 237 // Return error only if EPOLLIN is present. |
275 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0; | 238 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0; |
276 } | 239 } |
277 intptr_t event_mask = 0; | 240 intptr_t event_mask = 0; |
278 if (events & EPOLLIN) event_mask |= (1 << kInEvent); | 241 if (events & EPOLLIN) event_mask |= (1 << kInEvent); |
279 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent); | 242 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent); |
280 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent); | 243 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent); |
281 return event_mask; | 244 return event_mask; |
282 } | 245 } |
283 | 246 |
284 | 247 |
285 void EventHandlerImplementation::HandleEvents(struct epoll_event* events, | 248 void EventHandlerImplementation::HandleEvents(struct epoll_event* events, |
286 int size) { | 249 int size) { |
287 bool interrupt_seen = false; | 250 bool interrupt_seen = false; |
288 for (int i = 0; i < size; i++) { | 251 for (int i = 0; i < size; i++) { |
289 if (events[i].data.ptr == NULL) { | 252 if (events[i].data.ptr == NULL) { |
290 interrupt_seen = true; | 253 interrupt_seen = true; |
291 } else { | 254 } else { |
292 DescriptorInfo* di = | 255 SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr); |
293 reinterpret_cast<DescriptorInfo*>(events[i].data.ptr); | 256 intptr_t event_mask = GetPollEvents(events[i].events, sd); |
294 intptr_t event_mask = GetPollEvents(events[i].events, di); | |
295 if (event_mask != 0) { | 257 if (event_mask != 0) { |
296 Dart_Port port = di->NextPort(); | 258 if (sd->TakeToken()) { |
| 259 // Took last token, remove from epoll. |
| 260 RemoveFromEpollInstance(epoll_fd_, sd); |
| 261 } |
| 262 Dart_Port port = sd->port(); |
297 ASSERT(port != 0); | 263 ASSERT(port != 0); |
298 if (di->TakeToken()) { | |
299 // Took last token, remove from epoll. | |
300 RemoveFromEpollInstance(epoll_fd_, di); | |
301 } | |
302 DartUtils::PostInt32(port, event_mask); | 264 DartUtils::PostInt32(port, event_mask); |
303 } | 265 } |
304 } | 266 } |
305 } | 267 } |
306 if (interrupt_seen) { | 268 if (interrupt_seen) { |
307 // Handle after socket events, so we avoid closing a socket before we handle | 269 // Handle after socket events, so we avoid closing a socket before we handle |
308 // the current events. | 270 // the current events. |
309 HandleInterruptFd(); | 271 HandleInterruptFd(); |
310 } | 272 } |
311 } | 273 } |
(...skipping 18 matching lines...) Expand all Loading... |
330 timeout_queue_.RemoveCurrent(); | 292 timeout_queue_.RemoveCurrent(); |
331 } | 293 } |
332 } | 294 } |
333 } | 295 } |
334 | 296 |
335 | 297 |
336 void EventHandlerImplementation::Poll(uword args) { | 298 void EventHandlerImplementation::Poll(uword args) { |
337 ThreadSignalBlocker signal_blocker(SIGPROF); | 299 ThreadSignalBlocker signal_blocker(SIGPROF); |
338 static const intptr_t kMaxEvents = 16; | 300 static const intptr_t kMaxEvents = 16; |
339 struct epoll_event events[kMaxEvents]; | 301 struct epoll_event events[kMaxEvents]; |
340 EventHandler* handler = reinterpret_cast<EventHandler*>(args); | 302 EventHandlerImplementation* handler = |
341 EventHandlerImplementation* handler_impl = &handler->delegate_; | 303 reinterpret_cast<EventHandlerImplementation*>(args); |
342 ASSERT(handler_impl != NULL); | 304 ASSERT(handler != NULL); |
343 while (!handler_impl->shutdown_) { | 305 while (!handler->shutdown_) { |
344 int64_t millis = handler_impl->GetTimeout(); | 306 int64_t millis = handler->GetTimeout(); |
345 ASSERT(millis == kInfinityTimeout || millis >= 0); | 307 ASSERT(millis == kInfinityTimeout || millis >= 0); |
346 if (millis > kMaxInt32) millis = kMaxInt32; | 308 if (millis > kMaxInt32) millis = kMaxInt32; |
347 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( | 309 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( |
348 epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis)); | 310 epoll_wait(handler->epoll_fd_, events, kMaxEvents, millis)); |
349 ASSERT(EAGAIN == EWOULDBLOCK); | 311 ASSERT(EAGAIN == EWOULDBLOCK); |
350 if (result == -1) { | 312 if (result == -1) { |
351 if (errno != EWOULDBLOCK) { | 313 if (errno != EWOULDBLOCK) { |
352 perror("Poll failed"); | 314 perror("Poll failed"); |
353 } | 315 } |
354 } else { | 316 } else { |
355 handler_impl->HandleTimeout(); | 317 handler->HandleTimeout(); |
356 handler_impl->HandleEvents(events, result); | 318 handler->HandleEvents(events, result); |
357 } | 319 } |
358 } | 320 } |
359 delete handler; | |
360 } | 321 } |
361 | 322 |
362 | 323 |
363 void EventHandlerImplementation::Start(EventHandler* handler) { | 324 void EventHandlerImplementation::Start(EventHandler* handler) { |
364 int result = Thread::Start(&EventHandlerImplementation::Poll, | 325 int result = Thread::Start(&EventHandlerImplementation::Poll, |
365 reinterpret_cast<uword>(handler)); | 326 reinterpret_cast<uword>(handler)); |
366 if (result != 0) { | 327 if (result != 0) { |
367 FATAL1("Failed to start event handler thread %d", result); | 328 FATAL1("Failed to start event handler thread %d", result); |
368 } | 329 } |
369 } | 330 } |
370 | 331 |
371 | 332 |
372 void EventHandlerImplementation::Shutdown() { | 333 void EventHandlerImplementation::Shutdown() { |
373 SendData(kShutdownId, 0, 0); | 334 SendData(kShutdownId, 0, 0); |
374 } | 335 } |
375 | 336 |
376 | 337 |
377 void EventHandlerImplementation::SendData(intptr_t id, | 338 void EventHandlerImplementation::SendData(intptr_t id, |
378 Dart_Port dart_port, | 339 Dart_Port dart_port, |
379 int64_t data) { | 340 intptr_t data) { |
380 WakeupHandler(id, dart_port, data); | 341 WakeupHandler(id, dart_port, data); |
381 } | 342 } |
382 | 343 |
383 | 344 |
384 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { | 345 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { |
385 // The hashmap does not support keys with value 0. | 346 // The hashmap does not support keys with value 0. |
386 return reinterpret_cast<void*>(fd + 1); | 347 return reinterpret_cast<void*>(fd + 1); |
387 } | 348 } |
388 | 349 |
389 | 350 |
390 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { | 351 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { |
391 // The hashmap does not support keys with value 0. | 352 // The hashmap does not support keys with value 0. |
392 return dart::Utils::WordHash(fd + 1); | 353 return dart::Utils::WordHash(fd + 1); |
393 } | 354 } |
394 | 355 |
395 } // namespace bin | 356 } // namespace bin |
396 } // namespace dart | 357 } // namespace dart |
397 | 358 |
398 #endif // defined(TARGET_OS_ANDROID) | 359 #endif // defined(TARGET_OS_ANDROID) |
OLD | NEW |