Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Unified Diff: runtime/bin/eventhandler_linux.cc

Issue 104803005: Use timerfd to handler timeouts on Linux. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Close timer fd. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/eventhandler_linux.h ('k') | sdk/lib/io/timer_impl.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/eventhandler_linux.cc
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index c7e19695ca40e487ce935f63daf91743643693e6..572a0f6332d495167038804ce8893e0c59c4e1f2 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -13,6 +13,7 @@
#include <string.h> // NOLINT
#include <sys/epoll.h> // NOLINT
#include <sys/stat.h> // NOLINT
+#include <sys/timerfd.h> // NOLINT
#include <unistd.h> // NOLINT
#include <fcntl.h> // NOLINT
@@ -29,7 +30,6 @@ namespace dart {
namespace bin {
static const int kInterruptMessageSize = sizeof(InterruptMessage);
-static const int kInfinityTimeout = -1;
static const int kTimerId = -1;
static const int kShutdownId = -2;
@@ -134,11 +134,27 @@ EventHandlerImplementation::EventHandlerImplementation()
if (status == -1) {
FATAL("Failed adding interrupt fd to epoll instance");
}
+ timer_fd_ = TEMP_FAILURE_RETRY(timerfd_create(CLOCK_REALTIME,
+ TFD_NONBLOCK | TFD_CLOEXEC));
+ if (epoll_fd_ == -1) {
+ FATAL("Failed creating timerfd file descriptor");
+ }
+ // Register the timer_fd_ with the epoll instance.
+ event.events = EPOLLIN;
+ event.data.fd = timer_fd_;
+ status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_,
+ EPOLL_CTL_ADD,
+ timer_fd_,
+ &event));
+ if (status == -1) {
+ FATAL("Failed adding timerfd fd to epoll instance");
+ }
}
EventHandlerImplementation::~EventHandlerImplementation() {
TEMP_FAILURE_RETRY(close(epoll_fd_));
+ TEMP_FAILURE_RETRY(close(timer_fd_));
TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
}
@@ -191,6 +207,14 @@ void EventHandlerImplementation::HandleInterruptFd() {
for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) {
if (msg[i].id == kTimerId) {
Søren Gjesse 2013/12/05 07:39:34 With this approach do we even need to send this th
Anders Johnsen 2013/12/05 09:18:28 The alternative is to have a FD per isolate, but t
timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data);
+ struct itimerspec it;
+ memset(&it, 0, sizeof(it));
+ if (timeout_queue_.HasTimeout()) {
+ int64_t millis = timeout_queue_.CurrentTimeout();
+ it.it_value.tv_sec = millis / 1000;
+ it.it_value.tv_nsec = (millis % 1000) * 1000000;
+ }
+ timerfd_settime(timer_fd_, TFD_TIMER_ABSTIME, &it, NULL);
Søren Gjesse 2013/12/05 07:39:34 If the abs time set here has just passed will the
Anders Johnsen 2013/12/05 09:18:28 Yes, from spec: "If the specified absolute time
} else if (msg[i].id == kShutdownId) {
shutdown_ = true;
} else {
@@ -338,6 +362,13 @@ void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
for (int i = 0; i < size; i++) {
if (events[i].data.ptr == NULL) {
interrupt_seen = true;
+ } else if (events[i].data.fd == timer_fd_) {
+ int64_t val;
+ VOID_TEMP_FAILURE_RETRY(read(timer_fd_, &val, 8));
Søren Gjesse 2013/12/05 07:39:34 Should we have a constant for '8' here just to ind
Anders Johnsen 2013/12/05 09:18:28 I'll use sizeof val.
+ if (timeout_queue_.HasTimeout()) {
+ DartUtils::PostNull(timeout_queue_.CurrentPort());
+ timeout_queue_.RemoveCurrent();
+ }
} else {
SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr);
intptr_t event_mask = GetPollEvents(events[i].events, sd);
@@ -359,29 +390,6 @@ void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
}
-int64_t EventHandlerImplementation::GetTimeout() {
- if (!timeout_queue_.HasTimeout()) {
- return kInfinityTimeout;
- }
- int64_t millis = timeout_queue_.CurrentTimeout() -
- TimerUtils::GetCurrentTimeMilliseconds();
- return (millis < 0) ? 0 : millis;
-}
-
-
-void EventHandlerImplementation::HandleTimeout() {
- if (timeout_queue_.HasTimeout()) {
- int64_t millis = timeout_queue_.CurrentTimeout() -
- TimerUtils::GetCurrentTimeMilliseconds();
- if (millis <= 0) {
- DartUtils::PostNull(timeout_queue_.CurrentPort());
- // Remove current from queue.
- timeout_queue_.RemoveCurrent();
- }
- }
-}
-
-
void EventHandlerImplementation::Poll(uword args) {
static const intptr_t kMaxEvents = 16;
struct epoll_event events[kMaxEvents];
@@ -389,20 +397,15 @@ void EventHandlerImplementation::Poll(uword args) {
EventHandlerImplementation* handler_impl = &handler->delegate_;
ASSERT(handler_impl != NULL);
while (!handler_impl->shutdown_) {
- int64_t millis = handler_impl->GetTimeout();
- ASSERT(millis == kInfinityTimeout || millis >= 0);
- if (millis > kMaxInt32) millis = kMaxInt32;
intptr_t result = TEMP_FAILURE_RETRY(epoll_wait(handler_impl->epoll_fd_,
events,
kMaxEvents,
- millis));
+ -1));
Søren Gjesse 2013/12/05 07:39:34 Is there a constant for infinite?
Anders Johnsen 2013/12/05 09:18:28 -1 is special-case for epoll_wait, to wait forever
ASSERT(EAGAIN == EWOULDBLOCK);
- if (result == -1) {
+ if (result <= 0) {
if (errno != EWOULDBLOCK) {
perror("Poll failed");
}
- } else if (result == 0) {
- handler_impl->HandleTimeout();
} else {
handler_impl->HandleEvents(events, result);
}
« no previous file with comments | « runtime/bin/eventhandler_linux.h ('k') | sdk/lib/io/timer_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698