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