Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: runtime/bin/eventhandler_linux.cc

Issue 9332003: Use epoll for the event handler on Linux. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/eventhandler_linux.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/eventhandler_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698