X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FTimerSource.cc;h=fe6b7d1a380932e13fbb5764dd2870a65a14a3c0;hb=532240d72e09e19e57fac9bb55c2560b9c9e5b97;hp=84048b09fa03b08d7ab3aed197cd98024f1db730;hpb=b76d83f9671e935cbd5f2c6873efae1f75d25dac;p=senf.git diff --git a/Scheduler/TimerSource.cc b/Scheduler/TimerSource.cc index 84048b0..fe6b7d1 100644 --- a/Scheduler/TimerSource.cc +++ b/Scheduler/TimerSource.cc @@ -28,6 +28,9 @@ // Custom includes #include "FdEvent.hh" +#ifdef HAVE_TIMERFD +#include +#endif //#include "TimerSource.mpp" #define prefix_ @@ -168,6 +171,101 @@ prefix_ void senf::scheduler::detail::PollTimerSource::enable() prefix_ void senf::scheduler::detail::PollTimerSource::disable() {} +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::detail::TimerFDTimerSource + +#ifdef HAVE_TIMERFD +prefix_ senf::scheduler::detail::TimerFDTimerSource::TimerFDTimerSource() + : timerfd_ (-1), timeoutEnabled_ (false), timeout_ (0) +{ + timerfd_ = timerfd_create(CLOCK_MONOTONIC, 0); + if (timerfd_ < 0) + SENF_THROW_SYSTEM_EXCEPTION("timerfd_create()"); + senf::scheduler::detail::FdManager::instance().set( + timerfd_, detail::FdManager::EV_READ, this); +} + +prefix_ senf::scheduler::detail::TimerFDTimerSource::~TimerFDTimerSource() +{ + senf::scheduler::detail::FdManager::instance().remove(timerfd_); + close(timerfd_); +} + +prefix_ void +senf::scheduler::detail::TimerFDTimerSource::timeout(ClockService::clock_type timeout) +{ + if (!timeoutEnabled_ || timeout_ != timeout) { + timeout_ = timeout; + if (timeout_ <= 0) + timeout_ = 1; + timeoutEnabled_ = true; + reschedule(); + } +} + +prefix_ void senf::scheduler::detail::TimerFDTimerSource::notimeout() +{ + if (timeoutEnabled_) { + timeoutEnabled_ = false; + reschedule(); + } +} + +prefix_ void senf::scheduler::detail::TimerFDTimerSource::enable() +{} + +prefix_ void senf::scheduler::detail::TimerFDTimerSource::disable() +{} + +namespace { + + struct TimerFdCheck + { + TimerFdCheck(); + bool timerFdOk; + }; + + TimerFdCheck::TimerFdCheck() + : timerFdOk (false) + { + int fd (timerfd_create(CLOCK_MONOTONIC, 0)); + if (fd == -1) { + if (errno != EINVAL) + SENF_THROW_SYSTEM_EXCEPTION("timerfd_create()"); + } + else { + timerFdOk = true; + close(fd); + } + } + +} +prefix_ bool senf::scheduler::detail::TimerFDTimerSource::haveTimerFD() +{ + static TimerFdCheck check; + return check.timerFdOk; +} + +prefix_ void senf::scheduler::detail::TimerFDTimerSource::signal(int events) +{ + uint64_t expirations (0); + read(timerfd_, &expirations, sizeof(expirations)); +} + +prefix_ void senf::scheduler::detail::TimerFDTimerSource::reschedule() +{ + struct itimerspec timer; + memset(&timer, 0, sizeof(timer)); + if (timeoutEnabled_) { + timer.it_value.tv_sec = ClockService::in_seconds(timeout_); + timer.it_value.tv_nsec = ClockService::in_nanoseconds( + timeout_ - ClockService::seconds(timer.it_value.tv_sec)); + } + if (timerfd_settime(timerfd_, TIMER_ABSTIME, &timer, 0)<0) + SENF_THROW_SYSTEM_EXCEPTION("timerfd_settime()"); +} +#endif + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "TimerSource.mpp"