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