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_MACOS) | 6 #if defined(TARGET_OS_MACOS) |
7 | 7 |
8 #include "bin/eventhandler.h" | 8 #include "bin/eventhandler.h" |
9 #include "bin/eventhandler_macos.h" | |
10 | 9 |
11 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
12 #include <pthread.h> // NOLINT | 11 #include <pthread.h> // NOLINT |
13 #include <stdio.h> // NOLINT | 12 #include <stdio.h> // NOLINT |
14 #include <string.h> // NOLINT | 13 #include <string.h> // NOLINT |
15 #include <sys/event.h> // NOLINT | 14 #include <sys/event.h> // NOLINT |
16 #include <unistd.h> // NOLINT | 15 #include <unistd.h> // NOLINT |
17 #include <fcntl.h> // NOLINT | 16 #include <fcntl.h> // NOLINT |
18 | 17 |
19 #include "bin/dartutils.h" | 18 #include "bin/dartutils.h" |
20 #include "bin/fdutils.h" | 19 #include "bin/fdutils.h" |
21 #include "bin/lockers.h" | |
22 #include "bin/log.h" | 20 #include "bin/log.h" |
23 #include "bin/socket.h" | |
24 #include "bin/thread.h" | 21 #include "bin/thread.h" |
25 #include "bin/utils.h" | 22 #include "bin/utils.h" |
26 #include "platform/hashmap.h" | 23 #include "platform/hashmap.h" |
27 #include "platform/utils.h" | 24 #include "platform/utils.h" |
28 | 25 |
29 | 26 |
30 namespace dart { | 27 namespace dart { |
31 namespace bin { | 28 namespace bin { |
32 | 29 |
| 30 static const int kInterruptMessageSize = sizeof(InterruptMessage); |
| 31 static const int kInfinityTimeout = -1; |
| 32 static const int kTimerId = -1; |
| 33 static const int kShutdownId = -2; |
33 | 34 |
34 bool DescriptorInfo::HasReadEvent() { | 35 |
35 return (Mask() & (1 << kInEvent)) != 0; | 36 bool SocketData::HasReadEvent() { |
| 37 return (mask_ & (1 << kInEvent)) != 0; |
36 } | 38 } |
37 | 39 |
38 | 40 |
39 bool DescriptorInfo::HasWriteEvent() { | 41 bool SocketData::HasWriteEvent() { |
40 return (Mask() & (1 << kOutEvent)) != 0; | 42 return (mask_ & (1 << kOutEvent)) != 0; |
41 } | 43 } |
42 | 44 |
43 | 45 |
44 // Unregister the file descriptor for a SocketData structure with kqueue. | 46 // Unregister the file descriptor for a SocketData structure with kqueue. |
45 static void RemoveFromKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) { | 47 static void RemoveFromKqueue(intptr_t kqueue_fd_, SocketData* sd) { |
46 if (!di->tracked_by_kqueue()) return; | 48 if (!sd->tracked_by_kqueue()) return; |
47 static const intptr_t kMaxChanges = 2; | 49 static const intptr_t kMaxChanges = 2; |
48 struct kevent events[kMaxChanges]; | 50 struct kevent events[kMaxChanges]; |
49 EV_SET(events, di->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL); | 51 EV_SET(events, sd->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL); |
50 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); | 52 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); |
51 EV_SET(events, di->fd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); | 53 EV_SET(events, sd->fd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); |
52 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); | 54 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); |
53 di->set_tracked_by_kqueue(false); | 55 sd->set_tracked_by_kqueue(false); |
54 } | 56 } |
55 | 57 |
56 | 58 |
57 // Update the kqueue registration for SocketData structure to reflect | 59 // Update the kqueue registration for SocketData structure to reflect |
58 // the events currently of interest. | 60 // the events currently of interest. |
59 static void AddToKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) { | 61 static void AddToKqueue(intptr_t kqueue_fd_, SocketData* sd) { |
60 ASSERT(!di->tracked_by_kqueue()); | 62 ASSERT(!sd->tracked_by_kqueue()); |
61 static const intptr_t kMaxChanges = 2; | 63 static const intptr_t kMaxChanges = 2; |
62 intptr_t changes = 0; | 64 intptr_t changes = 0; |
63 struct kevent events[kMaxChanges]; | 65 struct kevent events[kMaxChanges]; |
64 int flags = EV_ADD; | 66 int flags = EV_ADD; |
65 if (!di->IsListeningSocket()) { | 67 if (!sd->IsListeningSocket()) { |
66 flags |= EV_CLEAR; | 68 flags |= EV_CLEAR; |
67 } | 69 } |
68 // Register or unregister READ filter if needed. | 70 // Register or unregister READ filter if needed. |
69 if (di->HasReadEvent()) { | 71 if (sd->HasReadEvent()) { |
70 EV_SET(events + changes, | 72 EV_SET(events + changes, |
71 di->fd(), | 73 sd->fd(), |
72 EVFILT_READ, | 74 EVFILT_READ, |
73 flags, | 75 flags, |
74 0, | 76 0, |
75 0, | 77 0, |
76 di); | 78 sd); |
77 ++changes; | 79 ++changes; |
78 } | 80 } |
79 // Register or unregister WRITE filter if needed. | 81 // Register or unregister WRITE filter if needed. |
80 if (di->HasWriteEvent()) { | 82 if (sd->HasWriteEvent()) { |
81 EV_SET(events + changes, | 83 EV_SET(events + changes, |
82 di->fd(), | 84 sd->fd(), |
83 EVFILT_WRITE, | 85 EVFILT_WRITE, |
84 flags, | 86 flags, |
85 0, | 87 0, |
86 0, | 88 0, |
87 di); | 89 sd); |
88 ++changes; | 90 ++changes; |
89 } | 91 } |
90 ASSERT(changes > 0); | 92 ASSERT(changes > 0); |
91 ASSERT(changes <= kMaxChanges); | 93 ASSERT(changes <= kMaxChanges); |
92 int status = | 94 int status = |
93 NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); | 95 NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); |
94 if (status == -1) { | 96 if (status == -1) { |
95 // TODO(kustermann): Verify that the dart end is handling this correctly & | |
96 // adapt this code to work for multiple listening sockets. | |
97 | |
98 // kQueue does not accept the file descriptor. It could be due to | 97 // kQueue does not accept the file descriptor. It could be due to |
99 // already closed file descriptor, or unuspported devices, such | 98 // already closed file descriptor, or unuspported devices, such |
100 // as /dev/null. In such case, mark the file descriptor as closed, | 99 // as /dev/null. In such case, mark the file descriptor as closed, |
101 // so dart will handle it accordingly. | 100 // so dart will handle it accordingly. |
102 DartUtils::PostInt32(di->NextPort(), 1 << kCloseEvent); | 101 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); |
103 } else { | 102 } else { |
104 di->set_tracked_by_kqueue(true); | 103 sd->set_tracked_by_kqueue(true); |
105 } | 104 } |
106 } | 105 } |
107 | 106 |
108 | 107 |
109 EventHandlerImplementation::EventHandlerImplementation() | 108 EventHandlerImplementation::EventHandlerImplementation() |
110 : socket_map_(&HashMap::SamePointerValue, 16) { | 109 : socket_map_(&HashMap::SamePointerValue, 16) { |
111 intptr_t result; | 110 intptr_t result; |
112 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); | 111 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); |
113 if (result != 0) { | 112 if (result != 0) { |
114 FATAL("Pipe creation failed"); | 113 FATAL("Pipe creation failed"); |
(...skipping 21 matching lines...) Expand all Loading... |
136 } | 135 } |
137 | 136 |
138 | 137 |
139 EventHandlerImplementation::~EventHandlerImplementation() { | 138 EventHandlerImplementation::~EventHandlerImplementation() { |
140 VOID_TEMP_FAILURE_RETRY(close(kqueue_fd_)); | 139 VOID_TEMP_FAILURE_RETRY(close(kqueue_fd_)); |
141 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 140 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
142 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 141 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
143 } | 142 } |
144 | 143 |
145 | 144 |
146 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( | 145 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { |
147 intptr_t fd, bool is_listening) { | |
148 ASSERT(fd >= 0); | 146 ASSERT(fd >= 0); |
149 HashMap::Entry* entry = socket_map_.Lookup( | 147 HashMap::Entry* entry = socket_map_.Lookup( |
150 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 148 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); |
151 ASSERT(entry != NULL); | 149 ASSERT(entry != NULL); |
152 DescriptorInfo* di = | 150 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); |
153 reinterpret_cast<DescriptorInfo*>(entry->value); | 151 if (sd == NULL) { |
154 if (di == NULL) { | |
155 // If there is no data in the hash map for this file descriptor a | 152 // If there is no data in the hash map for this file descriptor a |
156 // new DescriptorInfo for the file descriptor is inserted. | 153 // new SocketData for the file descriptor is inserted. |
157 if (is_listening) { | 154 sd = new SocketData(fd); |
158 di = new DescriptorInfoMultiple(fd); | 155 entry->value = sd; |
159 } else { | |
160 di = new DescriptorInfoSingle(fd); | |
161 } | |
162 entry->value = di; | |
163 } | 156 } |
164 ASSERT(fd == di->fd()); | 157 ASSERT(fd == sd->fd()); |
165 return di; | 158 return sd; |
166 } | 159 } |
167 | 160 |
168 | 161 |
169 void EventHandlerImplementation::WakeupHandler(intptr_t id, | 162 void EventHandlerImplementation::WakeupHandler(intptr_t id, |
170 Dart_Port dart_port, | 163 Dart_Port dart_port, |
171 int64_t data) { | 164 int64_t data) { |
172 InterruptMessage msg; | 165 InterruptMessage msg; |
173 msg.id = id; | 166 msg.id = id; |
174 msg.dart_port = dart_port; | 167 msg.dart_port = dart_port; |
175 msg.data = data; | 168 msg.data = data; |
(...skipping 15 matching lines...) Expand all Loading... |
191 const intptr_t MAX_MESSAGES = kInterruptMessageSize; | 184 const intptr_t MAX_MESSAGES = kInterruptMessageSize; |
192 InterruptMessage msg[MAX_MESSAGES]; | 185 InterruptMessage msg[MAX_MESSAGES]; |
193 ssize_t bytes = TEMP_FAILURE_RETRY( | 186 ssize_t bytes = TEMP_FAILURE_RETRY( |
194 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); | 187 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); |
195 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { | 188 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { |
196 if (msg[i].id == kTimerId) { | 189 if (msg[i].id == kTimerId) { |
197 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); | 190 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); |
198 } else if (msg[i].id == kShutdownId) { | 191 } else if (msg[i].id == kShutdownId) { |
199 shutdown_ = true; | 192 shutdown_ = true; |
200 } else { | 193 } else { |
201 DescriptorInfo* di = GetDescriptorInfo( | 194 SocketData* sd = GetSocketData(msg[i].id); |
202 msg[i].id, (msg[i].data & (1 << kListeningSocket)) != 0); | |
203 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { | 195 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { |
204 ASSERT(!di->IsListeningSocket()); | |
205 // Close the socket for reading. | 196 // Close the socket for reading. |
206 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD)); | 197 shutdown(sd->fd(), SHUT_RD); |
207 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { | 198 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { |
208 ASSERT(!di->IsListeningSocket()); | |
209 // Close the socket for writing. | 199 // Close the socket for writing. |
210 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR)); | 200 shutdown(sd->fd(), SHUT_WR); |
211 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { | 201 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { |
212 // Close the socket and free system resources and move on to next | 202 // Close the socket and free system resources. |
213 // message. | 203 RemoveFromKqueue(kqueue_fd_, sd); |
214 bool no_more_listeners = di->RemovePort(msg[i].dart_port); | 204 intptr_t fd = sd->fd(); |
215 if (no_more_listeners) { | 205 VOID_TEMP_FAILURE_RETRY(close(fd)); |
216 RemoveFromKqueue(kqueue_fd_, di); | 206 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
217 } | 207 delete sd; |
218 | |
219 intptr_t fd = di->fd(); | |
220 if (di->IsListeningSocket()) { | |
221 // We only close the socket file descriptor from the operating | |
222 // system if there are no other dart socket objects which | |
223 // are listening on the same (address, port) combination. | |
224 { | |
225 MutexLocker ml(globalTcpListeningSocketRegistry.mutex()); | |
226 if (globalTcpListeningSocketRegistry.CloseSafe(fd)) { | |
227 socket_map_.Remove( | |
228 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | |
229 di->Close(); | |
230 delete di; | |
231 } | |
232 } | |
233 } else { | |
234 ASSERT(no_more_listeners); | |
235 socket_map_.Remove( | |
236 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | |
237 di->Close(); | |
238 delete di; | |
239 } | |
240 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); | 208 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); |
241 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { | 209 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { |
242 int count = TOKEN_COUNT(msg[i].data); | 210 int count = TOKEN_COUNT(msg[i].data); |
243 if (di->ReturnTokens(msg[i].dart_port, count)) { | 211 for (int i = 0; i < count; i++) { |
244 AddToKqueue(kqueue_fd_, di); | 212 if (sd->ReturnToken()) { |
| 213 AddToKqueue(kqueue_fd_, sd); |
| 214 } |
245 } | 215 } |
246 } else { | 216 } else { |
247 ASSERT_NO_COMMAND(msg[i].data); | 217 ASSERT_NO_COMMAND(msg[i].data); |
| 218 // Setup events to wait for. |
248 ASSERT((msg[i].data > 0) && (msg[i].data < kIntptrMax)); | 219 ASSERT((msg[i].data > 0) && (msg[i].data < kIntptrMax)); |
249 bool had_listeners = di->HasNextPort(); | 220 ASSERT(sd->port() == 0); |
250 di->SetPortAndMask(msg[i].dart_port, msg[i].data & EVENT_MASK); | 221 sd->SetPortAndMask(msg[i].dart_port, |
251 bool has_listeners = di->HasNextPort(); | 222 static_cast<intptr_t>(msg[i].data)); |
252 | 223 AddToKqueue(kqueue_fd_, sd); |
253 // Add/Remove from epoll set depending on previous and current state. | |
254 if (!had_listeners && has_listeners) { | |
255 AddToKqueue(kqueue_fd_, di); | |
256 } else if (had_listeners && !has_listeners) { | |
257 RemoveFromKqueue(kqueue_fd_, di); | |
258 } | |
259 } | 224 } |
260 } | 225 } |
261 } | 226 } |
262 } | 227 } |
263 | 228 |
264 #ifdef DEBUG_KQUEUE | 229 #ifdef DEBUG_KQUEUE |
265 static void PrintEventMask(intptr_t fd, struct kevent* event) { | 230 static void PrintEventMask(intptr_t fd, struct kevent* event) { |
266 Log::Print("%d ", static_cast<int>(fd)); | 231 Log::Print("%d ", static_cast<int>(fd)); |
267 Log::Print("filter=0x%x:", event->filter); | 232 Log::Print("filter=0x%x:", event->filter); |
268 if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ "); | 233 if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ "); |
269 if (event->filter == EVFILT_WRITE) Log::Print("EVFILT_WRITE "); | 234 if (event->filter == EVFILT_WRITE) Log::Print("EVFILT_WRITE "); |
270 Log::Print("flags: %x: ", event->flags); | 235 Log::Print("flags: %x: ", event->flags); |
271 if ((event->flags & EV_EOF) != 0) Log::Print("EV_EOF "); | 236 if ((event->flags & EV_EOF) != 0) Log::Print("EV_EOF "); |
272 if ((event->flags & EV_ERROR) != 0) Log::Print("EV_ERROR "); | 237 if ((event->flags & EV_ERROR) != 0) Log::Print("EV_ERROR "); |
273 if ((event->flags & EV_CLEAR) != 0) Log::Print("EV_CLEAR "); | 238 if ((event->flags & EV_CLEAR) != 0) Log::Print("EV_CLEAR "); |
274 if ((event->flags & EV_ADD) != 0) Log::Print("EV_ADD "); | 239 if ((event->flags & EV_ADD) != 0) Log::Print("EV_ADD "); |
275 if ((event->flags & EV_DELETE) != 0) Log::Print("EV_DELETE "); | 240 if ((event->flags & EV_DELETE) != 0) Log::Print("EV_DELETE "); |
276 Log::Print("- fflags: %d ", event->fflags); | 241 Log::Print("- fflags: %d ", event->fflags); |
277 Log::Print("- data: %ld ", event->data); | 242 Log::Print("- data: %ld ", event->data); |
278 Log::Print("(available %d) ", | 243 Log::Print("(available %d) ", |
279 static_cast<int>(FDUtils::AvailableBytes(fd))); | 244 static_cast<int>(FDUtils::AvailableBytes(fd))); |
280 Log::Print("\n"); | 245 Log::Print("\n"); |
281 } | 246 } |
282 #endif | 247 #endif |
283 | 248 |
284 | 249 |
285 intptr_t EventHandlerImplementation::GetEvents(struct kevent* event, | 250 intptr_t EventHandlerImplementation::GetEvents(struct kevent* event, |
286 DescriptorInfo* di) { | 251 SocketData* sd) { |
287 #ifdef DEBUG_KQUEUE | 252 #ifdef DEBUG_KQUEUE |
288 PrintEventMask(di->fd(), event); | 253 PrintEventMask(sd->fd(), event); |
289 #endif | 254 #endif |
290 intptr_t event_mask = 0; | 255 intptr_t event_mask = 0; |
291 if (di->IsListeningSocket()) { | 256 if (sd->IsListeningSocket()) { |
292 // On a listening socket the READ event means that there are | 257 // On a listening socket the READ event means that there are |
293 // connections ready to be accepted. | 258 // connections ready to be accepted. |
294 if (event->filter == EVFILT_READ) { | 259 if (event->filter == EVFILT_READ) { |
295 if ((event->flags & EV_EOF) != 0) { | 260 if ((event->flags & EV_EOF) != 0) { |
296 if (event->fflags != 0) { | 261 if (event->fflags != 0) { |
297 event_mask |= (1 << kErrorEvent); | 262 event_mask |= (1 << kErrorEvent); |
298 } else { | 263 } else { |
299 event_mask |= (1 << kCloseEvent); | 264 event_mask |= (1 << kCloseEvent); |
300 } | 265 } |
301 } | 266 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 // If flag EV_ERROR is set it indicates an error in kevent processing. | 302 // If flag EV_ERROR is set it indicates an error in kevent processing. |
338 if ((events[i].flags & EV_ERROR) != 0) { | 303 if ((events[i].flags & EV_ERROR) != 0) { |
339 const int kBufferSize = 1024; | 304 const int kBufferSize = 1024; |
340 char error_message[kBufferSize]; | 305 char error_message[kBufferSize]; |
341 strerror_r(events[i].data, error_message, kBufferSize); | 306 strerror_r(events[i].data, error_message, kBufferSize); |
342 FATAL1("kevent failed %s\n", error_message); | 307 FATAL1("kevent failed %s\n", error_message); |
343 } | 308 } |
344 if (events[i].udata == NULL) { | 309 if (events[i].udata == NULL) { |
345 interrupt_seen = true; | 310 interrupt_seen = true; |
346 } else { | 311 } else { |
347 DescriptorInfo* di = | 312 SocketData* sd = reinterpret_cast<SocketData*>(events[i].udata); |
348 reinterpret_cast<DescriptorInfo*>(events[i].udata); | 313 intptr_t event_mask = GetEvents(events + i, sd); |
349 intptr_t event_mask = GetEvents(events + i, di); | |
350 if (event_mask != 0) { | 314 if (event_mask != 0) { |
351 Dart_Port port = di->NextPort(); | 315 if (sd->TakeToken()) { |
| 316 // Took last token, remove from epoll. |
| 317 RemoveFromKqueue(kqueue_fd_, sd); |
| 318 } |
| 319 Dart_Port port = sd->port(); |
352 ASSERT(port != 0); | 320 ASSERT(port != 0); |
353 if (di->TakeToken()) { | |
354 // Took last token, remove from kqueue. | |
355 RemoveFromKqueue(kqueue_fd_, di); | |
356 } | |
357 DartUtils::PostInt32(port, event_mask); | 321 DartUtils::PostInt32(port, event_mask); |
358 } | 322 } |
359 } | 323 } |
360 } | 324 } |
361 if (interrupt_seen) { | 325 if (interrupt_seen) { |
362 // Handle after socket events, so we avoid closing a socket before we handle | 326 // Handle after socket events, so we avoid closing a socket before we handle |
363 // the current events. | 327 // the current events. |
364 HandleInterruptFd(); | 328 HandleInterruptFd(); |
365 } | 329 } |
366 } | 330 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 | 421 |
458 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { | 422 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { |
459 // The hashmap does not support keys with value 0. | 423 // The hashmap does not support keys with value 0. |
460 return dart::Utils::WordHash(fd + 1); | 424 return dart::Utils::WordHash(fd + 1); |
461 } | 425 } |
462 | 426 |
463 } // namespace bin | 427 } // namespace bin |
464 } // namespace dart | 428 } // namespace dart |
465 | 429 |
466 #endif // defined(TARGET_OS_MACOS) | 430 #endif // defined(TARGET_OS_MACOS) |
OLD | NEW |