Scheduler: Add timerfd() kernel availability check
g0dil [Thu, 19 Feb 2009 12:44:01 +0000 (12:44 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1129 270642c3-0616-0410-b53a-bc976706d245

Scheduler/Scheduler.cc
Scheduler/Scheduler.cci
Scheduler/Scheduler.test.cc
Scheduler/TimerSource.cc
Scheduler/TimerSource.hh

index f40bf69..9457743 100644 (file)
@@ -123,6 +123,18 @@ prefix_ bool senf::scheduler::empty()
         && detail::EventHookDispatcher::instance().empty();
 }
 
+prefix_ void senf::scheduler::hiresTimers()
+{
+#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()));
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::schedulerLogTimeSource
 
index acce9db..75dcb06 100644 (file)
@@ -54,18 +54,6 @@ prefix_ unsigned senf::scheduler::hangCount()
     return scheduler::detail::FIFORunner::instance().hangCount();
 }
 
-prefix_ void senf::scheduler::hiresTimers()
-{
-#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()
 {
     detail::TimerDispatcher::instance().timerSource(
@@ -77,7 +65,7 @@ prefix_ bool senf::scheduler::haveScalableHiresTimers()
 #ifndef HAVE_TIMERFD
     return false;
 #else
-    return true;
+    return detail::TimerFDTimerSource::haveTimerFD();
 #endif
 }
 
index 75bc76a..08e9dc8 100644 (file)
@@ -337,19 +337,19 @@ BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers)
         BOOST_MESSAGE( "Using timerfd() hires timers" );
     else
         BOOST_MESSAGE( "Using POSIX hires timers");
-    senf::scheduler::hiresTimers();
+    SENF_CHECK_NO_THROW( senf::scheduler::hiresTimers() );
     BOOST_CHECK( senf::scheduler::usingHiresTimers() );
     schedulerTest();
-    senf::scheduler::loresTimers();
+    SENF_CHECK_NO_THROW( senf::scheduler::loresTimers() );
     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()));
+        SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().timerSource(
+                                 std::auto_ptr<senf::scheduler::detail::TimerSource>(
+                                     new senf::scheduler::detail::POSIXTimerSource())) );
         schedulerTest();
         senf::scheduler::loresTimers();
     }
index ac1baa3..fe6b7d1 100644 (file)
@@ -217,6 +217,35 @@ 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);
index d3afcad..c520348 100644 (file)
@@ -106,6 +106,8 @@ namespace detail {
         virtual void enable();
         virtual void disable();
 
+        static bool haveTimerFD();
+
     private:
         virtual void signal(int events);
         void reschedule();