Skip to content
Snippets Groups Projects
Commit b6cff3b9 authored by g0dil's avatar g0dil
Browse files

Scheduler: Implement TimerFDTimerSource

parent f7cd7d87
No related branches found
No related tags found
No related merge requests found
...@@ -56,8 +56,14 @@ prefix_ unsigned senf::scheduler::hangCount() ...@@ -56,8 +56,14 @@ prefix_ unsigned senf::scheduler::hangCount()
prefix_ void senf::scheduler::hiresTimers() prefix_ void senf::scheduler::hiresTimers()
{ {
detail::TimerDispatcher::instance().timerSource( #ifdef HAVE_TIMERFD
std::auto_ptr<detail::TimerSource>(new detail::POSIXTimerSource())); 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_ void senf::scheduler::loresTimers()
...@@ -68,7 +74,11 @@ prefix_ void senf::scheduler::loresTimers() ...@@ -68,7 +74,11 @@ prefix_ void senf::scheduler::loresTimers()
prefix_ bool senf::scheduler::haveScalableHiresTimers() prefix_ bool senf::scheduler::haveScalableHiresTimers()
{ {
#ifndef HAVE_TIMERFD
return false; return false;
#else
return true;
#endif
} }
prefix_ bool senf::scheduler::usingHiresTimers() prefix_ bool senf::scheduler::usingHiresTimers()
......
...@@ -294,7 +294,7 @@ void schedulerTest() ...@@ -294,7 +294,7 @@ void schedulerTest()
BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE ); BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE );
BOOST_CHECK( ! timer2.enabled() ); 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.action(&blockingHandler) );
SENF_CHECK_NO_THROW( timer1.timeout(senf::ClockService::now()) ); SENF_CHECK_NO_THROW( timer1.timeout(senf::ClockService::now()) );
SENF_CHECK_NO_THROW( senf::scheduler::process() ); SENF_CHECK_NO_THROW( senf::scheduler::process() );
...@@ -333,6 +333,10 @@ BOOST_AUTO_UNIT_TEST(testSchedulerPollTimers) ...@@ -333,6 +333,10 @@ BOOST_AUTO_UNIT_TEST(testSchedulerPollTimers)
BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers) 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(); senf::scheduler::hiresTimers();
BOOST_CHECK( senf::scheduler::usingHiresTimers() ); BOOST_CHECK( senf::scheduler::usingHiresTimers() );
schedulerTest(); schedulerTest();
...@@ -340,6 +344,17 @@ BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers) ...@@ -340,6 +344,17 @@ BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers)
BOOST_CHECK( ! senf::scheduler::usingHiresTimers() ); 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 { namespace {
void sigme() void sigme()
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
// Custom includes // Custom includes
#include "FdEvent.hh" #include "FdEvent.hh"
#ifdef HAVE_TIMERFD
#include <sys/timerfd.h>
#endif
//#include "TimerSource.mpp" //#include "TimerSource.mpp"
#define prefix_ #define prefix_
...@@ -168,6 +171,72 @@ prefix_ void senf::scheduler::detail::PollTimerSource::enable() ...@@ -168,6 +171,72 @@ prefix_ void senf::scheduler::detail::PollTimerSource::enable()
prefix_ void senf::scheduler::detail::PollTimerSource::disable() 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//////////////////////////////////////// ///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_ #undef prefix_
//#include "TimerSource.mpp" //#include "TimerSource.mpp"
......
...@@ -92,6 +92,30 @@ namespace detail { ...@@ -92,6 +92,30 @@ namespace detail {
virtual void disable(); 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//////////////////////////////////////// ///////////////////////////////hh.e////////////////////////////////////////
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
# #
# // Custom includes # // Custom includes
# include <boost/cstdint.hpp> # include <boost/cstdint.hpp>
# include <limits.h>
# #
# ///////////////////////////////hh.p//////////////////////////////////////// # ///////////////////////////////hh.p////////////////////////////////////////
...@@ -96,6 +97,10 @@ namespace config { ...@@ -96,6 +97,10 @@ namespace config {
# ifndef PHOENIX_LIMIT # ifndef PHOENIX_LIMIT
# define PHOENIX_LIMIT 6 # define PHOENIX_LIMIT 6
# endif # endif
#
# if __GLIBC__>=2 && __GLIBC_MINOR__>=8
# define HAVE_TIMERFD 1
# endif
# #
# ///////////////////////////////hh.e//////////////////////////////////////// # ///////////////////////////////hh.e////////////////////////////////////////
# endif # endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment