From: g0dil Date: Thu, 19 Feb 2009 12:13:32 +0000 (+0000) Subject: Scheduler: Implement TimerFDTimerSource X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=556aea04a82b3e2e5cdfe28a0abd3b275c7decf9;p=senf.git Scheduler: Implement TimerFDTimerSource git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1128 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Scheduler/Scheduler.cci b/Scheduler/Scheduler.cci index b20de6e..acce9db 100644 --- a/Scheduler/Scheduler.cci +++ b/Scheduler/Scheduler.cci @@ -56,8 +56,14 @@ prefix_ unsigned senf::scheduler::hangCount() prefix_ void senf::scheduler::hiresTimers() { - detail::TimerDispatcher::instance().timerSource( - std::auto_ptr(new detail::POSIXTimerSource())); +#ifdef HAVE_TIMERFD + if (haveScalableHiresTimers()) + detail::TimerDispatcher::instance().timerSource( + std::auto_ptr(new detail::TimerFDTimerSource())); + else +#endif + detail::TimerDispatcher::instance().timerSource( + std::auto_ptr(new detail::POSIXTimerSource())); } prefix_ void senf::scheduler::loresTimers() @@ -68,7 +74,11 @@ prefix_ void senf::scheduler::loresTimers() prefix_ bool senf::scheduler::haveScalableHiresTimers() { +#ifndef HAVE_TIMERFD return false; +#else + return true; +#endif } prefix_ bool senf::scheduler::usingHiresTimers() diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index 2254cdb..75bc76a 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -294,7 +294,7 @@ void schedulerTest() BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE ); BOOST_CHECK( ! timer2.enabled() ); - BOOST_WARN_MESSAGE( false, "A 'Scheduler task hanging' error is expected to be signaled here." ); + BOOST_MESSAGE( "A 'Scheduler task hanging' error is expected to be signaled here." ); SENF_CHECK_NO_THROW( timer1.action(&blockingHandler) ); SENF_CHECK_NO_THROW( timer1.timeout(senf::ClockService::now()) ); SENF_CHECK_NO_THROW( senf::scheduler::process() ); @@ -333,6 +333,10 @@ BOOST_AUTO_UNIT_TEST(testSchedulerPollTimers) BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers) { + if (senf::scheduler::haveScalableHiresTimers()) + BOOST_MESSAGE( "Using timerfd() hires timers" ); + else + BOOST_MESSAGE( "Using POSIX hires timers"); senf::scheduler::hiresTimers(); BOOST_CHECK( senf::scheduler::usingHiresTimers() ); schedulerTest(); @@ -340,6 +344,17 @@ BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers) BOOST_CHECK( ! senf::scheduler::usingHiresTimers() ); } +BOOST_AUTO_UNIT_TEST(testSchedulerPOSIXTimers) +{ + if (senf::scheduler::haveScalableHiresTimers()) { + senf::scheduler::detail::TimerDispatcher::instance().timerSource( + std::auto_ptr( + new senf::scheduler::detail::POSIXTimerSource())); + schedulerTest(); + senf::scheduler::loresTimers(); + } +} + namespace { void sigme() diff --git a/Scheduler/TimerSource.cc b/Scheduler/TimerSource.cc index 84048b0..ac1baa3 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,72 @@ 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() +{} + +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" diff --git a/Scheduler/TimerSource.hh b/Scheduler/TimerSource.hh index 4ae5719..d3afcad 100644 --- a/Scheduler/TimerSource.hh +++ b/Scheduler/TimerSource.hh @@ -92,6 +92,30 @@ namespace detail { virtual void disable(); }; +#ifdef HAVE_TIMERFD + class TimerFDTimerSource + : public detail::FdManager::Event, public TimerSource + { + public: + TimerFDTimerSource(); + ~TimerFDTimerSource(); + + virtual void timeout(ClockService::clock_type timeout); + virtual void notimeout(); + + virtual void enable(); + virtual void disable(); + + private: + virtual void signal(int events); + void reschedule(); + + int timerfd_; + bool timeoutEnabled_; + ClockService::clock_type timeout_; + }; +#endif + }}} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/config.hh b/config.hh index 12e24b5..bf13b1e 100644 --- a/config.hh +++ b/config.hh @@ -28,6 +28,7 @@ # # // Custom includes # include +# include # # ///////////////////////////////hh.p//////////////////////////////////////// @@ -96,6 +97,10 @@ namespace config { # ifndef PHOENIX_LIMIT # define PHOENIX_LIMIT 6 # endif +# +# if __GLIBC__>=2 && __GLIBC_MINOR__>=8 +# define HAVE_TIMERFD 1 +# endif # # ///////////////////////////////hh.e//////////////////////////////////////// # endif