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 |