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

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

Issue 198743002: Make the event-handler handle backpreasure. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Doc fix Created 6 years, 9 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_android.h ('k') | runtime/bin/eventhandler_linux.h » ('j') | 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 "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 9
10 #include <errno.h> // NOLINT 10 #include <errno.h> // NOLINT
(...skipping 22 matching lines...) Expand all
33 33
34 namespace dart { 34 namespace dart {
35 namespace bin { 35 namespace bin {
36 36
37 static const int kInterruptMessageSize = sizeof(InterruptMessage); 37 static const int kInterruptMessageSize = sizeof(InterruptMessage);
38 static const int kInfinityTimeout = -1; 38 static const int kInfinityTimeout = -1;
39 static const int kTimerId = -1; 39 static const int kTimerId = -1;
40 static const int kShutdownId = -2; 40 static const int kShutdownId = -2;
41 41
42 42
43 intptr_t SocketData::GetPollEvents() {
44 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
45 // triggered anyway.
46 intptr_t events = EPOLLET | EPOLLRDHUP;
47 if ((mask_ & (1 << kInEvent)) != 0) {
48 events |= EPOLLIN;
49 }
50 if ((mask_ & (1 << kOutEvent)) != 0) {
51 events |= EPOLLOUT;
52 }
53 return events;
54 }
55
56
43 // Unregister the file descriptor for a SocketData structure with epoll. 57 // Unregister the file descriptor for a SocketData structure with epoll.
44 static void RemoveFromEpollInstance(intptr_t epoll_fd_, SocketData* sd) { 58 static void RemoveFromEpollInstance(intptr_t epoll_fd_, SocketData* sd) {
45 if (!sd->tracked_by_epoll()) return; 59 VOID_TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_,
46 int status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, 60 EPOLL_CTL_DEL,
47 EPOLL_CTL_DEL, 61 sd->fd(),
48 sd->fd(), 62 NULL));
49 NULL));
50 if (status == -1) {
51 FATAL("Failed unregistering events for file descriptor");
52 }
53 sd->set_tracked_by_epoll(false);
54 } 63 }
55 64
56 65
57 static void AddToEpollInstance(intptr_t epoll_fd_, SocketData* sd) { 66 static void AddToEpollInstance(intptr_t epoll_fd_, SocketData* sd) {
58 ASSERT(!sd->tracked_by_epoll());
59 struct epoll_event event; 67 struct epoll_event event;
60 event.events = EPOLLET | EPOLLRDHUP; 68 event.events = sd->GetPollEvents();
61 if ((sd->mask() & (1 << kInEvent)) != 0) event.events |= EPOLLIN;
62 if ((sd->mask() & (1 << kOutEvent)) != 0) event.events |= EPOLLOUT;
63 event.data.ptr = sd; 69 event.data.ptr = sd;
64 int status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, 70 int status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_,
65 EPOLL_CTL_ADD, 71 EPOLL_CTL_ADD,
66 sd->fd(), 72 sd->fd(),
67 &event)); 73 &event));
68 if (status == -1) { 74 if (status == -1) {
69 // Epoll does not accept the file descriptor. It could be due to 75 // Epoll does not accept the file descriptor. It could be due to
70 // already closed file descriptor, or unuspported devices, such 76 // already closed file descriptor, or unuspported devices, such
71 // as /dev/null. In such case, mark the file descriptor as closed, 77 // as /dev/null. In such case, mark the file descriptor as closed,
72 // so dart will handle it accordingly. 78 // so dart will handle it accordingly.
73 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); 79 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent);
74 } else {
75 sd->set_tracked_by_epoll(true);
76 } 80 }
77 } 81 }
78 82
79 83
80 EventHandlerImplementation::EventHandlerImplementation() 84 EventHandlerImplementation::EventHandlerImplementation()
81 : socket_map_(&HashMap::SamePointerValue, 16) { 85 : socket_map_(&HashMap::SamePointerValue, 16) {
82 intptr_t result; 86 intptr_t result;
83 result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_)); 87 result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_));
84 if (result != 0) { 88 if (result != 0) {
85 FATAL("Pipe creation failed"); 89 FATAL("Pipe creation failed");
(...skipping 23 matching lines...) Expand all
109 } 113 }
110 } 114 }
111 115
112 116
113 EventHandlerImplementation::~EventHandlerImplementation() { 117 EventHandlerImplementation::~EventHandlerImplementation() {
114 TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); 118 TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
115 TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); 119 TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
116 } 120 }
117 121
118 122
119 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd, 123 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) {
120 bool* is_new) {
121 ASSERT(fd >= 0); 124 ASSERT(fd >= 0);
122 HashMap::Entry* entry = socket_map_.Lookup( 125 HashMap::Entry* entry = socket_map_.Lookup(
123 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); 126 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
124 ASSERT(entry != NULL); 127 ASSERT(entry != NULL);
125 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); 128 SocketData* sd = reinterpret_cast<SocketData*>(entry->value);
126 if (sd == NULL) { 129 if (sd == NULL) {
127 // If there is no data in the hash map for this file descriptor a 130 // If there is no data in the hash map for this file descriptor a
128 // new SocketData for the file descriptor is inserted. 131 // new SocketData for the file descriptor is inserted.
129 sd = new SocketData(fd); 132 sd = new SocketData(fd);
130 entry->value = sd; 133 entry->value = sd;
131 *is_new = true;
132 } 134 }
133 ASSERT(fd == sd->fd()); 135 ASSERT(fd == sd->fd());
134 return sd; 136 return sd;
135 } 137 }
136 138
137 139
138 void EventHandlerImplementation::WakeupHandler(intptr_t id, 140 void EventHandlerImplementation::WakeupHandler(intptr_t id,
139 Dart_Port dart_port, 141 Dart_Port dart_port,
140 int64_t data) { 142 int64_t data) {
141 InterruptMessage msg; 143 InterruptMessage msg;
(...skipping 19 matching lines...) Expand all
161 const intptr_t MAX_MESSAGES = kInterruptMessageSize; 163 const intptr_t MAX_MESSAGES = kInterruptMessageSize;
162 InterruptMessage msg[MAX_MESSAGES]; 164 InterruptMessage msg[MAX_MESSAGES];
163 ssize_t bytes = TEMP_FAILURE_RETRY( 165 ssize_t bytes = TEMP_FAILURE_RETRY(
164 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); 166 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize));
165 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { 167 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) {
166 if (msg[i].id == kTimerId) { 168 if (msg[i].id == kTimerId) {
167 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); 169 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data);
168 } else if (msg[i].id == kShutdownId) { 170 } else if (msg[i].id == kShutdownId) {
169 shutdown_ = true; 171 shutdown_ = true;
170 } else { 172 } else {
171 bool is_new = false; 173 SocketData* sd = GetSocketData(msg[i].id);
172 SocketData* sd = GetSocketData(msg[i].id, &is_new);
173 if (is_new) {
174 sd->SetPortAndMask(msg[i].dart_port, msg[i].data);
175 AddToEpollInstance(epoll_fd_, sd);
176 }
177 if ((msg[i].data & (1 << kShutdownReadCommand)) != 0) { 174 if ((msg[i].data & (1 << kShutdownReadCommand)) != 0) {
178 ASSERT(msg[i].data == (1 << kShutdownReadCommand)); 175 ASSERT(msg[i].data == (1 << kShutdownReadCommand));
179 // Close the socket for reading. 176 // Close the socket for reading.
180 sd->ShutdownRead(); 177 shutdown(sd->fd(), SHUT_RD);
181 } else if ((msg[i].data & (1 << kShutdownWriteCommand)) != 0) { 178 } else if ((msg[i].data & (1 << kShutdownWriteCommand)) != 0) {
182 ASSERT(msg[i].data == (1 << kShutdownWriteCommand)); 179 ASSERT(msg[i].data == (1 << kShutdownWriteCommand));
183 // Close the socket for writing. 180 // Close the socket for writing.
184 sd->ShutdownWrite(); 181 shutdown(sd->fd(), SHUT_WR);
185 } else if ((msg[i].data & (1 << kCloseCommand)) != 0) { 182 } else if ((msg[i].data & (1 << kCloseCommand)) != 0) {
186 ASSERT(msg[i].data == (1 << kCloseCommand)); 183 ASSERT(msg[i].data == (1 << kCloseCommand));
187 // Close the socket and free system resources and move on to 184 // Close the socket and free system resources and move on to
188 // next message. 185 // next message.
189 RemoveFromEpollInstance(epoll_fd_, sd); 186 RemoveFromEpollInstance(epoll_fd_, sd);
190 intptr_t fd = sd->fd(); 187 intptr_t fd = sd->fd();
191 sd->Close(); 188 sd->Close();
192 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); 189 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
193 delete sd; 190 delete sd;
194 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); 191 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent);
192 } else if ((msg[i].data & (1 << kReturnTokenCommand)) != 0) {
193 if (sd->ReturnToken()) {
194 AddToEpollInstance(epoll_fd_, sd);
195 }
196 } else {
197 // Setup events to wait for.
198 sd->SetPortAndMask(msg[i].dart_port, msg[i].data);
199 AddToEpollInstance(epoll_fd_, sd);
195 } 200 }
196 } 201 }
197 } 202 }
198 } 203 }
199 204
200 #ifdef DEBUG_POLL 205 #ifdef DEBUG_POLL
201 static void PrintEventMask(intptr_t fd, intptr_t events) { 206 static void PrintEventMask(intptr_t fd, intptr_t events) {
202 Log::Print("%d ", fd); 207 Log::Print("%d ", fd);
203 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN "); 208 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
204 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI "); 209 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
(...skipping 10 matching lines...) Expand all
215 220
216 Log::Print("\n"); 221 Log::Print("\n");
217 } 222 }
218 #endif 223 #endif
219 224
220 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events, 225 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
221 SocketData* sd) { 226 SocketData* sd) {
222 #ifdef DEBUG_POLL 227 #ifdef DEBUG_POLL
223 PrintEventMask(sd->fd(), events); 228 PrintEventMask(sd->fd(), events);
224 #endif 229 #endif
230 if (events & EPOLLERR) {
231 // Return error only if EPOLLIN is present.
232 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
233 }
225 intptr_t event_mask = 0; 234 intptr_t event_mask = 0;
226 if (sd->IsListeningSocket()) { 235 if (events & EPOLLIN) event_mask |= (1 << kInEvent);
227 // For listening sockets the EPOLLIN event indicate that there are 236 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
228 // connections ready for accept unless accompanied with one of the 237 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
229 // other flags.
230 if ((events & EPOLLIN) != 0) {
231 if ((events & EPOLLHUP) != 0) event_mask |= (1 << kCloseEvent);
232 if ((events & EPOLLERR) != 0) event_mask |= (1 << kErrorEvent);
233 if (event_mask == 0) event_mask |= (1 << kInEvent);
234 }
235 } else {
236 // Prioritize data events over close and error events.
237 if ((events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP)) != 0) {
238 // If we have EPOLLIN and we have available bytes, report that.
239 if ((events & EPOLLIN) != 0) {
240 event_mask = (1 << kInEvent);
241 }
242 if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
243 // If both EPOLLHUP and EPOLLERR are reported treat it as an
244 // error.
245 if ((events & EPOLLERR) != 0) {
246 event_mask = (1 << kErrorEvent);
247 } else {
248 event_mask |= (1 << kCloseEvent);
249 }
250 } else if ((events & EPOLLERR) != 0) {
251 event_mask = (1 << kErrorEvent);
252 }
253 }
254
255 if ((events & EPOLLOUT) != 0) {
256 if ((events & EPOLLERR) != 0) {
257 if (!sd->IsPipe()) {
258 event_mask = (1 << kErrorEvent);
259 }
260 } else {
261 event_mask |= (1 << kOutEvent);
262 }
263 }
264 }
265
266 return event_mask; 238 return event_mask;
267 } 239 }
268 240
269 241
270 void EventHandlerImplementation::HandleEvents(struct epoll_event* events, 242 void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
271 int size) { 243 int size) {
272 bool interrupt_seen = false; 244 bool interrupt_seen = false;
273 for (int i = 0; i < size; i++) { 245 for (int i = 0; i < size; i++) {
274 if (events[i].data.ptr == NULL) { 246 if (events[i].data.ptr == NULL) {
275 interrupt_seen = true; 247 interrupt_seen = true;
276 } else { 248 } else {
277 SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr); 249 SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr);
278 intptr_t event_mask = GetPollEvents(events[i].events, sd); 250 intptr_t event_mask = GetPollEvents(events[i].events, sd);
279 if (event_mask != 0) { 251 if (event_mask != 0) {
252 if (sd->TakeToken()) {
253 // Took last token, remove from epoll.
254 RemoveFromEpollInstance(epoll_fd_, sd);
255 }
280 Dart_Port port = sd->port(); 256 Dart_Port port = sd->port();
281 ASSERT(port != 0); 257 ASSERT(port != 0);
282 DartUtils::PostInt32(port, event_mask); 258 DartUtils::PostInt32(port, event_mask);
283 } 259 }
284 } 260 }
285 } 261 }
286 if (interrupt_seen) { 262 if (interrupt_seen) {
287 // Handle after socket events, so we avoid closing a socket before we handle 263 // Handle after socket events, so we avoid closing a socket before we handle
288 // the current events. 264 // the current events.
289 HandleInterruptFd(); 265 HandleInterruptFd();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 void EventHandlerImplementation::Start(EventHandler* handler) { 319 void EventHandlerImplementation::Start(EventHandler* handler) {
344 int result = dart::Thread::Start(&EventHandlerImplementation::Poll, 320 int result = dart::Thread::Start(&EventHandlerImplementation::Poll,
345 reinterpret_cast<uword>(handler)); 321 reinterpret_cast<uword>(handler));
346 if (result != 0) { 322 if (result != 0) {
347 FATAL1("Failed to start event handler thread %d", result); 323 FATAL1("Failed to start event handler thread %d", result);
348 } 324 }
349 } 325 }
350 326
351 327
352 void EventHandlerImplementation::Shutdown() { 328 void EventHandlerImplementation::Shutdown() {
353 Notify(kShutdownId, 0, 0); 329 SendData(kShutdownId, 0, 0);
354 } 330 }
355 331
356 332
357 void EventHandlerImplementation::Notify(intptr_t id, 333 void EventHandlerImplementation::SendData(intptr_t id,
358 Dart_Port dart_port, 334 Dart_Port dart_port,
359 intptr_t data) { 335 intptr_t data) {
360 WakeupHandler(id, dart_port, data); 336 WakeupHandler(id, dart_port, data);
361 } 337 }
362 338
363 339
364 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { 340 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) {
365 // The hashmap does not support keys with value 0. 341 // The hashmap does not support keys with value 0.
366 return reinterpret_cast<void*>(fd + 1); 342 return reinterpret_cast<void*>(fd + 1);
367 } 343 }
368 344
369 345
370 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { 346 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) {
371 // The hashmap does not support keys with value 0. 347 // The hashmap does not support keys with value 0.
372 return dart::Utils::WordHash(fd + 1); 348 return dart::Utils::WordHash(fd + 1);
373 } 349 }
374 350
375 } // namespace bin 351 } // namespace bin
376 } // namespace dart 352 } // namespace dart
377 353
378 #endif // defined(TARGET_OS_ANDROID) 354 #endif // defined(TARGET_OS_ANDROID)
OLDNEW
« no previous file with comments | « runtime/bin/eventhandler_android.h ('k') | runtime/bin/eventhandler_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698