Chromium Code Reviews| 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" | |
| 9 | 10 |
| 10 #include <errno.h> // NOLINT | 11 #include <errno.h> // NOLINT |
| 11 #include <pthread.h> // NOLINT | 12 #include <pthread.h> // NOLINT |
| 12 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
| 13 #include <string.h> // NOLINT | 14 #include <string.h> // NOLINT |
| 14 #include <sys/epoll.h> // NOLINT | 15 #include <sys/epoll.h> // NOLINT |
| 15 #include <sys/stat.h> // NOLINT | 16 #include <sys/stat.h> // NOLINT |
| 16 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
| 17 #include <fcntl.h> // NOLINT | 18 #include <fcntl.h> // NOLINT |
| 18 | 19 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 } | 94 } |
| 94 FDUtils::SetNonBlocking(interrupt_fds_[0]); | 95 FDUtils::SetNonBlocking(interrupt_fds_[0]); |
| 95 FDUtils::SetCloseOnExec(interrupt_fds_[0]); | 96 FDUtils::SetCloseOnExec(interrupt_fds_[0]); |
| 96 FDUtils::SetCloseOnExec(interrupt_fds_[1]); | 97 FDUtils::SetCloseOnExec(interrupt_fds_[1]); |
| 97 shutdown_ = false; | 98 shutdown_ = false; |
| 98 // The initial size passed to epoll_create is ignore on newer (>= | 99 // The initial size passed to epoll_create is ignore on newer (>= |
| 99 // 2.6.8) Linux versions | 100 // 2.6.8) Linux versions |
| 100 static const int kEpollInitialSize = 64; | 101 static const int kEpollInitialSize = 64; |
| 101 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); | 102 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); |
| 102 if (epoll_fd_ == -1) { | 103 if (epoll_fd_ == -1) { |
| 103 FATAL("Failed creating epoll file descriptor"); | 104 FATAL1("Failed creating epoll file descriptor: %i", errno); |
| 104 } | 105 } |
| 105 FDUtils::SetCloseOnExec(epoll_fd_); | 106 FDUtils::SetCloseOnExec(epoll_fd_); |
| 106 // Register the interrupt_fd with the epoll instance. | 107 // Register the interrupt_fd with the epoll instance. |
| 107 struct epoll_event event; | 108 struct epoll_event event; |
| 108 event.events = EPOLLIN; | 109 event.events = EPOLLIN; |
| 109 event.data.ptr = NULL; | 110 event.data.ptr = NULL; |
| 110 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, | 111 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, |
| 111 EPOLL_CTL_ADD, | 112 EPOLL_CTL_ADD, |
| 112 interrupt_fds_[0], | 113 interrupt_fds_[0], |
| 113 &event)); | 114 &event)); |
| 114 if (status == -1) { | 115 if (status == -1) { |
| 115 FATAL("Failed adding interrupt fd to epoll instance"); | 116 FATAL("Failed adding interrupt fd to epoll instance"); |
| 116 } | 117 } |
| 117 } | 118 } |
| 118 | 119 |
| 119 | 120 |
| 120 EventHandlerImplementation::~EventHandlerImplementation() { | 121 EventHandlerImplementation::~EventHandlerImplementation() { |
| 122 VOID_TEMP_FAILURE_RETRY(close(epoll_fd_)); | |
| 121 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 123 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
| 122 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 124 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
| 123 } | 125 } |
| 124 | 126 |
| 125 | 127 |
| 126 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { | 128 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { |
| 127 ASSERT(fd >= 0); | 129 ASSERT(fd >= 0); |
| 128 HashMap::Entry* entry = socket_map_.Lookup( | 130 HashMap::Entry* entry = socket_map_.Lookup( |
| 129 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 131 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); |
| 130 ASSERT(entry != NULL); | 132 ASSERT(entry != NULL); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 150 // WriteToBlocking will write up to 512 bytes atomically, and since our msg | 152 // WriteToBlocking will write up to 512 bytes atomically, and since our msg |
| 151 // is smaller than 512, we don't need a thread lock. | 153 // is smaller than 512, we don't need a thread lock. |
| 152 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'. | 154 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'. |
| 153 ASSERT(kInterruptMessageSize < PIPE_BUF); | 155 ASSERT(kInterruptMessageSize < PIPE_BUF); |
| 154 intptr_t result = | 156 intptr_t result = |
| 155 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); | 157 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); |
| 156 if (result != kInterruptMessageSize) { | 158 if (result != kInterruptMessageSize) { |
| 157 if (result == -1) { | 159 if (result == -1) { |
| 158 perror("Interrupt message failure:"); | 160 perror("Interrupt message failure:"); |
| 159 } | 161 } |
| 160 FATAL1("Interrupt message failure. Wrote %d bytes.", result); | 162 FATAL1("Interrupt message failure. Wrote %" Pd " bytes.", result); |
| 161 } | 163 } |
| 162 } | 164 } |
| 163 | 165 |
| 164 | 166 |
| 165 void EventHandlerImplementation::HandleInterruptFd() { | 167 void EventHandlerImplementation::HandleInterruptFd() { |
| 166 const intptr_t MAX_MESSAGES = kInterruptMessageSize; | 168 const intptr_t MAX_MESSAGES = kInterruptMessageSize; |
| 167 InterruptMessage msg[MAX_MESSAGES]; | 169 InterruptMessage msg[MAX_MESSAGES]; |
| 168 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( | 170 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( |
| 169 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); | 171 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); |
| 170 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { | 172 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { |
| 171 if (msg[i].id == kTimerId) { | 173 if (msg[i].id == kTimerId) { |
| 172 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); | 174 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); |
| 173 } else if (msg[i].id == kShutdownId) { | 175 } else if (msg[i].id == kShutdownId) { |
| 174 shutdown_ = true; | 176 shutdown_ = true; |
| 175 } else { | 177 } else { |
| 176 SocketData* sd = GetSocketData(msg[i].id); | 178 SocketData* sd = GetSocketData(msg[i].id); |
| 177 | 179 |
| 178 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { | 180 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { |
| 179 // Close the socket for reading. | 181 // Close the socket for reading. |
| 180 shutdown(sd->fd(), SHUT_RD); | 182 VOID_NO_RETRY_EXPECTED(shutdown(sd->fd(), SHUT_RD)); |
| 181 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { | 183 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { |
| 182 // Close the socket for writing. | 184 // Close the socket for writing. |
| 183 shutdown(sd->fd(), SHUT_WR); | 185 VOID_NO_RETRY_EXPECTED(shutdown(sd->fd(), SHUT_WR)); |
| 184 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { | 186 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { |
| 185 // Close the socket and free system resources and move on to | 187 // Close the socket and free system resources and move on to |
| 186 // next message. | 188 // next message. |
| 187 RemoveFromEpollInstance(epoll_fd_, sd); | 189 RemoveFromEpollInstance(epoll_fd_, sd); |
| 188 intptr_t fd = sd->fd(); | 190 intptr_t fd = sd->fd(); |
| 189 sd->Close(); | 191 sd->Close(); |
| 190 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | 192 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
| 191 delete sd; | 193 delete sd; |
| 192 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); | 194 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); |
| 193 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { | 195 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 timeout_queue_.RemoveCurrent(); | 294 timeout_queue_.RemoveCurrent(); |
| 293 } | 295 } |
| 294 } | 296 } |
| 295 } | 297 } |
| 296 | 298 |
| 297 | 299 |
| 298 void EventHandlerImplementation::Poll(uword args) { | 300 void EventHandlerImplementation::Poll(uword args) { |
| 299 ThreadSignalBlocker signal_blocker(SIGPROF); | 301 ThreadSignalBlocker signal_blocker(SIGPROF); |
| 300 static const intptr_t kMaxEvents = 16; | 302 static const intptr_t kMaxEvents = 16; |
| 301 struct epoll_event events[kMaxEvents]; | 303 struct epoll_event events[kMaxEvents]; |
| 302 EventHandlerImplementation* handler = | 304 EventHandler* handler = reinterpret_cast<EventHandler*>(args); |
| 303 reinterpret_cast<EventHandlerImplementation*>(args); | 305 EventHandlerImplementation* handler_impl = &handler->delegate_; |
|
kustermann
2015/01/29 11:22:33
This was a pretty risky cast. It just happens by a
| |
| 304 ASSERT(handler != NULL); | 306 ASSERT(handler_impl != NULL); |
| 305 while (!handler->shutdown_) { | 307 while (!handler_impl->shutdown_) { |
| 306 int64_t millis = handler->GetTimeout(); | 308 int64_t millis = handler->GetTimeout(); |
| 307 ASSERT(millis == kInfinityTimeout || millis >= 0); | 309 ASSERT(millis == kInfinityTimeout || millis >= 0); |
| 308 if (millis > kMaxInt32) millis = kMaxInt32; | 310 if (millis > kMaxInt32) millis = kMaxInt32; |
| 309 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( | 311 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( |
| 310 epoll_wait(handler->epoll_fd_, events, kMaxEvents, millis)); | 312 epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis)); |
| 311 ASSERT(EAGAIN == EWOULDBLOCK); | 313 ASSERT(EAGAIN == EWOULDBLOCK); |
| 312 if (result == -1) { | 314 if (result == -1) { |
| 313 if (errno != EWOULDBLOCK) { | 315 if (errno != EWOULDBLOCK) { |
| 314 perror("Poll failed"); | 316 perror("Poll failed"); |
| 315 } | 317 } |
| 316 } else { | 318 } else { |
| 317 handler->HandleTimeout(); | 319 handler->HandleTimeout(); |
| 318 handler->HandleEvents(events, result); | 320 handler->HandleEvents(events, result); |
| 319 } | 321 } |
| 320 } | 322 } |
| 323 delete handler; | |
| 321 } | 324 } |
| 322 | 325 |
| 323 | 326 |
| 324 void EventHandlerImplementation::Start(EventHandler* handler) { | 327 void EventHandlerImplementation::Start(EventHandler* handler) { |
| 325 int result = Thread::Start(&EventHandlerImplementation::Poll, | 328 int result = Thread::Start(&EventHandlerImplementation::Poll, |
| 326 reinterpret_cast<uword>(handler)); | 329 reinterpret_cast<uword>(handler)); |
| 327 if (result != 0) { | 330 if (result != 0) { |
| 328 FATAL1("Failed to start event handler thread %d", result); | 331 FATAL1("Failed to start event handler thread %d", result); |
| 329 } | 332 } |
| 330 } | 333 } |
| 331 | 334 |
| 332 | 335 |
| 333 void EventHandlerImplementation::Shutdown() { | 336 void EventHandlerImplementation::Shutdown() { |
| 334 SendData(kShutdownId, 0, 0); | 337 SendData(kShutdownId, 0, 0); |
| 335 } | 338 } |
| 336 | 339 |
| 337 | 340 |
| 338 void EventHandlerImplementation::SendData(intptr_t id, | 341 void EventHandlerImplementation::SendData(intptr_t id, |
| 339 Dart_Port dart_port, | 342 Dart_Port dart_port, |
| 340 intptr_t data) { | 343 int64_t data) { |
| 341 WakeupHandler(id, dart_port, data); | 344 WakeupHandler(id, dart_port, data); |
| 342 } | 345 } |
| 343 | 346 |
| 344 | 347 |
| 345 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { | 348 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { |
| 346 // The hashmap does not support keys with value 0. | 349 // The hashmap does not support keys with value 0. |
| 347 return reinterpret_cast<void*>(fd + 1); | 350 return reinterpret_cast<void*>(fd + 1); |
| 348 } | 351 } |
| 349 | 352 |
| 350 | 353 |
| 351 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { | 354 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { |
| 352 // The hashmap does not support keys with value 0. | 355 // The hashmap does not support keys with value 0. |
| 353 return dart::Utils::WordHash(fd + 1); | 356 return dart::Utils::WordHash(fd + 1); |
| 354 } | 357 } |
| 355 | 358 |
| 356 } // namespace bin | 359 } // namespace bin |
| 357 } // namespace dart | 360 } // namespace dart |
| 358 | 361 |
| 359 #endif // defined(TARGET_OS_ANDROID) | 362 #endif // defined(TARGET_OS_ANDROID) |
| OLD | NEW |