prefix_ void senf::scheduler::hiresTimers()
{
- detail::TimerDispatcher::instance().timerSource(
- std::auto_ptr<detail::TimerSource>(new detail::POSIXTimerSource()));
+#ifdef HAVE_TIMERFD
+ if (haveScalableHiresTimers())
+ detail::TimerDispatcher::instance().timerSource(
+ std::auto_ptr<detail::TimerSource>(new detail::TimerFDTimerSource()));
+ else
+#endif
+ detail::TimerDispatcher::instance().timerSource(
+ std::auto_ptr<detail::TimerSource>(new detail::POSIXTimerSource()));
}
prefix_ void senf::scheduler::loresTimers()
prefix_ bool senf::scheduler::haveScalableHiresTimers()
{
+#ifndef HAVE_TIMERFD
return false;
+#else
+ return true;
+#endif
}
prefix_ bool senf::scheduler::usingHiresTimers()
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() );
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();
BOOST_CHECK( ! senf::scheduler::usingHiresTimers() );
}
+BOOST_AUTO_UNIT_TEST(testSchedulerPOSIXTimers)
+{
+ if (senf::scheduler::haveScalableHiresTimers()) {
+ senf::scheduler::detail::TimerDispatcher::instance().timerSource(
+ std::auto_ptr<senf::scheduler::detail::TimerSource>(
+ new senf::scheduler::detail::POSIXTimerSource()));
+ schedulerTest();
+ senf::scheduler::loresTimers();
+ }
+}
+
namespace {
void sigme()
// Custom includes
#include "FdEvent.hh"
+#ifdef HAVE_TIMERFD
+#include <sys/timerfd.h>
+#endif
//#include "TimerSource.mpp"
#define prefix_
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"
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////////////////////////////////////////
#
# // Custom includes
# include <boost/cstdint.hpp>
+# include <limits.h>
#
# ///////////////////////////////hh.p////////////////////////////////////////
# ifndef PHOENIX_LIMIT
# define PHOENIX_LIMIT 6
# endif
+#
+# if __GLIBC__>=2 && __GLIBC_MINOR__>=8
+# define HAVE_TIMERFD 1
+# endif
#
# ///////////////////////////////hh.e////////////////////////////////////////
# endif