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

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

Issue 879353003: Introduce optional 'bool shared' parameter to ServerSocket.bind() ... (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 5 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 | « dart/runtime/bin/eventhandler_android.h ('k') | dart/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 #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
19 #include "bin/dartutils.h" 20 #include "bin/dartutils.h"
20 #include "bin/fdutils.h" 21 #include "bin/fdutils.h"
21 #include "bin/log.h" 22 #include "bin/log.h"
23 #include "bin/lockers.h"
24 #include "bin/socket.h"
22 #include "bin/thread.h" 25 #include "bin/thread.h"
23 #include "bin/utils.h" 26 #include "bin/utils.h"
24 #include "platform/hashmap.h" 27 #include "platform/hashmap.h"
25 #include "platform/utils.h" 28 #include "platform/utils.h"
26 29
27 30
28 // Android doesn't define EPOLLRDHUP. 31 // Android doesn't define EPOLLRDHUP.
29 #if !defined(EPOLLRDHUP) 32 #if !defined(EPOLLRDHUP)
30 #define EPOLLRDHUP 0x2000 33 #define EPOLLRDHUP 0x2000
31 #endif // !defined(EPOLLRDHUP) 34 #endif // !defined(EPOLLRDHUP)
32 35
33 36
34 namespace dart { 37 namespace dart {
35 namespace bin { 38 namespace bin {
36 39
37 static const int kInterruptMessageSize = sizeof(InterruptMessage);
38 static const int kInfinityTimeout = -1;
39 static const int kTimerId = -1;
40 static const int kShutdownId = -2;
41 40
42 41 intptr_t DescriptorInfo::GetPollEvents() {
43 intptr_t SocketData::GetPollEvents() {
44 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are 42 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
45 // triggered anyway. 43 // triggered anyway.
46 intptr_t events = 0; 44 intptr_t events = 0;
47 if ((mask_ & (1 << kInEvent)) != 0) { 45 if ((Mask() & (1 << kInEvent)) != 0) {
48 events |= EPOLLIN; 46 events |= EPOLLIN;
49 } 47 }
50 if ((mask_ & (1 << kOutEvent)) != 0) { 48 if ((Mask() & (1 << kOutEvent)) != 0) {
51 events |= EPOLLOUT; 49 events |= EPOLLOUT;
52 } 50 }
53 return events; 51 return events;
54 } 52 }
55 53
56 54
57 // Unregister the file descriptor for a SocketData structure with epoll. 55 // Unregister the file descriptor for a DescriptorInfo structure with
58 static void RemoveFromEpollInstance(intptr_t epoll_fd_, SocketData* sd) { 56 // epoll.
57 static void RemoveFromEpollInstance(intptr_t epoll_fd_,
58 DescriptorInfo* di) {
59 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, 59 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_,
60 EPOLL_CTL_DEL, 60 EPOLL_CTL_DEL,
61 sd->fd(), 61 di->fd(),
62 NULL)); 62 NULL));
63 } 63 }
64 64
65 65
66 static void AddToEpollInstance(intptr_t epoll_fd_, SocketData* sd) { 66 static void AddToEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) {
67 struct epoll_event event; 67 struct epoll_event event;
68 event.events = EPOLLRDHUP | sd->GetPollEvents(); 68 event.events = EPOLLRDHUP | di->GetPollEvents();
69 if (!sd->IsListeningSocket()) { 69 if (!di->IsListeningSocket()) {
70 event.events |= EPOLLET; 70 event.events |= EPOLLET;
71 } 71 }
72 event.data.ptr = sd; 72 event.data.ptr = di;
73 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, 73 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_,
74 EPOLL_CTL_ADD, 74 EPOLL_CTL_ADD,
75 sd->fd(), 75 di->fd(),
76 &event)); 76 &event));
77 if (status == -1) { 77 if (status == -1) {
78 // TODO(kustermann): Verify that the dart end is handling this correctly &
79 // adapt this code to work for multiple listening sockets.
80
78 // Epoll does not accept the file descriptor. It could be due to 81 // Epoll does not accept the file descriptor. It could be due to
79 // already closed file descriptor, or unuspported devices, such 82 // already closed file descriptor, or unuspported devices, such
80 // as /dev/null. In such case, mark the file descriptor as closed, 83 // as /dev/null. In such case, mark the file descriptor as closed,
81 // so dart will handle it accordingly. 84 // so dart will handle it accordingly.
82 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); 85 DartUtils::PostInt32(di->NextPort(), 1 << kCloseEvent);
83 } 86 }
84 } 87 }
85 88
86 89
87 EventHandlerImplementation::EventHandlerImplementation() 90 EventHandlerImplementation::EventHandlerImplementation()
88 : socket_map_(&HashMap::SamePointerValue, 16) { 91 : socket_map_(&HashMap::SamePointerValue, 16) {
89 intptr_t result; 92 intptr_t result;
90 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); 93 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
91 if (result != 0) { 94 if (result != 0) {
92 FATAL("Pipe creation failed"); 95 FATAL("Pipe creation failed");
93 } 96 }
94 FDUtils::SetNonBlocking(interrupt_fds_[0]); 97 FDUtils::SetNonBlocking(interrupt_fds_[0]);
95 FDUtils::SetCloseOnExec(interrupt_fds_[0]); 98 FDUtils::SetCloseOnExec(interrupt_fds_[0]);
96 FDUtils::SetCloseOnExec(interrupt_fds_[1]); 99 FDUtils::SetCloseOnExec(interrupt_fds_[1]);
97 shutdown_ = false; 100 shutdown_ = false;
98 // The initial size passed to epoll_create is ignore on newer (>= 101 // The initial size passed to epoll_create is ignore on newer (>=
99 // 2.6.8) Linux versions 102 // 2.6.8) Linux versions
100 static const int kEpollInitialSize = 64; 103 static const int kEpollInitialSize = 64;
101 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); 104 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize));
102 if (epoll_fd_ == -1) { 105 if (epoll_fd_ == -1) {
103 FATAL("Failed creating epoll file descriptor"); 106 FATAL1("Failed creating epoll file descriptor: %i", errno);
104 } 107 }
105 FDUtils::SetCloseOnExec(epoll_fd_); 108 FDUtils::SetCloseOnExec(epoll_fd_);
106 // Register the interrupt_fd with the epoll instance. 109 // Register the interrupt_fd with the epoll instance.
107 struct epoll_event event; 110 struct epoll_event event;
108 event.events = EPOLLIN; 111 event.events = EPOLLIN;
109 event.data.ptr = NULL; 112 event.data.ptr = NULL;
110 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, 113 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_,
111 EPOLL_CTL_ADD, 114 EPOLL_CTL_ADD,
112 interrupt_fds_[0], 115 interrupt_fds_[0],
113 &event)); 116 &event));
114 if (status == -1) { 117 if (status == -1) {
115 FATAL("Failed adding interrupt fd to epoll instance"); 118 FATAL("Failed adding interrupt fd to epoll instance");
116 } 119 }
117 } 120 }
118 121
119 122
120 EventHandlerImplementation::~EventHandlerImplementation() { 123 EventHandlerImplementation::~EventHandlerImplementation() {
124 VOID_TEMP_FAILURE_RETRY(close(epoll_fd_));
121 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); 125 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
122 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); 126 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
123 } 127 }
124 128
125 129
126 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { 130 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo(
131 intptr_t fd, bool is_listening) {
127 ASSERT(fd >= 0); 132 ASSERT(fd >= 0);
128 HashMap::Entry* entry = socket_map_.Lookup( 133 HashMap::Entry* entry = socket_map_.Lookup(
129 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); 134 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
130 ASSERT(entry != NULL); 135 ASSERT(entry != NULL);
131 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); 136 DescriptorInfo* di =
132 if (sd == NULL) { 137 reinterpret_cast<DescriptorInfo*>(entry->value);
138 if (di == NULL) {
133 // If there is no data in the hash map for this file descriptor a 139 // If there is no data in the hash map for this file descriptor a
134 // new SocketData for the file descriptor is inserted. 140 // new DescriptorInfo for the file descriptor is inserted.
135 sd = new SocketData(fd); 141 if (is_listening) {
136 entry->value = sd; 142 di = new DescriptorInfoMultiple(fd);
143 } else {
144 di = new DescriptorInfoSingle(fd);
145 }
146 entry->value = di;
137 } 147 }
138 ASSERT(fd == sd->fd()); 148 ASSERT(fd == di->fd());
139 return sd; 149 return di;
140 } 150 }
141 151
142 152
143 void EventHandlerImplementation::WakeupHandler(intptr_t id, 153 void EventHandlerImplementation::WakeupHandler(intptr_t id,
144 Dart_Port dart_port, 154 Dart_Port dart_port,
145 int64_t data) { 155 int64_t data) {
146 InterruptMessage msg; 156 InterruptMessage msg;
147 msg.id = id; 157 msg.id = id;
148 msg.dart_port = dart_port; 158 msg.dart_port = dart_port;
149 msg.data = data; 159 msg.data = data;
150 // WriteToBlocking will write up to 512 bytes atomically, and since our msg 160 // WriteToBlocking will write up to 512 bytes atomically, and since our msg
151 // is smaller than 512, we don't need a thread lock. 161 // is smaller than 512, we don't need a thread lock.
152 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'. 162 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'.
153 ASSERT(kInterruptMessageSize < PIPE_BUF); 163 ASSERT(kInterruptMessageSize < PIPE_BUF);
154 intptr_t result = 164 intptr_t result =
155 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); 165 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize);
156 if (result != kInterruptMessageSize) { 166 if (result != kInterruptMessageSize) {
157 if (result == -1) { 167 if (result == -1) {
158 perror("Interrupt message failure:"); 168 perror("Interrupt message failure:");
159 } 169 }
160 FATAL1("Interrupt message failure. Wrote %d bytes.", result); 170 FATAL1("Interrupt message failure. Wrote %" Pd " bytes.", result);
161 } 171 }
162 } 172 }
163 173
164 174
165 void EventHandlerImplementation::HandleInterruptFd() { 175 void EventHandlerImplementation::HandleInterruptFd() {
166 const intptr_t MAX_MESSAGES = kInterruptMessageSize; 176 const intptr_t MAX_MESSAGES = kInterruptMessageSize;
167 InterruptMessage msg[MAX_MESSAGES]; 177 InterruptMessage msg[MAX_MESSAGES];
168 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( 178 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
169 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); 179 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize));
170 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { 180 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) {
171 if (msg[i].id == kTimerId) { 181 if (msg[i].id == kTimerId) {
172 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); 182 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data);
173 } else if (msg[i].id == kShutdownId) { 183 } else if (msg[i].id == kShutdownId) {
174 shutdown_ = true; 184 shutdown_ = true;
175 } else { 185 } else {
176 SocketData* sd = GetSocketData(msg[i].id); 186 DescriptorInfo* di = GetDescriptorInfo(
187 msg[i].id, (msg[i].data & (1 << kListeningSocket)) != 0);
188 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) {
189 ASSERT(!di->IsListeningSocket());
190 // Close the socket for reading.
191 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD));
192 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) {
193 ASSERT(!di->IsListeningSocket());
194 // Close the socket for writing.
195 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR));
196 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) {
197 // Close the socket and free system resources and move on to next
198 // message.
199 bool no_more_listeners = di->RemovePort(msg[i].dart_port);
200 if (no_more_listeners) {
201 RemoveFromEpollInstance(epoll_fd_, di);
202 }
177 203
178 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { 204 intptr_t fd = di->fd();
179 // Close the socket for reading. 205 if (di->IsListeningSocket()) {
180 shutdown(sd->fd(), SHUT_RD); 206 // We only close the socket file descriptor from the operating
181 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { 207 // system if there are no other dart socket objects which
182 // Close the socket for writing. 208 // are listening on the same (address, port) combination.
183 shutdown(sd->fd(), SHUT_WR); 209 {
184 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { 210 MutexLocker ml(globalTcpListeningSocketRegistry.mutex());
185 // Close the socket and free system resources and move on to 211 if (globalTcpListeningSocketRegistry.CloseSafe(fd)) {
186 // next message. 212 socket_map_.Remove(
187 RemoveFromEpollInstance(epoll_fd_, sd); 213 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
188 intptr_t fd = sd->fd(); 214 di->Close();
189 sd->Close(); 215 delete di;
190 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); 216 }
191 delete sd; 217 }
218 } else {
219 ASSERT(no_more_listeners);
220 socket_map_.Remove(
221 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
222 di->Close();
223 delete di;
224 }
192 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); 225 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent);
193 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { 226 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) {
194 int count = TOKEN_COUNT(msg[i].data); 227 int count = TOKEN_COUNT(msg[i].data);
195 228 if (di->ReturnTokens(msg[i].dart_port, count)) {
196 for (int i = 0; i < count; i++) { 229 AddToEpollInstance(epoll_fd_, di);
197 if (sd->ReturnToken()) {
198 AddToEpollInstance(epoll_fd_, sd);
199 }
200 } 230 }
201 } else { 231 } else {
202 ASSERT_NO_COMMAND(msg[i].data); 232 ASSERT_NO_COMMAND(msg[i].data);
203 // Setup events to wait for. 233 bool had_listeners = di->HasNextPort();
204 sd->SetPortAndMask(msg[i].dart_port, msg[i].data); 234 di->SetPortAndMask(msg[i].dart_port, msg[i].data & EVENT_MASK);
205 AddToEpollInstance(epoll_fd_, sd); 235 bool has_listeners = di->HasNextPort();
236
237 // Add/Remove from epoll set depending on previous and current state.
238 if (!had_listeners && has_listeners) {
239 AddToEpollInstance(epoll_fd_, di);
240 } else if (had_listeners && !has_listeners) {
241 RemoveFromEpollInstance(epoll_fd_, di);
242 }
206 } 243 }
207 } 244 }
208 } 245 }
209 } 246 }
210 247
211 #ifdef DEBUG_POLL 248 #ifdef DEBUG_POLL
212 static void PrintEventMask(intptr_t fd, intptr_t events) { 249 static void PrintEventMask(intptr_t fd, intptr_t events) {
213 Log::Print("%d ", fd); 250 Log::Print("%d ", fd);
214 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN "); 251 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
215 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI "); 252 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
216 if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT "); 253 if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
217 if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR "); 254 if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
218 if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP "); 255 if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
219 if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP "); 256 if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
220 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT | 257 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
221 EPOLLERR | EPOLLHUP | EPOLLRDHUP; 258 EPOLLERR | EPOLLHUP | EPOLLRDHUP;
222 if ((events & ~all_events) != 0) { 259 if ((events & ~all_events) != 0) {
223 Log::Print("(and %08x) ", events & ~all_events); 260 Log::Print("(and %08x) ", events & ~all_events);
224 } 261 }
225 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd)); 262 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd));
226 263
227 Log::Print("\n"); 264 Log::Print("\n");
228 } 265 }
229 #endif 266 #endif
230 267
231 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events, 268 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
232 SocketData* sd) { 269 DescriptorInfo* di) {
233 #ifdef DEBUG_POLL 270 #ifdef DEBUG_POLL
234 PrintEventMask(sd->fd(), events); 271 PrintEventMask(di->fd(), events);
235 #endif 272 #endif
236 if (events & EPOLLERR) { 273 if (events & EPOLLERR) {
237 // Return error only if EPOLLIN is present. 274 // Return error only if EPOLLIN is present.
238 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0; 275 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
239 } 276 }
240 intptr_t event_mask = 0; 277 intptr_t event_mask = 0;
241 if (events & EPOLLIN) event_mask |= (1 << kInEvent); 278 if (events & EPOLLIN) event_mask |= (1 << kInEvent);
242 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent); 279 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
243 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent); 280 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
244 return event_mask; 281 return event_mask;
245 } 282 }
246 283
247 284
248 void EventHandlerImplementation::HandleEvents(struct epoll_event* events, 285 void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
249 int size) { 286 int size) {
250 bool interrupt_seen = false; 287 bool interrupt_seen = false;
251 for (int i = 0; i < size; i++) { 288 for (int i = 0; i < size; i++) {
252 if (events[i].data.ptr == NULL) { 289 if (events[i].data.ptr == NULL) {
253 interrupt_seen = true; 290 interrupt_seen = true;
254 } else { 291 } else {
255 SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr); 292 DescriptorInfo* di =
256 intptr_t event_mask = GetPollEvents(events[i].events, sd); 293 reinterpret_cast<DescriptorInfo*>(events[i].data.ptr);
294 intptr_t event_mask = GetPollEvents(events[i].events, di);
257 if (event_mask != 0) { 295 if (event_mask != 0) {
258 if (sd->TakeToken()) { 296 Dart_Port port = di->NextPort();
297 ASSERT(port != 0);
298 if (di->TakeToken()) {
259 // Took last token, remove from epoll. 299 // Took last token, remove from epoll.
260 RemoveFromEpollInstance(epoll_fd_, sd); 300 RemoveFromEpollInstance(epoll_fd_, di);
261 } 301 }
262 Dart_Port port = sd->port();
263 ASSERT(port != 0);
264 DartUtils::PostInt32(port, event_mask); 302 DartUtils::PostInt32(port, event_mask);
265 } 303 }
266 } 304 }
267 } 305 }
268 if (interrupt_seen) { 306 if (interrupt_seen) {
269 // Handle after socket events, so we avoid closing a socket before we handle 307 // Handle after socket events, so we avoid closing a socket before we handle
270 // the current events. 308 // the current events.
271 HandleInterruptFd(); 309 HandleInterruptFd();
272 } 310 }
273 } 311 }
(...skipping 18 matching lines...) Expand all
292 timeout_queue_.RemoveCurrent(); 330 timeout_queue_.RemoveCurrent();
293 } 331 }
294 } 332 }
295 } 333 }
296 334
297 335
298 void EventHandlerImplementation::Poll(uword args) { 336 void EventHandlerImplementation::Poll(uword args) {
299 ThreadSignalBlocker signal_blocker(SIGPROF); 337 ThreadSignalBlocker signal_blocker(SIGPROF);
300 static const intptr_t kMaxEvents = 16; 338 static const intptr_t kMaxEvents = 16;
301 struct epoll_event events[kMaxEvents]; 339 struct epoll_event events[kMaxEvents];
302 EventHandlerImplementation* handler = 340 EventHandler* handler = reinterpret_cast<EventHandler*>(args);
303 reinterpret_cast<EventHandlerImplementation*>(args); 341 EventHandlerImplementation* handler_impl = &handler->delegate_;
304 ASSERT(handler != NULL); 342 ASSERT(handler_impl != NULL);
305 while (!handler->shutdown_) { 343 while (!handler_impl->shutdown_) {
306 int64_t millis = handler->GetTimeout(); 344 int64_t millis = handler_impl->GetTimeout();
307 ASSERT(millis == kInfinityTimeout || millis >= 0); 345 ASSERT(millis == kInfinityTimeout || millis >= 0);
308 if (millis > kMaxInt32) millis = kMaxInt32; 346 if (millis > kMaxInt32) millis = kMaxInt32;
309 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( 347 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
310 epoll_wait(handler->epoll_fd_, events, kMaxEvents, millis)); 348 epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis));
311 ASSERT(EAGAIN == EWOULDBLOCK); 349 ASSERT(EAGAIN == EWOULDBLOCK);
312 if (result == -1) { 350 if (result == -1) {
313 if (errno != EWOULDBLOCK) { 351 if (errno != EWOULDBLOCK) {
314 perror("Poll failed"); 352 perror("Poll failed");
315 } 353 }
316 } else { 354 } else {
317 handler->HandleTimeout(); 355 handler_impl->HandleTimeout();
318 handler->HandleEvents(events, result); 356 handler_impl->HandleEvents(events, result);
319 } 357 }
320 } 358 }
359 delete handler;
321 } 360 }
322 361
323 362
324 void EventHandlerImplementation::Start(EventHandler* handler) { 363 void EventHandlerImplementation::Start(EventHandler* handler) {
325 int result = Thread::Start(&EventHandlerImplementation::Poll, 364 int result = Thread::Start(&EventHandlerImplementation::Poll,
326 reinterpret_cast<uword>(handler)); 365 reinterpret_cast<uword>(handler));
327 if (result != 0) { 366 if (result != 0) {
328 FATAL1("Failed to start event handler thread %d", result); 367 FATAL1("Failed to start event handler thread %d", result);
329 } 368 }
330 } 369 }
331 370
332 371
333 void EventHandlerImplementation::Shutdown() { 372 void EventHandlerImplementation::Shutdown() {
334 SendData(kShutdownId, 0, 0); 373 SendData(kShutdownId, 0, 0);
335 } 374 }
336 375
337 376
338 void EventHandlerImplementation::SendData(intptr_t id, 377 void EventHandlerImplementation::SendData(intptr_t id,
339 Dart_Port dart_port, 378 Dart_Port dart_port,
340 intptr_t data) { 379 int64_t data) {
341 WakeupHandler(id, dart_port, data); 380 WakeupHandler(id, dart_port, data);
342 } 381 }
343 382
344 383
345 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { 384 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) {
346 // The hashmap does not support keys with value 0. 385 // The hashmap does not support keys with value 0.
347 return reinterpret_cast<void*>(fd + 1); 386 return reinterpret_cast<void*>(fd + 1);
348 } 387 }
349 388
350 389
351 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { 390 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) {
352 // The hashmap does not support keys with value 0. 391 // The hashmap does not support keys with value 0.
353 return dart::Utils::WordHash(fd + 1); 392 return dart::Utils::WordHash(fd + 1);
354 } 393 }
355 394
356 } // namespace bin 395 } // namespace bin
357 } // namespace dart 396 } // namespace dart
358 397
359 #endif // defined(TARGET_OS_ANDROID) 398 #endif // defined(TARGET_OS_ANDROID)
OLDNEW
« no previous file with comments | « dart/runtime/bin/eventhandler_android.h ('k') | dart/runtime/bin/eventhandler_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698