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 #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_ANDROID) | 8 #if defined(TARGET_OS_ANDROID) |
9 | 9 |
10 #include "bin/eventhandler.h" | 10 #include "bin/eventhandler.h" |
11 #include "bin/eventhandler_android.h" | 11 #include "bin/eventhandler_android.h" |
12 | 12 |
13 #include <errno.h> // NOLINT | 13 #include <errno.h> // NOLINT |
14 #include <fcntl.h> // NOLINT | 14 #include <fcntl.h> // NOLINT |
15 #include <pthread.h> // NOLINT | 15 #include <pthread.h> // NOLINT |
16 #include <stdio.h> // NOLINT | 16 #include <stdio.h> // NOLINT |
17 #include <string.h> // NOLINT | 17 #include <string.h> // NOLINT |
18 #include <sys/epoll.h> // NOLINT | 18 #include <sys/epoll.h> // NOLINT |
19 #include <sys/stat.h> // NOLINT | 19 #include <sys/stat.h> // NOLINT |
20 #include <unistd.h> // NOLINT | 20 #include <unistd.h> // NOLINT |
21 | 21 |
22 #include "bin/dartutils.h" | 22 #include "bin/dartutils.h" |
23 #include "bin/fdutils.h" | 23 #include "bin/fdutils.h" |
24 #include "bin/log.h" | 24 #include "bin/log.h" |
25 #include "bin/lockers.h" | 25 #include "bin/lockers.h" |
26 #include "bin/socket.h" | 26 #include "bin/socket.h" |
27 #include "bin/thread.h" | 27 #include "bin/thread.h" |
28 #include "bin/utils.h" | 28 #include "bin/utils.h" |
29 #include "platform/hashmap.h" | 29 #include "platform/hashmap.h" |
30 #include "platform/utils.h" | 30 #include "platform/utils.h" |
(...skipping 15 matching lines...) Expand all Loading... |
46 } | 46 } |
47 if ((Mask() & (1 << kOutEvent)) != 0) { | 47 if ((Mask() & (1 << kOutEvent)) != 0) { |
48 events |= EPOLLOUT; | 48 events |= EPOLLOUT; |
49 } | 49 } |
50 return events; | 50 return events; |
51 } | 51 } |
52 | 52 |
53 | 53 |
54 // Unregister the file descriptor for a DescriptorInfo structure with | 54 // Unregister the file descriptor for a DescriptorInfo structure with |
55 // epoll. | 55 // epoll. |
56 static void RemoveFromEpollInstance(intptr_t epoll_fd_, | 56 static void RemoveFromEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) { |
57 DescriptorInfo* di) { | 57 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, di->fd(), NULL)); |
58 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | |
59 EPOLL_CTL_DEL, | |
60 di->fd(), | |
61 NULL)); | |
62 } | 58 } |
63 | 59 |
64 | 60 |
65 static void AddToEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) { | 61 static void AddToEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) { |
66 struct epoll_event event; | 62 struct epoll_event event; |
67 event.events = EPOLLRDHUP | di->GetPollEvents(); | 63 event.events = EPOLLRDHUP | di->GetPollEvents(); |
68 if (!di->IsListeningSocket()) { | 64 if (!di->IsListeningSocket()) { |
69 event.events |= EPOLLET; | 65 event.events |= EPOLLET; |
70 } | 66 } |
71 event.data.ptr = di; | 67 event.data.ptr = di; |
72 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | 68 int status = |
73 EPOLL_CTL_ADD, | 69 NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, di->fd(), &event)); |
74 di->fd(), | |
75 &event)); | |
76 if (status == -1) { | 70 if (status == -1) { |
77 // TODO(dart:io): Verify that the dart end is handling this correctly. | 71 // TODO(dart:io): Verify that the dart end is handling this correctly. |
78 | 72 |
79 // Epoll does not accept the file descriptor. It could be due to | 73 // Epoll does not accept the file descriptor. It could be due to |
80 // already closed file descriptor, or unuspported devices, such | 74 // already closed file descriptor, or unuspported devices, such |
81 // as /dev/null. In such case, mark the file descriptor as closed, | 75 // as /dev/null. In such case, mark the file descriptor as closed, |
82 // so dart will handle it accordingly. | 76 // so dart will handle it accordingly. |
83 di->NotifyAllDartPorts(1 << kCloseEvent); | 77 di->NotifyAllDartPorts(1 << kCloseEvent); |
84 } | 78 } |
85 } | 79 } |
(...skipping 15 matching lines...) Expand all Loading... |
101 static const int kEpollInitialSize = 64; | 95 static const int kEpollInitialSize = 64; |
102 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); | 96 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); |
103 if (epoll_fd_ == -1) { | 97 if (epoll_fd_ == -1) { |
104 FATAL1("Failed creating epoll file descriptor: %i", errno); | 98 FATAL1("Failed creating epoll file descriptor: %i", errno); |
105 } | 99 } |
106 FDUtils::SetCloseOnExec(epoll_fd_); | 100 FDUtils::SetCloseOnExec(epoll_fd_); |
107 // Register the interrupt_fd with the epoll instance. | 101 // Register the interrupt_fd with the epoll instance. |
108 struct epoll_event event; | 102 struct epoll_event event; |
109 event.events = EPOLLIN; | 103 event.events = EPOLLIN; |
110 event.data.ptr = NULL; | 104 event.data.ptr = NULL; |
111 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | 105 int status = NO_RETRY_EXPECTED( |
112 EPOLL_CTL_ADD, | 106 epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupt_fds_[0], &event)); |
113 interrupt_fds_[0], | |
114 &event)); | |
115 if (status == -1) { | 107 if (status == -1) { |
116 FATAL("Failed adding interrupt fd to epoll instance"); | 108 FATAL("Failed adding interrupt fd to epoll instance"); |
117 } | 109 } |
118 } | 110 } |
119 | 111 |
120 | 112 |
121 static void DeleteDescriptorInfo(void* info) { | 113 static void DeleteDescriptorInfo(void* info) { |
122 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(info); | 114 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(info); |
123 di->Close(); | 115 di->Close(); |
124 delete di; | 116 delete di; |
125 } | 117 } |
126 | 118 |
127 | 119 |
128 EventHandlerImplementation::~EventHandlerImplementation() { | 120 EventHandlerImplementation::~EventHandlerImplementation() { |
129 socket_map_.Clear(DeleteDescriptorInfo); | 121 socket_map_.Clear(DeleteDescriptorInfo); |
130 VOID_TEMP_FAILURE_RETRY(close(epoll_fd_)); | 122 VOID_TEMP_FAILURE_RETRY(close(epoll_fd_)); |
131 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 123 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
132 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 124 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
133 } | 125 } |
134 | 126 |
135 | 127 |
136 void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask, | 128 void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask, |
137 DescriptorInfo *di) { | 129 DescriptorInfo* di) { |
138 intptr_t new_mask = di->Mask(); | 130 intptr_t new_mask = di->Mask(); |
139 if ((old_mask != 0) && (new_mask == 0)) { | 131 if ((old_mask != 0) && (new_mask == 0)) { |
140 RemoveFromEpollInstance(epoll_fd_, di); | 132 RemoveFromEpollInstance(epoll_fd_, di); |
141 } else if ((old_mask == 0) && (new_mask != 0)) { | 133 } else if ((old_mask == 0) && (new_mask != 0)) { |
142 AddToEpollInstance(epoll_fd_, di); | 134 AddToEpollInstance(epoll_fd_, di); |
143 } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) { | 135 } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) { |
144 ASSERT(!di->IsListeningSocket()); | 136 ASSERT(!di->IsListeningSocket()); |
145 RemoveFromEpollInstance(epoll_fd_, di); | 137 RemoveFromEpollInstance(epoll_fd_, di); |
146 AddToEpollInstance(epoll_fd_, di); | 138 AddToEpollInstance(epoll_fd_, di); |
147 } | 139 } |
148 } | 140 } |
149 | 141 |
150 | 142 |
151 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( | 143 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( |
152 intptr_t fd, bool is_listening) { | 144 intptr_t fd, |
| 145 bool is_listening) { |
153 ASSERT(fd >= 0); | 146 ASSERT(fd >= 0); |
154 HashMap::Entry* entry = socket_map_.Lookup( | 147 HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd), |
155 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 148 GetHashmapHashFromFd(fd), true); |
156 ASSERT(entry != NULL); | 149 ASSERT(entry != NULL); |
157 DescriptorInfo* di = | 150 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value); |
158 reinterpret_cast<DescriptorInfo*>(entry->value); | |
159 if (di == NULL) { | 151 if (di == NULL) { |
160 // If there is no data in the hash map for this file descriptor a | 152 // If there is no data in the hash map for this file descriptor a |
161 // new DescriptorInfo for the file descriptor is inserted. | 153 // new DescriptorInfo for the file descriptor is inserted. |
162 if (is_listening) { | 154 if (is_listening) { |
163 di = new DescriptorInfoMultiple(fd); | 155 di = new DescriptorInfoMultiple(fd); |
164 } else { | 156 } else { |
165 di = new DescriptorInfoSingle(fd); | 157 di = new DescriptorInfoSingle(fd); |
166 } | 158 } |
167 entry->value = di; | 159 entry->value = di; |
168 } | 160 } |
(...skipping 30 matching lines...) Expand all Loading... |
199 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( | 191 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( |
200 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); | 192 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); |
201 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { | 193 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { |
202 if (msg[i].id == kTimerId) { | 194 if (msg[i].id == kTimerId) { |
203 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); | 195 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); |
204 } else if (msg[i].id == kShutdownId) { | 196 } else if (msg[i].id == kShutdownId) { |
205 shutdown_ = true; | 197 shutdown_ = true; |
206 } else { | 198 } else { |
207 ASSERT((msg[i].data & COMMAND_MASK) != 0); | 199 ASSERT((msg[i].data & COMMAND_MASK) != 0); |
208 | 200 |
209 DescriptorInfo* di = GetDescriptorInfo( | 201 DescriptorInfo* di = |
210 msg[i].id, IS_LISTENING_SOCKET(msg[i].data)); | 202 GetDescriptorInfo(msg[i].id, IS_LISTENING_SOCKET(msg[i].data)); |
211 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { | 203 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { |
212 ASSERT(!di->IsListeningSocket()); | 204 ASSERT(!di->IsListeningSocket()); |
213 // Close the socket for reading. | 205 // Close the socket for reading. |
214 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD)); | 206 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD)); |
215 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { | 207 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { |
216 ASSERT(!di->IsListeningSocket()); | 208 ASSERT(!di->IsListeningSocket()); |
217 // Close the socket for writing. | 209 // Close the socket for writing. |
218 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR)); | 210 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR)); |
219 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { | 211 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { |
220 // Close the socket and free system resources and move on to next | 212 // Close the socket and free system resources and move on to next |
221 // message. | 213 // message. |
222 intptr_t old_mask = di->Mask(); | 214 intptr_t old_mask = di->Mask(); |
223 Dart_Port port = msg[i].dart_port; | 215 Dart_Port port = msg[i].dart_port; |
224 di->RemovePort(port); | 216 di->RemovePort(port); |
225 intptr_t new_mask = di->Mask(); | 217 intptr_t new_mask = di->Mask(); |
226 UpdateEpollInstance(old_mask, di); | 218 UpdateEpollInstance(old_mask, di); |
227 | 219 |
228 intptr_t fd = di->fd(); | 220 intptr_t fd = di->fd(); |
229 if (di->IsListeningSocket()) { | 221 if (di->IsListeningSocket()) { |
230 // We only close the socket file descriptor from the operating | 222 // We only close the socket file descriptor from the operating |
231 // system if there are no other dart socket objects which | 223 // system if there are no other dart socket objects which |
232 // are listening on the same (address, port) combination. | 224 // are listening on the same (address, port) combination. |
233 ListeningSocketRegistry *registry = | 225 ListeningSocketRegistry* registry = |
234 ListeningSocketRegistry::Instance(); | 226 ListeningSocketRegistry::Instance(); |
235 | 227 |
236 MutexLocker locker(registry->mutex()); | 228 MutexLocker locker(registry->mutex()); |
237 | 229 |
238 if (registry->CloseSafe(fd)) { | 230 if (registry->CloseSafe(fd)) { |
239 ASSERT(new_mask == 0); | 231 ASSERT(new_mask == 0); |
240 socket_map_.Remove(GetHashmapKeyFromFd(fd), | 232 socket_map_.Remove(GetHashmapKeyFromFd(fd), |
241 GetHashmapHashFromFd(fd)); | 233 GetHashmapHashFromFd(fd)); |
242 di->Close(); | 234 di->Close(); |
243 delete di; | 235 delete di; |
244 } | 236 } |
245 } else { | 237 } else { |
246 ASSERT(new_mask == 0); | 238 ASSERT(new_mask == 0); |
247 socket_map_.Remove( | 239 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
248 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | |
249 di->Close(); | 240 di->Close(); |
250 delete di; | 241 delete di; |
251 } | 242 } |
252 | 243 |
253 DartUtils::PostInt32(port, 1 << kDestroyedEvent); | 244 DartUtils::PostInt32(port, 1 << kDestroyedEvent); |
254 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { | 245 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { |
255 int count = TOKEN_COUNT(msg[i].data); | 246 int count = TOKEN_COUNT(msg[i].data); |
256 intptr_t old_mask = di->Mask(); | 247 intptr_t old_mask = di->Mask(); |
257 di->ReturnTokens(msg[i].dart_port, count); | 248 di->ReturnTokens(msg[i].dart_port, count); |
258 UpdateEpollInstance(old_mask, di); | 249 UpdateEpollInstance(old_mask, di); |
(...skipping 27 matching lines...) Expand all Loading... |
286 } | 277 } |
287 if ((events & EPOLLERR) != 0) { | 278 if ((events & EPOLLERR) != 0) { |
288 Log::Print("EPOLLERR "); | 279 Log::Print("EPOLLERR "); |
289 } | 280 } |
290 if ((events & EPOLLHUP) != 0) { | 281 if ((events & EPOLLHUP) != 0) { |
291 Log::Print("EPOLLHUP "); | 282 Log::Print("EPOLLHUP "); |
292 } | 283 } |
293 if ((events & EPOLLRDHUP) != 0) { | 284 if ((events & EPOLLRDHUP) != 0) { |
294 Log::Print("EPOLLRDHUP "); | 285 Log::Print("EPOLLRDHUP "); |
295 } | 286 } |
296 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT | | 287 int all_events = |
297 EPOLLERR | EPOLLHUP | EPOLLRDHUP; | 288 EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDHUP; |
298 if ((events & ~all_events) != 0) { | 289 if ((events & ~all_events) != 0) { |
299 Log::Print("(and %08x) ", events & ~all_events); | 290 Log::Print("(and %08x) ", events & ~all_events); |
300 } | 291 } |
301 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd)); | 292 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd)); |
302 | 293 |
303 Log::Print("\n"); | 294 Log::Print("\n"); |
304 } | 295 } |
305 #endif | 296 #endif |
306 | 297 |
307 | 298 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 // the current events. | 343 // the current events. |
353 HandleInterruptFd(); | 344 HandleInterruptFd(); |
354 } | 345 } |
355 } | 346 } |
356 | 347 |
357 | 348 |
358 int64_t EventHandlerImplementation::GetTimeout() { | 349 int64_t EventHandlerImplementation::GetTimeout() { |
359 if (!timeout_queue_.HasTimeout()) { | 350 if (!timeout_queue_.HasTimeout()) { |
360 return kInfinityTimeout; | 351 return kInfinityTimeout; |
361 } | 352 } |
362 int64_t millis = timeout_queue_.CurrentTimeout() - | 353 int64_t millis = |
363 TimerUtils::GetCurrentMonotonicMillis(); | 354 timeout_queue_.CurrentTimeout() - TimerUtils::GetCurrentMonotonicMillis(); |
364 return (millis < 0) ? 0 : millis; | 355 return (millis < 0) ? 0 : millis; |
365 } | 356 } |
366 | 357 |
367 | 358 |
368 void EventHandlerImplementation::HandleTimeout() { | 359 void EventHandlerImplementation::HandleTimeout() { |
369 if (timeout_queue_.HasTimeout()) { | 360 if (timeout_queue_.HasTimeout()) { |
370 int64_t millis = timeout_queue_.CurrentTimeout() - | 361 int64_t millis = timeout_queue_.CurrentTimeout() - |
371 TimerUtils::GetCurrentMonotonicMillis(); | 362 TimerUtils::GetCurrentMonotonicMillis(); |
372 if (millis <= 0) { | 363 if (millis <= 0) { |
373 DartUtils::PostNull(timeout_queue_.CurrentPort()); | 364 DartUtils::PostNull(timeout_queue_.CurrentPort()); |
374 timeout_queue_.RemoveCurrent(); | 365 timeout_queue_.RemoveCurrent(); |
375 } | 366 } |
376 } | 367 } |
377 } | 368 } |
378 | 369 |
379 | 370 |
380 void EventHandlerImplementation::Poll(uword args) { | 371 void EventHandlerImplementation::Poll(uword args) { |
381 ThreadSignalBlocker signal_blocker(SIGPROF); | 372 ThreadSignalBlocker signal_blocker(SIGPROF); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 // The hashmap does not support keys with value 0. | 429 // The hashmap does not support keys with value 0. |
439 return dart::Utils::WordHash(fd + 1); | 430 return dart::Utils::WordHash(fd + 1); |
440 } | 431 } |
441 | 432 |
442 } // namespace bin | 433 } // namespace bin |
443 } // namespace dart | 434 } // namespace dart |
444 | 435 |
445 #endif // defined(TARGET_OS_ANDROID) | 436 #endif // defined(TARGET_OS_ANDROID) |
446 | 437 |
447 #endif // !defined(DART_IO_DISABLED) | 438 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |