X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FTimerSource.cc;h=fe6b7d1a380932e13fbb5764dd2870a65a14a3c0;hb=532240d72e09e19e57fac9bb55c2560b9c9e5b97;hp=17d2de7eb91aef46cf967fec2a1ef308d5686182;hpb=8057a9e389e33771aad9c78538f76d0e82ad7adb;p=senf.git diff --git a/Scheduler/TimerSource.cc b/Scheduler/TimerSource.cc index 17d2de7..fe6b7d1 100644 --- a/Scheduler/TimerSource.cc +++ b/Scheduler/TimerSource.cc @@ -27,6 +27,10 @@ //#include "TimerSource.ih" // Custom includes +#include "FdEvent.hh" +#ifdef HAVE_TIMERFD +#include +#endif //#include "TimerSource.mpp" #define prefix_ @@ -146,6 +150,122 @@ prefix_ void senf::scheduler::detail::POSIXTimerSource::reschedule() SENF_THROW_SYSTEM_EXCEPTION("timer_settime()"); } +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::detail::PollTimerSource + +prefix_ void senf::scheduler::detail::PollTimerSource::timeout(ClockService::clock_type timeout) +{ + ClockService::clock_type now (ClockService::now()); + int delay (ClockService::in_milliseconds(timeout-now)+1); + FileDispatcher::instance().timeout(delay<0?0:delay); +} + +prefix_ void senf::scheduler::detail::PollTimerSource::notimeout() +{ + FileDispatcher::instance().timeout(-1); +} + +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"