| 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 |