| 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 | 9 |
| 10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 | 40 |
| 41 bool SocketData::HasWriteEvent() { | 41 bool SocketData::HasWriteEvent() { |
| 42 return (mask_ & (1 << kOutEvent)) != 0; | 42 return (mask_ & (1 << kOutEvent)) != 0; |
| 43 } | 43 } |
| 44 | 44 |
| 45 | 45 |
| 46 // Unregister the file descriptor for a SocketData structure with kqueue. | 46 // Unregister the file descriptor for a SocketData structure with kqueue. |
| 47 static void RemoveFromKqueue(intptr_t kqueue_fd_, SocketData* sd) { | 47 static void RemoveFromKqueue(intptr_t kqueue_fd_, SocketData* sd) { |
| 48 if (!sd->tracked_by_kqueue()) return; | 48 if (!sd->tracked_by_kqueue()) return; |
| 49 static const intptr_t kMaxChanges = 2; | 49 static const intptr_t kMaxChanges = 2; |
| 50 intptr_t changes = 0; | |
| 51 struct kevent events[kMaxChanges]; | 50 struct kevent events[kMaxChanges]; |
| 52 if (sd->HasReadEvent()) { | 51 EV_SET(events, sd->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL); |
| 53 EV_SET(events + changes, sd->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL); | 52 VOID_TEMP_FAILURE_RETRY(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); |
| 54 ++changes; | 53 EV_SET(events, sd->fd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); |
| 55 } | 54 VOID_TEMP_FAILURE_RETRY(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); |
| 56 if (sd->HasWriteEvent()) { | |
| 57 EV_SET(events + changes, sd->fd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); | |
| 58 ++changes; | |
| 59 } | |
| 60 ASSERT(changes > 0); | |
| 61 ASSERT(changes <= kMaxChanges); | |
| 62 int status = | |
| 63 TEMP_FAILURE_RETRY(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); | |
| 64 if (status == -1) { | |
| 65 const int kBufferSize = 1024; | |
| 66 char error_message[kBufferSize]; | |
| 67 strerror_r(errno, error_message, kBufferSize); | |
| 68 FATAL1("Failed deleting events from kqueue: %s\n", error_message); | |
| 69 } | |
| 70 sd->set_tracked_by_kqueue(false); | 55 sd->set_tracked_by_kqueue(false); |
| 71 } | 56 } |
| 72 | 57 |
| 73 | 58 |
| 74 // Update the kqueue registration for SocketData structure to reflect | 59 // Update the kqueue registration for SocketData structure to reflect |
| 75 // the events currently of interest. | 60 // the events currently of interest. |
| 76 static void AddToKqueue(intptr_t kqueue_fd_, SocketData* sd) { | 61 static void AddToKqueue(intptr_t kqueue_fd_, SocketData* sd) { |
| 62 ASSERT(!sd->tracked_by_kqueue()); |
| 77 static const intptr_t kMaxChanges = 2; | 63 static const intptr_t kMaxChanges = 2; |
| 78 intptr_t changes = 0; | 64 intptr_t changes = 0; |
| 79 struct kevent events[kMaxChanges]; | 65 struct kevent events[kMaxChanges]; |
| 80 // Register or unregister READ filter if needed. | 66 // Register or unregister READ filter if needed. |
| 81 if (sd->HasReadEvent()) { | 67 if (sd->HasReadEvent()) { |
| 82 EV_SET(events + changes, | 68 EV_SET(events + changes, |
| 83 sd->fd(), | 69 sd->fd(), |
| 84 EVFILT_READ, | 70 EVFILT_READ, |
| 85 EV_ADD | EV_CLEAR, | 71 EV_ADD | EV_CLEAR, |
| 86 0, | 72 0, |
| 87 0, | 73 0, |
| 88 sd); | 74 sd); |
| 89 ++changes; | 75 ++changes; |
| 90 } | 76 } |
| 91 // Register or unregister WRITE filter if needed. | 77 // Register or unregister WRITE filter if needed. |
| 92 if (sd->HasWriteEvent()) { | 78 if (sd->HasWriteEvent()) { |
| 93 EV_SET(events + changes, | 79 EV_SET(events + changes, |
| 94 sd->fd(), | 80 sd->fd(), |
| 95 EVFILT_WRITE, | 81 EVFILT_WRITE, |
| 96 EV_ADD | EV_CLEAR, | 82 EV_ADD | EV_CLEAR, |
| 97 0, | 83 0, |
| 98 0, | 84 0, |
| 99 sd); | 85 sd); |
| 100 ++changes; | 86 ++changes; |
| 101 } | 87 } |
| 102 ASSERT(changes > 0); | 88 ASSERT(changes > 0); |
| 103 ASSERT(changes <= kMaxChanges); | 89 ASSERT(changes <= kMaxChanges); |
| 104 int status = | 90 int status = |
| 105 TEMP_FAILURE_RETRY(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); | 91 TEMP_FAILURE_RETRY(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); |
| 106 if (status == -1) { | 92 if (status == -1) { |
| 107 // kQueue does not accept the file descriptor. It could be due to | 93 // kQueue does not accept the file descriptor. It could be due to |
| 108 // already closed file descriptor, or unuspported devices, such | 94 // already closed file descriptor, or unuspported devices, such |
| 109 // as /dev/null. In such case, mark the file descriptor as closed, | 95 // as /dev/null. In such case, mark the file descriptor as closed, |
| 110 // so dart will handle it accordingly. | 96 // so dart will handle it accordingly. |
| 111 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); | 97 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); |
| 112 } else { | 98 } else { |
| 113 sd->set_tracked_by_kqueue(true); | 99 sd->set_tracked_by_kqueue(true); |
| 114 } | 100 } |
| 115 } | 101 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 145 } | 131 } |
| 146 | 132 |
| 147 | 133 |
| 148 EventHandlerImplementation::~EventHandlerImplementation() { | 134 EventHandlerImplementation::~EventHandlerImplementation() { |
| 149 VOID_TEMP_FAILURE_RETRY(close(kqueue_fd_)); | 135 VOID_TEMP_FAILURE_RETRY(close(kqueue_fd_)); |
| 150 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); | 136 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); |
| 151 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); | 137 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); |
| 152 } | 138 } |
| 153 | 139 |
| 154 | 140 |
| 155 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd, | 141 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { |
| 156 bool* is_new) { | |
| 157 ASSERT(fd >= 0); | 142 ASSERT(fd >= 0); |
| 158 HashMap::Entry* entry = socket_map_.Lookup( | 143 HashMap::Entry* entry = socket_map_.Lookup( |
| 159 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); | 144 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); |
| 160 ASSERT(entry != NULL); | 145 ASSERT(entry != NULL); |
| 161 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); | 146 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); |
| 162 if (sd == NULL) { | 147 if (sd == NULL) { |
| 163 // If there is no data in the hash map for this file descriptor a | 148 // If there is no data in the hash map for this file descriptor a |
| 164 // new SocketData for the file descriptor is inserted. | 149 // new SocketData for the file descriptor is inserted. |
| 165 sd = new SocketData(fd); | 150 sd = new SocketData(fd); |
| 166 entry->value = sd; | 151 entry->value = sd; |
| 167 *is_new = true; | |
| 168 } | 152 } |
| 169 ASSERT(fd == sd->fd()); | 153 ASSERT(fd == sd->fd()); |
| 170 return sd; | 154 return sd; |
| 171 } | 155 } |
| 172 | 156 |
| 173 | 157 |
| 174 void EventHandlerImplementation::WakeupHandler(intptr_t id, | 158 void EventHandlerImplementation::WakeupHandler(intptr_t id, |
| 175 Dart_Port dart_port, | 159 Dart_Port dart_port, |
| 176 int64_t data) { | 160 int64_t data) { |
| 177 InterruptMessage msg; | 161 InterruptMessage msg; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 196 const intptr_t MAX_MESSAGES = kInterruptMessageSize; | 180 const intptr_t MAX_MESSAGES = kInterruptMessageSize; |
| 197 InterruptMessage msg[MAX_MESSAGES]; | 181 InterruptMessage msg[MAX_MESSAGES]; |
| 198 ssize_t bytes = TEMP_FAILURE_RETRY( | 182 ssize_t bytes = TEMP_FAILURE_RETRY( |
| 199 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); | 183 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); |
| 200 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { | 184 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { |
| 201 if (msg[i].id == kTimerId) { | 185 if (msg[i].id == kTimerId) { |
| 202 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); | 186 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); |
| 203 } else if (msg[i].id == kShutdownId) { | 187 } else if (msg[i].id == kShutdownId) { |
| 204 shutdown_ = true; | 188 shutdown_ = true; |
| 205 } else { | 189 } else { |
| 206 bool is_new = false; | 190 SocketData* sd = GetSocketData(msg[i].id); |
| 207 SocketData* sd = GetSocketData(msg[i].id, &is_new); | |
| 208 if (is_new) { | |
| 209 sd->SetPortAndMask(msg[i].dart_port, msg[i].data); | |
| 210 } | |
| 211 if ((msg[i].data & (1 << kShutdownReadCommand)) != 0) { | 191 if ((msg[i].data & (1 << kShutdownReadCommand)) != 0) { |
| 212 ASSERT(msg[i].data == (1 << kShutdownReadCommand)); | 192 ASSERT(msg[i].data == (1 << kShutdownReadCommand)); |
| 213 // Close the socket for reading. | 193 // Close the socket for reading. |
| 214 sd->ShutdownRead(); | 194 shutdown(sd->fd(), SHUT_RD); |
| 215 } else if ((msg[i].data & (1 << kShutdownWriteCommand)) != 0) { | 195 } else if ((msg[i].data & (1 << kShutdownWriteCommand)) != 0) { |
| 216 ASSERT(msg[i].data == (1 << kShutdownWriteCommand)); | 196 ASSERT(msg[i].data == (1 << kShutdownWriteCommand)); |
| 217 // Close the socket for writing. | 197 // Close the socket for writing. |
| 218 sd->ShutdownWrite(); | 198 shutdown(sd->fd(), SHUT_WR); |
| 219 } else if ((msg[i].data & (1 << kCloseCommand)) != 0) { | 199 } else if ((msg[i].data & (1 << kCloseCommand)) != 0) { |
| 220 ASSERT(msg[i].data == (1 << kCloseCommand)); | 200 ASSERT(msg[i].data == (1 << kCloseCommand)); |
| 221 // Close the socket and free system resources. | 201 // Close the socket and free system resources. |
| 222 RemoveFromKqueue(kqueue_fd_, sd); | 202 RemoveFromKqueue(kqueue_fd_, sd); |
| 223 intptr_t fd = sd->fd(); | 203 intptr_t fd = sd->fd(); |
| 224 sd->Close(); | 204 sd->Close(); |
| 225 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); | 205 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); |
| 226 delete sd; | 206 delete sd; |
| 227 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); | 207 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); |
| 228 } else { | 208 } else if ((msg[i].data & (1 << kReturnTokenCommand)) != 0) { |
| 229 if (is_new) { | 209 if (sd->ReturnToken()) { |
| 230 AddToKqueue(kqueue_fd_, sd); | 210 AddToKqueue(kqueue_fd_, sd); |
| 231 } | 211 } |
| 212 } else { |
| 213 // Setup events to wait for. |
| 214 ASSERT((msg[i].data > 0) && (msg[i].data < kIntptrMax)); |
| 215 ASSERT(sd->port() == 0); |
| 216 sd->SetPortAndMask(msg[i].dart_port, |
| 217 static_cast<intptr_t>(msg[i].data)); |
| 218 AddToKqueue(kqueue_fd_, sd); |
| 232 } | 219 } |
| 233 } | 220 } |
| 234 } | 221 } |
| 235 } | 222 } |
| 236 | 223 |
| 237 #ifdef DEBUG_KQUEUE | 224 #ifdef DEBUG_KQUEUE |
| 238 static void PrintEventMask(intptr_t fd, struct kevent* event) { | 225 static void PrintEventMask(intptr_t fd, struct kevent* event) { |
| 239 Log::Print("%d ", static_cast<int>(fd)); | 226 Log::Print("%d ", static_cast<int>(fd)); |
| 240 Log::Print("filter=0x%x:", event->filter); | 227 Log::Print("filter=0x%x:", event->filter); |
| 241 if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ "); | 228 if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ "); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 char error_message[kBufferSize]; | 300 char error_message[kBufferSize]; |
| 314 strerror_r(events[i].data, error_message, kBufferSize); | 301 strerror_r(events[i].data, error_message, kBufferSize); |
| 315 FATAL1("kevent failed %s\n", error_message); | 302 FATAL1("kevent failed %s\n", error_message); |
| 316 } | 303 } |
| 317 if (events[i].udata == NULL) { | 304 if (events[i].udata == NULL) { |
| 318 interrupt_seen = true; | 305 interrupt_seen = true; |
| 319 } else { | 306 } else { |
| 320 SocketData* sd = reinterpret_cast<SocketData*>(events[i].udata); | 307 SocketData* sd = reinterpret_cast<SocketData*>(events[i].udata); |
| 321 intptr_t event_mask = GetEvents(events + i, sd); | 308 intptr_t event_mask = GetEvents(events + i, sd); |
| 322 if (event_mask != 0) { | 309 if (event_mask != 0) { |
| 310 if (sd->TakeToken()) { |
| 311 // Took last token, remove from epoll. |
| 312 RemoveFromKqueue(kqueue_fd_, sd); |
| 313 } |
| 323 Dart_Port port = sd->port(); | 314 Dart_Port port = sd->port(); |
| 324 ASSERT(port != 0); | 315 ASSERT(port != 0); |
| 325 DartUtils::PostInt32(port, event_mask); | 316 DartUtils::PostInt32(port, event_mask); |
| 326 } | 317 } |
| 327 } | 318 } |
| 328 } | 319 } |
| 329 if (interrupt_seen) { | 320 if (interrupt_seen) { |
| 330 // Handle after socket events, so we avoid closing a socket before we handle | 321 // Handle after socket events, so we avoid closing a socket before we handle |
| 331 // the current events. | 322 // the current events. |
| 332 HandleInterruptFd(); | 323 HandleInterruptFd(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 int result = | 392 int result = |
| 402 dart::Thread::Start(&EventHandlerImplementation::EventHandlerEntry, | 393 dart::Thread::Start(&EventHandlerImplementation::EventHandlerEntry, |
| 403 reinterpret_cast<uword>(handler)); | 394 reinterpret_cast<uword>(handler)); |
| 404 if (result != 0) { | 395 if (result != 0) { |
| 405 FATAL1("Failed to start event handler thread %d", result); | 396 FATAL1("Failed to start event handler thread %d", result); |
| 406 } | 397 } |
| 407 } | 398 } |
| 408 | 399 |
| 409 | 400 |
| 410 void EventHandlerImplementation::Shutdown() { | 401 void EventHandlerImplementation::Shutdown() { |
| 411 Notify(kShutdownId, 0, 0); | 402 SendData(kShutdownId, 0, 0); |
| 412 } | 403 } |
| 413 | 404 |
| 414 | 405 |
| 415 void EventHandlerImplementation::Notify(intptr_t id, | 406 void EventHandlerImplementation::SendData(intptr_t id, |
| 416 Dart_Port dart_port, | 407 Dart_Port dart_port, |
| 417 int64_t data) { | 408 int64_t data) { |
| 418 WakeupHandler(id, dart_port, data); | 409 WakeupHandler(id, dart_port, data); |
| 419 } | 410 } |
| 420 | 411 |
| 421 | 412 |
| 422 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { | 413 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { |
| 423 // The hashmap does not support keys with value 0. | 414 // The hashmap does not support keys with value 0. |
| 424 return reinterpret_cast<void*>(fd + 1); | 415 return reinterpret_cast<void*>(fd + 1); |
| 425 } | 416 } |
| 426 | 417 |
| 427 | 418 |
| 428 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { | 419 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { |
| 429 // The hashmap does not support keys with value 0. | 420 // The hashmap does not support keys with value 0. |
| 430 return dart::Utils::WordHash(fd + 1); | 421 return dart::Utils::WordHash(fd + 1); |
| 431 } | 422 } |
| 432 | 423 |
| 433 } // namespace bin | 424 } // namespace bin |
| 434 } // namespace dart | 425 } // namespace dart |
| 435 | 426 |
| 436 #endif // defined(TARGET_OS_MACOS) | 427 #endif // defined(TARGET_OS_MACOS) |
| OLD | NEW |