| 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 "bin/eventhandler.h" | 5 #include "bin/eventhandler.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <poll.h> | |
| 9 #include <pthread.h> | 8 #include <pthread.h> |
| 10 #include <stdio.h> | 9 #include <stdio.h> |
| 11 #include <string.h> | 10 #include <string.h> |
| 11 #include <sys/epoll.h> |
| 12 #include <sys/time.h> | 12 #include <sys/time.h> |
| 13 #include <unistd.h> | 13 #include <unistd.h> |
| 14 | 14 |
| 15 #include "bin/fdutils.h" | 15 #include "bin/fdutils.h" |
| 16 #include "bin/hashmap.h" | 16 #include "bin/hashmap.h" |
| 17 #include "platform/utils.h" | 17 #include "platform/utils.h" |
| 18 | 18 |
| 19 | 19 |
| 20 int64_t GetCurrentTimeMilliseconds() { | 20 int64_t GetCurrentTimeMilliseconds() { |
| 21 struct timeval tv; | 21 struct timeval tv; |
| 22 if (gettimeofday(&tv, NULL) < 0) { | 22 if (gettimeofday(&tv, NULL) < 0) { |
| 23 UNREACHABLE(); | 23 UNREACHABLE(); |
| 24 return 0; | 24 return 0; |
| 25 } | 25 } |
| 26 return ((static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec) / 1000; | 26 return ((static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec) / 1000; |
| 27 } | 27 } |
| 28 | 28 |
| 29 | 29 |
| 30 static const int kInterruptMessageSize = sizeof(InterruptMessage); | 30 static const int kInterruptMessageSize = sizeof(InterruptMessage); |
| 31 static const int kInfinityTimeout = -1; | 31 static const int kInfinityTimeout = -1; |
| 32 static const int kTimerId = -1; | 32 static const int kTimerId = -1; |
| 33 | 33 |
| 34 | 34 |
| 35 intptr_t SocketData::GetPollEvents() { | 35 intptr_t SocketData::GetPollEvents() { |
| 36 // Do not ask for POLLERR and POLLHUP explicitly as they are | 36 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are |
| 37 // triggered anyway. | 37 // triggered anyway. |
| 38 intptr_t events = 0; | 38 intptr_t events = 0; |
| 39 if (!IsClosedRead()) { | 39 if (!IsClosedRead()) { |
| 40 if ((mask_ & (1 << kInEvent)) != 0) { | 40 if ((mask_ & (1 << kInEvent)) != 0) { |
| 41 events |= POLLIN; | 41 events |= EPOLLIN; |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 if (!IsClosedWrite()) { | 44 if (!IsClosedWrite()) { |
| 45 if ((mask_ & (1 << kOutEvent)) != 0) { | 45 if ((mask_ & (1 << kOutEvent)) != 0) { |
| 46 events |= POLLOUT; | 46 events |= EPOLLOUT; |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 return events; | 49 return events; |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 // Unregister the file descriptor for a SocketData structure with epoll. |
| 54 static void RemoveFromEpollInstance(intptr_t epoll_fd_, SocketData* sd) { |
| 55 if (sd->tracked_by_epoll()) { |
| 56 int status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, |
| 57 EPOLL_CTL_DEL, |
| 58 sd->fd(), |
| 59 NULL)); |
| 60 if (status == -1) { |
| 61 FATAL("Failed unregistering events for file descriptor"); |
| 62 } |
| 63 sd->set_tracked_by_epoll(false); |
| 64 } |
| 65 } |
| 66 |
| 67 |
| 68 // Register the file descriptor for a SocketData structure with epoll |
| 69 // if events are requested. |
| 70 static void UpdateEpollInstance(intptr_t epoll_fd_, SocketData* sd) { |
| 71 struct epoll_event event; |
| 72 event.events = sd->GetPollEvents(); |
| 73 event.data.ptr = sd; |
| 74 if (sd->port() != 0 && event.events != 0) { |
| 75 int status = 0; |
| 76 if (sd->tracked_by_epoll()) { |
| 77 status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, |
| 78 EPOLL_CTL_MOD, |
| 79 sd->fd(), |
| 80 &event)); |
| 81 } else { |
| 82 status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, |
| 83 EPOLL_CTL_ADD, |
| 84 sd->fd(), |
| 85 &event)); |
| 86 sd->set_tracked_by_epoll(true); |
| 87 } |
| 88 if (status == -1) { |
| 89 FATAL("Failed updating epoll instance"); |
| 90 } |
| 91 } |
| 92 } |
| 93 |
| 94 |
| 53 EventHandlerImplementation::EventHandlerImplementation() | 95 EventHandlerImplementation::EventHandlerImplementation() |
| 54 : socket_map_(&HashMap::SamePointerValue, 16) { | 96 : socket_map_(&HashMap::SamePointerValue, 16) { |
| 55 intptr_t result; | 97 intptr_t result; |
| 56 result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_)); | 98 result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_)); |
| 57 if (result != 0) { | 99 if (result != 0) { |
| 58 FATAL("Pipe creation failed"); | 100 FATAL("Pipe creation failed"); |
| 59 } | 101 } |
| 60 FDUtils::SetNonBlocking(interrupt_fds_[0]); | 102 FDUtils::SetNonBlocking(interrupt_fds_[0]); |
| 61 timeout_ = kInfinityTimeout; | 103 timeout_ = kInfinityTimeout; |
| 62 timeout_port_ = 0; | 104 timeout_port_ = 0; |
| 105 // The initial size passed to epoll_create is ignore on newer (>= |
| 106 // 2.6.8) Linux versions |
| 107 static const int kEpollInitialSize = 64; |
| 108 epoll_fd_ = TEMP_FAILURE_RETRY(epoll_create(kEpollInitialSize)); |
| 109 if (epoll_fd_ == -1) { |
| 110 FATAL("Failed creating epoll file descriptor"); |
| 111 } |
| 112 // Register the interrupt_fd with the epoll instance. |
| 113 struct epoll_event event; |
| 114 event.events = EPOLLIN; |
| 115 event.data.ptr = NULL; |
| 116 int status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, |
| 117 EPOLL_CTL_ADD, |
| 118 interrupt_fds_[0], |
| 119 &event)); |
| 120 if (status == -1) { |
| 121 FATAL("Failed adding interrupt fd to epoll instance"); |
| 122 } |
| 63 } | 123 } |
| 64 | 124 |
| 65 | 125 |
| 66 EventHandlerImplementation::~EventHandlerImplementation() { | 126 EventHandlerImplementation::~EventHandlerImplementation() { |
| 67 TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 127 TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
| 68 TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 128 TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
| 69 } | 129 } |
| 70 | 130 |
| 71 | 131 |
| 72 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { | 132 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { |
| 73 ASSERT(fd >= 0); | 133 ASSERT(fd >= 0); |
| 74 HashMap::Entry* entry = socket_map_.Lookup( | 134 HashMap::Entry* entry = socket_map_.Lookup( |
| 75 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 135 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); |
| 76 ASSERT(entry != NULL); | 136 ASSERT(entry != NULL); |
| 77 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); | 137 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); |
| 78 if (sd == NULL) { | 138 if (sd == NULL) { |
| 79 // If there is no data in the hash map for this file descriptor | 139 // If there is no data in the hash map for this file descriptor a |
| 80 // then this is inserting a new SocketData for the file descriptor. | 140 // new SocketData for the file descriptor is inserted. |
| 81 sd = new SocketData(fd); | 141 sd = new SocketData(fd); |
| 82 entry->value = sd; | 142 entry->value = sd; |
| 83 } | 143 } |
| 84 ASSERT(fd == sd->fd()); | 144 ASSERT(fd == sd->fd()); |
| 85 return sd; | 145 return sd; |
| 86 } | 146 } |
| 87 | 147 |
| 88 | 148 |
| 89 void EventHandlerImplementation::WakeupHandler(intptr_t id, | 149 void EventHandlerImplementation::WakeupHandler(intptr_t id, |
| 90 Dart_Port dart_port, | 150 Dart_Port dart_port, |
| 91 int64_t data) { | 151 int64_t data) { |
| 92 InterruptMessage msg; | 152 InterruptMessage msg; |
| 93 msg.id = id; | 153 msg.id = id; |
| 94 msg.dart_port = dart_port; | 154 msg.dart_port = dart_port; |
| 95 msg.data = data; | 155 msg.data = data; |
| 96 intptr_t result = | 156 intptr_t result = |
| 97 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); | 157 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); |
| 98 if (result != kInterruptMessageSize) { | 158 if (result != kInterruptMessageSize) { |
| 99 if (result == -1) { | 159 if (result == -1) { |
| 100 perror("Interrupt message failure:"); | 160 perror("Interrupt message failure:"); |
| 101 } | 161 } |
| 102 FATAL1("Interrupt message failure. Wrote %d bytes.", result); | 162 FATAL1("Interrupt message failure. Wrote %d bytes.", result); |
| 103 } | 163 } |
| 104 } | 164 } |
| 105 | 165 |
| 106 | 166 |
| 107 struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) { | |
| 108 struct pollfd* pollfds; | |
| 109 | |
| 110 // Calculate the number of file descriptors to poll on. | |
| 111 intptr_t numPollfds = 1; | |
| 112 for (HashMap::Entry* entry = socket_map_.Start(); | |
| 113 entry != NULL; | |
| 114 entry = socket_map_.Next(entry)) { | |
| 115 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); | |
| 116 if (sd->port() > 0 && sd->GetPollEvents() != 0) numPollfds++; | |
| 117 } | |
| 118 | |
| 119 pollfds = reinterpret_cast<struct pollfd*>(calloc(sizeof(struct pollfd), | |
| 120 numPollfds)); | |
| 121 pollfds[0].fd = interrupt_fds_[0]; | |
| 122 pollfds[0].events |= POLLIN; | |
| 123 | |
| 124 int i = 1; | |
| 125 for (HashMap::Entry* entry = socket_map_.Start(); | |
| 126 entry != NULL; | |
| 127 entry = socket_map_.Next(entry)) { | |
| 128 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); | |
| 129 intptr_t events = sd->GetPollEvents(); | |
| 130 if (sd->port() > 0 && events != 0) { | |
| 131 // Fd is added to the poll set. | |
| 132 pollfds[i].fd = sd->fd(); | |
| 133 pollfds[i].events = events; | |
| 134 i++; | |
| 135 } | |
| 136 } | |
| 137 ASSERT(numPollfds == i); | |
| 138 *pollfds_size = i; | |
| 139 | |
| 140 return pollfds; | |
| 141 } | |
| 142 | |
| 143 | |
| 144 bool EventHandlerImplementation::GetInterruptMessage(InterruptMessage* msg) { | 167 bool EventHandlerImplementation::GetInterruptMessage(InterruptMessage* msg) { |
| 145 int total_read = 0; | 168 int total_read = 0; |
| 146 int bytes_read = | 169 int bytes_read = |
| 147 TEMP_FAILURE_RETRY(read(interrupt_fds_[0], msg, kInterruptMessageSize)); | 170 TEMP_FAILURE_RETRY(read(interrupt_fds_[0], msg, kInterruptMessageSize)); |
| 148 if (bytes_read < 0) { | 171 if (bytes_read < 0) { |
| 149 return false; | 172 return false; |
| 150 } | 173 } |
| 151 total_read = bytes_read; | 174 total_read = bytes_read; |
| 152 while (total_read < kInterruptMessageSize) { | 175 while (total_read < kInterruptMessageSize) { |
| 153 bytes_read = TEMP_FAILURE_RETRY(read(interrupt_fds_[0], | 176 bytes_read = TEMP_FAILURE_RETRY(read(interrupt_fds_[0], |
| (...skipping 11 matching lines...) Expand all Loading... |
| 165 while (GetInterruptMessage(&msg)) { | 188 while (GetInterruptMessage(&msg)) { |
| 166 if (msg.id == kTimerId) { | 189 if (msg.id == kTimerId) { |
| 167 timeout_ = msg.data; | 190 timeout_ = msg.data; |
| 168 timeout_port_ = msg.dart_port; | 191 timeout_port_ = msg.dart_port; |
| 169 } else { | 192 } else { |
| 170 SocketData* sd = GetSocketData(msg.id); | 193 SocketData* sd = GetSocketData(msg.id); |
| 171 if ((msg.data & (1 << kShutdownReadCommand)) != 0) { | 194 if ((msg.data & (1 << kShutdownReadCommand)) != 0) { |
| 172 ASSERT(msg.data == (1 << kShutdownReadCommand)); | 195 ASSERT(msg.data == (1 << kShutdownReadCommand)); |
| 173 // Close the socket for reading. | 196 // Close the socket for reading. |
| 174 sd->ShutdownRead(); | 197 sd->ShutdownRead(); |
| 198 UpdateEpollInstance(epoll_fd_, sd); |
| 175 } else if ((msg.data & (1 << kShutdownWriteCommand)) != 0) { | 199 } else if ((msg.data & (1 << kShutdownWriteCommand)) != 0) { |
| 176 ASSERT(msg.data == (1 << kShutdownWriteCommand)); | 200 ASSERT(msg.data == (1 << kShutdownWriteCommand)); |
| 177 // Close the socket for writing. | 201 // Close the socket for writing. |
| 178 sd->ShutdownWrite(); | 202 sd->ShutdownWrite(); |
| 203 UpdateEpollInstance(epoll_fd_, sd); |
| 179 } else if ((msg.data & (1 << kCloseCommand)) != 0) { | 204 } else if ((msg.data & (1 << kCloseCommand)) != 0) { |
| 180 ASSERT(msg.data == (1 << kCloseCommand)); | 205 ASSERT(msg.data == (1 << kCloseCommand)); |
| 181 // Close the socket and free system resources. | 206 // Close the socket and free system resources and move on to |
| 207 // next message. |
| 208 RemoveFromEpollInstance(epoll_fd_, sd); |
| 182 intptr_t fd = sd->fd(); | 209 intptr_t fd = sd->fd(); |
| 183 sd->Close(); | 210 sd->Close(); |
| 184 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | 211 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
| 185 delete sd; | 212 delete sd; |
| 186 } else { | 213 } else { |
| 187 // Setup events to wait for. | 214 // Setup events to wait for. |
| 188 sd->SetPortAndMask(msg.dart_port, msg.data); | 215 sd->SetPortAndMask(msg.dart_port, msg.data); |
| 216 UpdateEpollInstance(epoll_fd_, sd); |
| 189 } | 217 } |
| 190 } | 218 } |
| 191 } | 219 } |
| 192 } | 220 } |
| 193 | 221 |
| 194 #ifdef DEBUG_POLL | 222 #ifdef DEBUG_POLL |
| 195 static void PrintEventMask(struct pollfd* pollfd) { | 223 static void PrintEventMask(intptr_t fd, intptr_t events) { |
| 196 printf("%d ", pollfd->fd); | 224 printf("%d ", fd); |
| 197 if ((pollfd->revents & POLLIN) != 0) printf("POLLIN "); | 225 if ((events & EPOLLIN) != 0) printf("EPOLLIN "); |
| 198 if ((pollfd->revents & POLLPRI) != 0) printf("POLLPRI "); | 226 if ((events & EPOLLPRI) != 0) printf("EPOLLPRI "); |
| 199 if ((pollfd->revents & POLLOUT) != 0) printf("POLLOUT "); | 227 if ((events & EPOLLOUT) != 0) printf("EPOLLOUT "); |
| 200 if ((pollfd->revents & POLLERR) != 0) printf("POLLERR "); | 228 if ((events & EPOLLERR) != 0) printf("EPOLLERR "); |
| 201 if ((pollfd->revents & POLLHUP) != 0) printf("POLLHUP "); | 229 if ((events & EPOLLHUP) != 0) printf("EPOLLHUP "); |
| 202 if ((pollfd->revents & POLLRDHUP) != 0) printf("POLLRDHUP "); | 230 if ((events & EPOLLRDHUP) != 0) printf("EPOLLRDHUP "); |
| 203 if ((pollfd->revents & POLLNVAL) != 0) printf("POLLNVAL "); | 231 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT | |
| 204 int all_events = POLLIN | POLLPRI | POLLOUT | | 232 EPOLLERR | EPOLLHUP | EPOLLRDHUP; |
| 205 POLLERR | POLLHUP | POLLRDHUP | POLLNVAL; | 233 if ((events & ~all_events) != 0) { |
| 206 if ((pollfd->revents & ~all_events) != 0) { | 234 printf("(and %08x) ", events & ~all_events); |
| 207 printf("(and %08x) ", pollfd->revents & ~all_events); | |
| 208 } | 235 } |
| 209 printf("(available %d) ", FDUtils::AvailableBytes(pollfd->fd)); | 236 printf("(available %d) ", FDUtils::AvailableBytes(fd)); |
| 210 | 237 |
| 211 printf("\n"); | 238 printf("\n"); |
| 212 } | 239 } |
| 213 #endif | 240 #endif |
| 214 | 241 |
| 215 intptr_t EventHandlerImplementation::GetPollEvents(struct pollfd* pollfd) { | 242 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events, |
| 243 SocketData* sd) { |
| 216 #ifdef DEBUG_POLL | 244 #ifdef DEBUG_POLL |
| 217 if (pollfd->fd != interrupt_fds_[0]) PrintEventMask(pollfd); | 245 PrintEventMask(sd->fd(), events); |
| 218 #endif | 246 #endif |
| 219 intptr_t event_mask = 0; | 247 intptr_t event_mask = 0; |
| 220 SocketData* sd = GetSocketData(pollfd->fd); | |
| 221 if (sd->IsListeningSocket()) { | 248 if (sd->IsListeningSocket()) { |
| 222 // For listening sockets the POLLIN event indicate that there are | 249 // For listening sockets the EPOLLIN event indicate that there are |
| 223 // connections ready for accept unless accompanied with one of the | 250 // connections ready for accept unless accompanied with one of the |
| 224 // other flags. | 251 // other flags. |
| 225 if ((pollfd->revents & POLLIN) != 0) { | 252 if ((events & EPOLLIN) != 0) { |
| 226 if ((pollfd->revents & POLLHUP) != 0) event_mask |= (1 << kCloseEvent); | 253 if ((events & EPOLLHUP) != 0) event_mask |= (1 << kCloseEvent); |
| 227 if ((pollfd->revents & POLLERR) != 0) event_mask |= (1 << kErrorEvent); | 254 if ((events & EPOLLERR) != 0) event_mask |= (1 << kErrorEvent); |
| 228 if (event_mask == 0) event_mask |= (1 << kInEvent); | 255 if (event_mask == 0) event_mask |= (1 << kInEvent); |
| 229 } | 256 } |
| 230 } else { | 257 } else { |
| 231 if ((pollfd->revents & POLLNVAL) != 0) { | |
| 232 return 0; | |
| 233 } | |
| 234 | |
| 235 // Prioritize data events over close and error events. | 258 // Prioritize data events over close and error events. |
| 236 if ((pollfd->revents & POLLIN) != 0) { | 259 if ((events & EPOLLIN) != 0) { |
| 237 if (FDUtils::AvailableBytes(pollfd->fd) != 0) { | 260 if (FDUtils::AvailableBytes(sd->fd()) != 0) { |
| 238 event_mask = (1 << kInEvent); | 261 event_mask = (1 << kInEvent); |
| 239 } else if (((pollfd->revents & POLLHUP) != 0)) { | 262 } else if (((events & EPOLLHUP) != 0)) { |
| 240 event_mask = (1 << kCloseEvent); | 263 event_mask = (1 << kCloseEvent); |
| 241 sd->MarkClosedRead(); | 264 sd->MarkClosedRead(); |
| 242 } else if ((pollfd->revents & POLLERR) != 0) { | 265 } else if ((events & EPOLLERR) != 0) { |
| 243 event_mask = (1 << kErrorEvent); | 266 event_mask = (1 << kErrorEvent); |
| 244 } else { | 267 } else { |
| 245 if (sd->IsPipe()) { | 268 if (sd->IsPipe()) { |
| 246 // When reading from stdin (either from a terminal or piped | 269 // When reading from stdin (either from a terminal or piped |
| 247 // input) treat POLLIN with 0 available bytes as | 270 // input) treat EPOLLIN with 0 available bytes as |
| 248 // end-of-file. | 271 // end-of-file. |
| 249 if (sd->fd() == STDIN_FILENO) { | 272 if (sd->fd() == STDIN_FILENO) { |
| 250 event_mask = (1 << kCloseEvent); | 273 event_mask = (1 << kCloseEvent); |
| 251 sd->MarkClosedRead(); | 274 sd->MarkClosedRead(); |
| 252 } | 275 } |
| 253 } else { | 276 } else { |
| 254 // If POLLIN is set with no available data and no POLLHUP use | 277 // If EPOLLIN is set with no available data and no EPOLLHUP use |
| 255 // recv to peek for whether the other end of the socket | 278 // recv to peek for whether the other end of the socket |
| 256 // actually closed. | 279 // actually closed. |
| 257 char buffer; | 280 char buffer; |
| 258 ssize_t bytesPeeked = | 281 ssize_t bytesPeeked = |
| 259 TEMP_FAILURE_RETRY(recv(sd->fd(), &buffer, 1, MSG_PEEK)); | 282 TEMP_FAILURE_RETRY(recv(sd->fd(), &buffer, 1, MSG_PEEK)); |
| 260 ASSERT(EAGAIN == EWOULDBLOCK); | 283 ASSERT(EAGAIN == EWOULDBLOCK); |
| 261 if (bytesPeeked == 0) { | 284 if (bytesPeeked == 0) { |
| 262 event_mask = (1 << kCloseEvent); | 285 event_mask = (1 << kCloseEvent); |
| 263 sd->MarkClosedRead(); | 286 sd->MarkClosedRead(); |
| 264 } else if (errno != EWOULDBLOCK) { | 287 } else if (errno != EWOULDBLOCK) { |
| 265 fprintf(stderr, "Error recv: %s\n", strerror(errno)); | 288 fprintf(stderr, "Error recv: %s\n", strerror(errno)); |
| 266 } | 289 } |
| 267 } | 290 } |
| 268 } | 291 } |
| 269 } | 292 } |
| 270 | 293 |
| 271 // On pipes POLLHUP is reported without POLLIN when there is no | 294 // On pipes EPOLLHUP is reported without EPOLLIN when there is no |
| 272 // more data to read. | 295 // more data to read. |
| 273 if (sd->IsPipe()) { | 296 if (sd->IsPipe()) { |
| 274 if (((pollfd->revents & POLLIN) == 0) && | 297 if (((events & EPOLLIN) == 0) && |
| 275 ((pollfd->revents & POLLHUP) != 0)) { | 298 ((events & EPOLLHUP) != 0)) { |
| 276 event_mask = (1 << kCloseEvent); | 299 event_mask = (1 << kCloseEvent); |
| 277 sd->MarkClosedRead(); | 300 sd->MarkClosedRead(); |
| 278 } | 301 } |
| 279 } | 302 } |
| 280 | 303 |
| 281 if ((pollfd->revents & POLLOUT) != 0) { | 304 if ((events & EPOLLOUT) != 0) { |
| 282 if ((pollfd->revents & POLLERR) != 0) { | 305 if ((events & EPOLLERR) != 0) { |
| 283 event_mask = (1 << kErrorEvent); | 306 event_mask = (1 << kErrorEvent); |
| 284 sd->MarkClosedWrite(); | 307 sd->MarkClosedWrite(); |
| 285 } else { | 308 } else { |
| 286 event_mask |= (1 << kOutEvent); | 309 event_mask |= (1 << kOutEvent); |
| 287 } | 310 } |
| 288 } | 311 } |
| 289 } | 312 } |
| 290 | 313 |
| 291 return event_mask; | 314 return event_mask; |
| 292 } | 315 } |
| 293 | 316 |
| 294 | 317 |
| 295 void EventHandlerImplementation::HandleEvents(struct pollfd* pollfds, | 318 void EventHandlerImplementation::HandleEvents(struct epoll_event* events, |
| 296 int pollfds_size, | 319 int size) { |
| 297 int result_size) { | 320 for (int i = 0; i < size; i++) { |
| 298 if ((pollfds[0].revents & POLLIN) != 0) { | 321 if (events[i].data.ptr != NULL) { |
| 299 result_size -= 1; | 322 SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr); |
| 300 } | 323 intptr_t event_mask = GetPollEvents(events[i].events, sd); |
| 301 if (result_size > 0) { | |
| 302 for (int i = 1; i < pollfds_size; i++) { | |
| 303 /* | |
| 304 * The fd is unregistered. It gets re-registered when the request | |
| 305 * was handled by dart. | |
| 306 */ | |
| 307 intptr_t event_mask = GetPollEvents(&pollfds[i]); | |
| 308 if (event_mask != 0) { | 324 if (event_mask != 0) { |
| 309 intptr_t fd = pollfds[i].fd; | 325 // Unregister events for the file descriptor. Events will be |
| 310 SocketData* sd = GetSocketData(fd); | 326 // registered again when the current event has been handled in |
| 327 // Dart code. |
| 328 RemoveFromEpollInstance(epoll_fd_, sd); |
| 311 Dart_Port port = sd->port(); | 329 Dart_Port port = sd->port(); |
| 312 ASSERT(port != 0); | 330 ASSERT(port != 0); |
| 313 sd->Unregister(); | |
| 314 Dart_PostIntArray(port, 1, &event_mask); | 331 Dart_PostIntArray(port, 1, &event_mask); |
| 315 } | 332 } |
| 316 } | 333 } |
| 317 } | 334 } |
| 318 HandleInterruptFd(); | 335 HandleInterruptFd(); |
| 319 } | 336 } |
| 320 | 337 |
| 321 | 338 |
| 322 intptr_t EventHandlerImplementation::GetTimeout() { | 339 intptr_t EventHandlerImplementation::GetTimeout() { |
| 323 if (timeout_ == kInfinityTimeout) { | 340 if (timeout_ == kInfinityTimeout) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 334 if (millis <= 0) { | 351 if (millis <= 0) { |
| 335 Dart_PostIntArray(timeout_port_, 0, NULL); | 352 Dart_PostIntArray(timeout_port_, 0, NULL); |
| 336 timeout_ = kInfinityTimeout; | 353 timeout_ = kInfinityTimeout; |
| 337 timeout_port_ = 0; | 354 timeout_port_ = 0; |
| 338 } | 355 } |
| 339 } | 356 } |
| 340 } | 357 } |
| 341 | 358 |
| 342 | 359 |
| 343 void EventHandlerImplementation::Poll(uword args) { | 360 void EventHandlerImplementation::Poll(uword args) { |
| 344 intptr_t pollfds_size; | 361 static const intptr_t kMaxEvents = 16; |
| 345 struct pollfd* pollfds; | 362 struct epoll_event events[kMaxEvents]; |
| 346 EventHandlerImplementation* handler = | 363 EventHandlerImplementation* handler = |
| 347 reinterpret_cast<EventHandlerImplementation*>(args); | 364 reinterpret_cast<EventHandlerImplementation*>(args); |
| 348 ASSERT(handler != NULL); | 365 ASSERT(handler != NULL); |
| 349 while (1) { | 366 while (1) { |
| 350 pollfds = handler->GetPollFds(&pollfds_size); | |
| 351 intptr_t millis = handler->GetTimeout(); | 367 intptr_t millis = handler->GetTimeout(); |
| 352 intptr_t result = TEMP_FAILURE_RETRY(poll(pollfds, pollfds_size, millis)); | 368 intptr_t result = TEMP_FAILURE_RETRY(epoll_wait(handler->epoll_fd_, |
| 369 events, |
| 370 kMaxEvents, |
| 371 millis)); |
| 353 ASSERT(EAGAIN == EWOULDBLOCK); | 372 ASSERT(EAGAIN == EWOULDBLOCK); |
| 354 if (result == -1) { | 373 if (result == -1) { |
| 355 if (errno != EWOULDBLOCK) { | 374 if (errno != EWOULDBLOCK) { |
| 356 perror("Poll failed"); | 375 perror("Poll failed"); |
| 357 } | 376 } |
| 358 } else { | 377 } else { |
| 359 handler->HandleTimeout(); | 378 handler->HandleTimeout(); |
| 360 handler->HandleEvents(pollfds, pollfds_size, result); | 379 handler->HandleEvents(events, result); |
| 361 } | 380 } |
| 362 free(pollfds); | |
| 363 } | 381 } |
| 364 } | 382 } |
| 365 | 383 |
| 366 | 384 |
| 367 void EventHandlerImplementation::StartEventHandler() { | 385 void EventHandlerImplementation::StartEventHandler() { |
| 368 int result = dart::Thread::Start(&EventHandlerImplementation::Poll, | 386 int result = dart::Thread::Start(&EventHandlerImplementation::Poll, |
| 369 reinterpret_cast<uword>(this)); | 387 reinterpret_cast<uword>(this)); |
| 370 if (result != 0) { | 388 if (result != 0) { |
| 371 FATAL1("Failed to start event handler thread %d", result); | 389 FATAL1("Failed to start event handler thread %d", result); |
| 372 } | 390 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 383 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { | 401 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { |
| 384 // The hashmap does not support keys with value 0. | 402 // The hashmap does not support keys with value 0. |
| 385 return reinterpret_cast<void*>(fd + 1); | 403 return reinterpret_cast<void*>(fd + 1); |
| 386 } | 404 } |
| 387 | 405 |
| 388 | 406 |
| 389 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { | 407 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { |
| 390 // The hashmap does not support keys with value 0. | 408 // The hashmap does not support keys with value 0. |
| 391 return dart::Utils::WordHash(fd + 1); | 409 return dart::Utils::WordHash(fd + 1); |
| 392 } | 410 } |
| OLD | NEW |