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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
6 | 6 |
7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
8 #if defined(TARGET_OS_MACOS) | 8 #if defined(TARGET_OS_MACOS) |
9 | 9 |
10 #include "bin/eventhandler.h" | 10 #include "bin/eventhandler.h" |
11 #include "bin/eventhandler_macos.h" | 11 #include "bin/eventhandler_macos.h" |
12 | 12 |
13 #include <errno.h> // NOLINT | 13 #include <errno.h> // NOLINT |
14 #include <fcntl.h> // NOLINT | 14 #include <fcntl.h> // NOLINT |
15 #include <pthread.h> // NOLINT | 15 #include <pthread.h> // NOLINT |
16 #include <stdio.h> // NOLINT | 16 #include <stdio.h> // NOLINT |
17 #include <string.h> // NOLINT | 17 #include <string.h> // NOLINT |
18 #include <sys/event.h> // NOLINT | 18 #include <sys/event.h> // NOLINT |
19 #include <unistd.h> // NOLINT | 19 #include <unistd.h> // NOLINT |
20 | 20 |
21 #include "bin/dartutils.h" | 21 #include "bin/dartutils.h" |
22 #include "bin/fdutils.h" | 22 #include "bin/fdutils.h" |
23 #include "bin/lockers.h" | 23 #include "bin/lockers.h" |
24 #include "bin/log.h" | 24 #include "bin/log.h" |
25 #include "bin/socket.h" | 25 #include "bin/socket.h" |
26 #include "bin/thread.h" | 26 #include "bin/thread.h" |
27 #include "bin/utils.h" | 27 #include "bin/utils.h" |
28 #include "platform/hashmap.h" | 28 #include "platform/hashmap.h" |
29 #include "platform/utils.h" | 29 #include "platform/utils.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 struct kevent events[kMaxChanges]; | 65 struct kevent events[kMaxChanges]; |
66 int flags = EV_ADD; | 66 int flags = EV_ADD; |
67 if (!di->IsListeningSocket()) { | 67 if (!di->IsListeningSocket()) { |
68 flags |= EV_CLEAR; | 68 flags |= EV_CLEAR; |
69 } | 69 } |
70 | 70 |
71 ASSERT(di->HasReadEvent() || di->HasWriteEvent()); | 71 ASSERT(di->HasReadEvent() || di->HasWriteEvent()); |
72 | 72 |
73 // Register or unregister READ filter if needed. | 73 // Register or unregister READ filter if needed. |
74 if (di->HasReadEvent()) { | 74 if (di->HasReadEvent()) { |
75 EV_SET(events + changes, | 75 EV_SET(events + changes, di->fd(), EVFILT_READ, flags, 0, 0, di); |
76 di->fd(), | |
77 EVFILT_READ, | |
78 flags, | |
79 0, | |
80 0, | |
81 di); | |
82 ++changes; | 76 ++changes; |
83 } | 77 } |
84 // Register or unregister WRITE filter if needed. | 78 // Register or unregister WRITE filter if needed. |
85 if (di->HasWriteEvent()) { | 79 if (di->HasWriteEvent()) { |
86 EV_SET(events + changes, | 80 EV_SET(events + changes, di->fd(), EVFILT_WRITE, flags, 0, 0, di); |
87 di->fd(), | |
88 EVFILT_WRITE, | |
89 flags, | |
90 0, | |
91 0, | |
92 di); | |
93 ++changes; | 81 ++changes; |
94 } | 82 } |
95 ASSERT(changes > 0); | 83 ASSERT(changes > 0); |
96 ASSERT(changes <= kMaxChanges); | 84 ASSERT(changes <= kMaxChanges); |
97 int status = | 85 int status = |
98 NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); | 86 NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); |
99 if (status == -1) { | 87 if (status == -1) { |
100 // TODO(dart:io): Verify that the dart end is handling this correctly. | 88 // TODO(dart:io): Verify that the dart end is handling this correctly. |
101 | 89 |
102 // kQueue does not accept the file descriptor. It could be due to | 90 // kQueue does not accept the file descriptor. It could be due to |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 137 |
150 EventHandlerImplementation::~EventHandlerImplementation() { | 138 EventHandlerImplementation::~EventHandlerImplementation() { |
151 socket_map_.Clear(DeleteDescriptorInfo); | 139 socket_map_.Clear(DeleteDescriptorInfo); |
152 VOID_TEMP_FAILURE_RETRY(close(kqueue_fd_)); | 140 VOID_TEMP_FAILURE_RETRY(close(kqueue_fd_)); |
153 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 141 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
154 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 142 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
155 } | 143 } |
156 | 144 |
157 | 145 |
158 void EventHandlerImplementation::UpdateKQueueInstance(intptr_t old_mask, | 146 void EventHandlerImplementation::UpdateKQueueInstance(intptr_t old_mask, |
159 DescriptorInfo *di) { | 147 DescriptorInfo* di) { |
160 intptr_t new_mask = di->Mask(); | 148 intptr_t new_mask = di->Mask(); |
161 if (old_mask != 0 && new_mask == 0) { | 149 if (old_mask != 0 && new_mask == 0) { |
162 RemoveFromKqueue(kqueue_fd_, di); | 150 RemoveFromKqueue(kqueue_fd_, di); |
163 } else if ((old_mask == 0) && (new_mask != 0)) { | 151 } else if ((old_mask == 0) && (new_mask != 0)) { |
164 AddToKqueue(kqueue_fd_, di); | 152 AddToKqueue(kqueue_fd_, di); |
165 } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) { | 153 } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) { |
166 ASSERT(!di->IsListeningSocket()); | 154 ASSERT(!di->IsListeningSocket()); |
167 RemoveFromKqueue(kqueue_fd_, di); | 155 RemoveFromKqueue(kqueue_fd_, di); |
168 AddToKqueue(kqueue_fd_, di); | 156 AddToKqueue(kqueue_fd_, di); |
169 } | 157 } |
170 } | 158 } |
171 | 159 |
172 | 160 |
173 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( | 161 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( |
174 intptr_t fd, bool is_listening) { | 162 intptr_t fd, |
| 163 bool is_listening) { |
175 ASSERT(fd >= 0); | 164 ASSERT(fd >= 0); |
176 HashMap::Entry* entry = socket_map_.Lookup( | 165 HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd), |
177 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 166 GetHashmapHashFromFd(fd), true); |
178 ASSERT(entry != NULL); | 167 ASSERT(entry != NULL); |
179 DescriptorInfo* di = | 168 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value); |
180 reinterpret_cast<DescriptorInfo*>(entry->value); | |
181 if (di == NULL) { | 169 if (di == NULL) { |
182 // If there is no data in the hash map for this file descriptor a | 170 // If there is no data in the hash map for this file descriptor a |
183 // new DescriptorInfo for the file descriptor is inserted. | 171 // new DescriptorInfo for the file descriptor is inserted. |
184 if (is_listening) { | 172 if (is_listening) { |
185 di = new DescriptorInfoMultiple(fd); | 173 di = new DescriptorInfoMultiple(fd); |
186 } else { | 174 } else { |
187 di = new DescriptorInfoSingle(fd); | 175 di = new DescriptorInfoSingle(fd); |
188 } | 176 } |
189 entry->value = di; | 177 entry->value = di; |
190 } | 178 } |
(...skipping 29 matching lines...) Expand all Loading... |
220 ssize_t bytes = TEMP_FAILURE_RETRY( | 208 ssize_t bytes = TEMP_FAILURE_RETRY( |
221 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); | 209 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); |
222 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { | 210 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { |
223 if (msg[i].id == kTimerId) { | 211 if (msg[i].id == kTimerId) { |
224 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); | 212 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); |
225 } else if (msg[i].id == kShutdownId) { | 213 } else if (msg[i].id == kShutdownId) { |
226 shutdown_ = true; | 214 shutdown_ = true; |
227 } else { | 215 } else { |
228 ASSERT((msg[i].data & COMMAND_MASK) != 0); | 216 ASSERT((msg[i].data & COMMAND_MASK) != 0); |
229 | 217 |
230 DescriptorInfo* di = GetDescriptorInfo( | 218 DescriptorInfo* di = |
231 msg[i].id, IS_LISTENING_SOCKET(msg[i].data)); | 219 GetDescriptorInfo(msg[i].id, IS_LISTENING_SOCKET(msg[i].data)); |
232 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { | 220 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { |
233 ASSERT(!di->IsListeningSocket()); | 221 ASSERT(!di->IsListeningSocket()); |
234 // Close the socket for reading. | 222 // Close the socket for reading. |
235 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD)); | 223 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD)); |
236 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { | 224 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { |
237 ASSERT(!di->IsListeningSocket()); | 225 ASSERT(!di->IsListeningSocket()); |
238 // Close the socket for writing. | 226 // Close the socket for writing. |
239 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR)); | 227 VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR)); |
240 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { | 228 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { |
241 // Close the socket and free system resources and move on to next | 229 // Close the socket and free system resources and move on to next |
242 // message. | 230 // message. |
243 intptr_t old_mask = di->Mask(); | 231 intptr_t old_mask = di->Mask(); |
244 Dart_Port port = msg[i].dart_port; | 232 Dart_Port port = msg[i].dart_port; |
245 di->RemovePort(port); | 233 di->RemovePort(port); |
246 intptr_t new_mask = di->Mask(); | 234 intptr_t new_mask = di->Mask(); |
247 UpdateKQueueInstance(old_mask, di); | 235 UpdateKQueueInstance(old_mask, di); |
248 | 236 |
249 intptr_t fd = di->fd(); | 237 intptr_t fd = di->fd(); |
250 if (di->IsListeningSocket()) { | 238 if (di->IsListeningSocket()) { |
251 // We only close the socket file descriptor from the operating | 239 // We only close the socket file descriptor from the operating |
252 // system if there are no other dart socket objects which | 240 // system if there are no other dart socket objects which |
253 // are listening on the same (address, port) combination. | 241 // are listening on the same (address, port) combination. |
254 ListeningSocketRegistry *registry = | 242 ListeningSocketRegistry* registry = |
255 ListeningSocketRegistry::Instance(); | 243 ListeningSocketRegistry::Instance(); |
256 | 244 |
257 MutexLocker locker(registry->mutex()); | 245 MutexLocker locker(registry->mutex()); |
258 | 246 |
259 if (registry->CloseSafe(fd)) { | 247 if (registry->CloseSafe(fd)) { |
260 ASSERT(new_mask == 0); | 248 ASSERT(new_mask == 0); |
261 socket_map_.Remove(GetHashmapKeyFromFd(fd), | 249 socket_map_.Remove(GetHashmapKeyFromFd(fd), |
262 GetHashmapHashFromFd(fd)); | 250 GetHashmapHashFromFd(fd)); |
263 di->Close(); | 251 di->Close(); |
264 delete di; | 252 delete di; |
265 } | 253 } |
266 } else { | 254 } else { |
267 ASSERT(new_mask == 0); | 255 ASSERT(new_mask == 0); |
268 socket_map_.Remove( | 256 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
269 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | |
270 di->Close(); | 257 di->Close(); |
271 delete di; | 258 delete di; |
272 } | 259 } |
273 | 260 |
274 DartUtils::PostInt32(port, 1 << kDestroyedEvent); | 261 DartUtils::PostInt32(port, 1 << kDestroyedEvent); |
275 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { | 262 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { |
276 intptr_t old_mask = di->Mask(); | 263 intptr_t old_mask = di->Mask(); |
277 di->ReturnTokens(msg[i].dart_port, TOKEN_COUNT(msg[i].data)); | 264 di->ReturnTokens(msg[i].dart_port, TOKEN_COUNT(msg[i].data)); |
278 UpdateKQueueInstance(old_mask, di); | 265 UpdateKQueueInstance(old_mask, di); |
279 } else if (IS_COMMAND(msg[i].data, kSetEventMaskCommand)) { | 266 } else if (IS_COMMAND(msg[i].data, kSetEventMaskCommand)) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 } | 359 } |
373 } else { | 360 } else { |
374 UNREACHABLE(); | 361 UNREACHABLE(); |
375 } | 362 } |
376 } | 363 } |
377 | 364 |
378 return event_mask; | 365 return event_mask; |
379 } | 366 } |
380 | 367 |
381 | 368 |
382 void EventHandlerImplementation::HandleEvents(struct kevent* events, | 369 void EventHandlerImplementation::HandleEvents(struct kevent* events, int size) { |
383 int size) { | |
384 bool interrupt_seen = false; | 370 bool interrupt_seen = false; |
385 for (int i = 0; i < size; i++) { | 371 for (int i = 0; i < size; i++) { |
386 // If flag EV_ERROR is set it indicates an error in kevent processing. | 372 // If flag EV_ERROR is set it indicates an error in kevent processing. |
387 if ((events[i].flags & EV_ERROR) != 0) { | 373 if ((events[i].flags & EV_ERROR) != 0) { |
388 const int kBufferSize = 1024; | 374 const int kBufferSize = 1024; |
389 char error_message[kBufferSize]; | 375 char error_message[kBufferSize]; |
390 Utils::StrError(events[i].data, error_message, kBufferSize); | 376 Utils::StrError(events[i].data, error_message, kBufferSize); |
391 FATAL1("kevent failed %s\n", error_message); | 377 FATAL1("kevent failed %s\n", error_message); |
392 } | 378 } |
393 if (events[i].udata == NULL) { | 379 if (events[i].udata == NULL) { |
394 interrupt_seen = true; | 380 interrupt_seen = true; |
395 } else { | 381 } else { |
396 DescriptorInfo* di = | 382 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(events[i].udata); |
397 reinterpret_cast<DescriptorInfo*>(events[i].udata); | |
398 intptr_t event_mask = GetEvents(events + i, di); | 383 intptr_t event_mask = GetEvents(events + i, di); |
399 if ((event_mask & (1 << kErrorEvent)) != 0) { | 384 if ((event_mask & (1 << kErrorEvent)) != 0) { |
400 di->NotifyAllDartPorts(event_mask); | 385 di->NotifyAllDartPorts(event_mask); |
401 } | 386 } |
402 event_mask &= ~(1 << kErrorEvent); | 387 event_mask &= ~(1 << kErrorEvent); |
403 | 388 |
404 if (event_mask != 0) { | 389 if (event_mask != 0) { |
405 intptr_t old_mask = di->Mask(); | 390 intptr_t old_mask = di->Mask(); |
406 Dart_Port port = di->NextNotifyDartPort(event_mask); | 391 Dart_Port port = di->NextNotifyDartPort(event_mask); |
407 ASSERT(port != 0); | 392 ASSERT(port != 0); |
408 UpdateKQueueInstance(old_mask, di); | 393 UpdateKQueueInstance(old_mask, di); |
409 DartUtils::PostInt32(port, event_mask); | 394 DartUtils::PostInt32(port, event_mask); |
410 } | 395 } |
411 } | 396 } |
412 } | 397 } |
413 if (interrupt_seen) { | 398 if (interrupt_seen) { |
414 // Handle after socket events, so we avoid closing a socket before we handle | 399 // Handle after socket events, so we avoid closing a socket before we handle |
415 // the current events. | 400 // the current events. |
416 HandleInterruptFd(); | 401 HandleInterruptFd(); |
417 } | 402 } |
418 } | 403 } |
419 | 404 |
420 | 405 |
421 int64_t EventHandlerImplementation::GetTimeout() { | 406 int64_t EventHandlerImplementation::GetTimeout() { |
422 if (!timeout_queue_.HasTimeout()) { | 407 if (!timeout_queue_.HasTimeout()) { |
423 return kInfinityTimeout; | 408 return kInfinityTimeout; |
424 } | 409 } |
425 int64_t millis = timeout_queue_.CurrentTimeout() - | 410 int64_t millis = |
426 TimerUtils::GetCurrentMonotonicMillis(); | 411 timeout_queue_.CurrentTimeout() - TimerUtils::GetCurrentMonotonicMillis(); |
427 return (millis < 0) ? 0 : millis; | 412 return (millis < 0) ? 0 : millis; |
428 } | 413 } |
429 | 414 |
430 | 415 |
431 void EventHandlerImplementation::HandleTimeout() { | 416 void EventHandlerImplementation::HandleTimeout() { |
432 if (timeout_queue_.HasTimeout()) { | 417 if (timeout_queue_.HasTimeout()) { |
433 int64_t millis = timeout_queue_.CurrentTimeout() - | 418 int64_t millis = timeout_queue_.CurrentTimeout() - |
434 TimerUtils::GetCurrentMonotonicMillis(); | 419 TimerUtils::GetCurrentMonotonicMillis(); |
435 if (millis <= 0) { | 420 if (millis <= 0) { |
436 DartUtils::PostNull(timeout_queue_.CurrentPort()); | 421 DartUtils::PostNull(timeout_queue_.CurrentPort()); |
437 timeout_queue_.RemoveCurrent(); | 422 timeout_queue_.RemoveCurrent(); |
438 } | 423 } |
439 } | 424 } |
440 } | 425 } |
441 | 426 |
442 | 427 |
443 void EventHandlerImplementation::EventHandlerEntry(uword args) { | 428 void EventHandlerImplementation::EventHandlerEntry(uword args) { |
444 static const intptr_t kMaxEvents = 16; | 429 static const intptr_t kMaxEvents = 16; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 } else { | 461 } else { |
477 handler_impl->HandleTimeout(); | 462 handler_impl->HandleTimeout(); |
478 handler_impl->HandleEvents(events, result); | 463 handler_impl->HandleEvents(events, result); |
479 } | 464 } |
480 } | 465 } |
481 handler->NotifyShutdownDone(); | 466 handler->NotifyShutdownDone(); |
482 } | 467 } |
483 | 468 |
484 | 469 |
485 void EventHandlerImplementation::Start(EventHandler* handler) { | 470 void EventHandlerImplementation::Start(EventHandler* handler) { |
486 int result = | 471 int result = Thread::Start(&EventHandlerImplementation::EventHandlerEntry, |
487 Thread::Start(&EventHandlerImplementation::EventHandlerEntry, | 472 reinterpret_cast<uword>(handler)); |
488 reinterpret_cast<uword>(handler)); | |
489 if (result != 0) { | 473 if (result != 0) { |
490 FATAL1("Failed to start event handler thread %d", result); | 474 FATAL1("Failed to start event handler thread %d", result); |
491 } | 475 } |
492 } | 476 } |
493 | 477 |
494 | 478 |
495 void EventHandlerImplementation::Shutdown() { | 479 void EventHandlerImplementation::Shutdown() { |
496 SendData(kShutdownId, 0, 0); | 480 SendData(kShutdownId, 0, 0); |
497 } | 481 } |
498 | 482 |
(...skipping 15 matching lines...) Expand all Loading... |
514 // The hashmap does not support keys with value 0. | 498 // The hashmap does not support keys with value 0. |
515 return dart::Utils::WordHash(fd + 1); | 499 return dart::Utils::WordHash(fd + 1); |
516 } | 500 } |
517 | 501 |
518 } // namespace bin | 502 } // namespace bin |
519 } // namespace dart | 503 } // namespace dart |
520 | 504 |
521 #endif // defined(TARGET_OS_MACOS) | 505 #endif // defined(TARGET_OS_MACOS) |
522 | 506 |
523 #endif // !defined(DART_IO_DISABLED) | 507 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |