Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 #if defined(FLETCH_TARGET_OS_LINUX) | 5 #if defined(FLETCH_TARGET_OS_LINUX) |
| 6 | 6 |
| 7 #include "src/vm/event_handler.h" | 7 #include "src/vm/event_handler.h" |
| 8 | 8 |
| 9 #include <sys/epoll.h> | 9 #include <sys/epoll.h> |
| 10 #include <sys/timerfd.h> | |
| 10 #include <sys/types.h> | 11 #include <sys/types.h> |
| 11 #include <fcntl.h> | 12 #include <fcntl.h> |
| 12 #include <unistd.h> | 13 #include <unistd.h> |
| 13 | 14 |
| 15 #include "src/shared/utils.h" | |
| 14 #include "src/vm/thread.h" | 16 #include "src/vm/thread.h" |
| 17 #include "src/vm/vector.h" | |
| 15 | 18 |
| 16 // Some versions of android sys/epoll does not define | 19 // Some versions of android sys/epoll does not define |
| 17 // EPOLLRDHUP. However, it works as intended, so we just | 20 // EPOLLRDHUP. However, it works as intended, so we just |
| 18 // define it if it is not there. | 21 // define it if it is not there. |
| 19 #if !defined(EPOLLRDHUP) | 22 #if !defined(EPOLLRDHUP) |
| 20 #define EPOLLRDHUP 0x2000 | 23 #define EPOLLRDHUP 0x2000 |
| 21 #endif // !defined(EPOLLRDHUP) | 24 #endif // !defined(EPOLLRDHUP) |
| 22 | 25 |
| 23 namespace fletch { | 26 namespace fletch { |
| 24 | 27 |
| 25 int EventHandler::Create() { | 28 int EventHandler::Create() { |
| 26 int fd = epoll_create(1); | 29 int fd = epoll_create(1); |
| 27 int status = fcntl(fd, F_SETFD, FD_CLOEXEC); | 30 int status = fcntl(fd, F_SETFD, FD_CLOEXEC); |
| 28 if (status == -1) FATAL("Failed making epoll descriptor close on exec."); | 31 if (status == -1) FATAL("Failed making epoll descriptor close on exec."); |
| 29 return fd; | 32 return fd; |
| 30 } | 33 } |
| 31 | 34 |
| 32 void EventHandler::Run() { | 35 void EventHandler::Run() { |
| 33 struct epoll_event event; | 36 struct epoll_event event; |
| 34 event.events = EPOLLHUP | EPOLLRDHUP; | 37 event.events = EPOLLHUP | EPOLLRDHUP | EPOLLIN; |
| 35 event.data.fd = read_fd_; | 38 event.data.fd = read_fd_; |
| 36 epoll_ctl(fd_, EPOLL_CTL_ADD, read_fd_, &event); | 39 epoll_ctl(fd_, EPOLL_CTL_ADD, read_fd_, &event); |
| 37 while (true) { | 40 while (true) { |
| 38 int status = epoll_wait(fd_, &event, 1, -1); | 41 int64 next_timeout; |
| 42 { | |
| 43 ScopedMonitorLock locker(monitor_); | |
| 44 next_timeout = next_timeout_; | |
| 45 } | |
| 46 | |
| 47 if (next_timeout == INT64_MAX) { | |
| 48 next_timeout = -1; | |
| 49 } else { | |
| 50 next_timeout -= Platform::GetMicroseconds() / 1000LL; | |
| 51 if (next_timeout < 0) next_timeout = 0; | |
| 52 } | |
| 53 | |
| 54 int status = epoll_wait(fd_, &event, 1, next_timeout); | |
| 55 | |
| 56 { | |
| 57 // Check timeouts. | |
| 58 int64 current_time = Platform::GetMicroseconds() / 1000LL; | |
| 59 ScopedMonitorLock scoped_lock(monitor_); | |
| 60 if (next_timeout_ <= current_time) { | |
| 61 int64 next_timeout = INT64_MAX; | |
| 62 // TODO(ajohnsen): We could consider a heap structure to avoid O(n^2) in | |
| 63 // this case? | |
| 64 while (true) { | |
|
Mads Ager (google)
2015/10/01 14:08:37
Would this be easier to read if it was a do-while?
Anders Johnsen
2015/10/02 00:25:14
I need to reset found to false, so sadly not a rea
| |
| 65 bool found = false; | |
| 66 for (auto it = timeouts_.Begin(); it != timeouts_.End(); ++it) { | |
| 67 if (it->second <= current_time) { | |
| 68 Send(it->first, 0); | |
| 69 timeouts_.Erase(it); | |
| 70 found = true; | |
| 71 break; | |
| 72 } else { | |
| 73 next_timeout = Utils::Minimum(next_timeout, it->second); | |
| 74 } | |
| 75 } | |
| 76 if (!found) break; | |
| 77 } | |
| 78 next_timeout_ = next_timeout; | |
| 79 } | |
| 80 } | |
| 81 | |
| 39 if (status != 1) continue; | 82 if (status != 1) continue; |
| 40 | 83 |
| 84 int events = event.events; | |
| 85 | |
| 41 if (event.data.fd == read_fd_) { | 86 if (event.data.fd == read_fd_) { |
| 42 close(read_fd_); | 87 if ((events & EPOLLIN) != 0) { |
| 43 close(fd_); | 88 char b; |
| 89 read(read_fd_, &b, 1); | |
| 90 continue; | |
| 91 } else { | |
| 92 close(read_fd_); | |
| 93 close(fd_); | |
| 44 | 94 |
| 45 ScopedMonitorLock locker(monitor_); | 95 ScopedMonitorLock locker(monitor_); |
| 46 fd_ = -1; | 96 fd_ = -1; |
| 47 monitor_->Notify(); | 97 monitor_->Notify(); |
| 48 return; | 98 return; |
| 99 } | |
| 49 } | 100 } |
| 50 | 101 |
| 51 int events = event.events; | |
| 52 word mask = 0; | 102 word mask = 0; |
| 53 if ((events & EPOLLIN) != 0) mask |= READ_EVENT; | 103 if ((events & EPOLLIN) != 0) mask |= READ_EVENT; |
| 54 if ((events & EPOLLOUT) != 0) mask |= WRITE_EVENT; | 104 if ((events & EPOLLOUT) != 0) mask |= WRITE_EVENT; |
| 55 if ((events & EPOLLRDHUP) != 0) mask |= CLOSE_EVENT; | 105 if ((events & EPOLLRDHUP) != 0) mask |= CLOSE_EVENT; |
| 56 if ((events & EPOLLHUP) != 0) mask |= CLOSE_EVENT; | 106 if ((events & EPOLLHUP) != 0) mask |= CLOSE_EVENT; |
| 57 if ((events & EPOLLERR) != 0) mask |= ERROR_EVENT; | 107 if ((events & EPOLLERR) != 0) mask |= ERROR_EVENT; |
| 58 | 108 |
| 59 Port* port = reinterpret_cast<Port*>(event.data.ptr); | 109 Port* port = reinterpret_cast<Port*>(event.data.ptr); |
| 60 Send(port, mask); | 110 Send(port, mask); |
| 61 } | 111 } |
| 62 } | 112 } |
| 63 | 113 |
| 64 } // namespace fletch | 114 } // namespace fletch |
| 65 | 115 |
| 66 #endif // defined(FLETCH_TARGET_OS_LINUX) | 116 #endif // defined(FLETCH_TARGET_OS_LINUX) |
| OLD | NEW |