X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FClockService.cc;h=44b54046e365c07df2d566f7c36d0aa33acfe25e;hb=51044eb18f034c1a059ffe2fb109a422c1cbe251;hp=010bd2093a0aa32936ec1b1540dbcdc5061698e0;hpb=3d16600678b948ff3bd0e4fd2a1a800fcc629a03;p=senf.git diff --git a/Scheduler/ClockService.cc b/Scheduler/ClockService.cc index 010bd20..44b5404 100644 --- a/Scheduler/ClockService.cc +++ b/Scheduler/ClockService.cc @@ -1,8 +1,8 @@ // $Id$ // // Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -31,13 +31,16 @@ #include #include #include -#include "Utils/Exception.hh" +#include "../Utils/Exception.hh" //#include "ClockService.mpp" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -#define CheckErrno(op,args) if (op args < 0) throw SystemException(# op, errno) +#define CheckError(op,args) if (op args < 0) throwErrno(# op, errno) + +/////////////////////////////////////////////////////////////////////////// +// senf::ClockService::Impl struct senf::ClockService::Impl { @@ -46,6 +49,7 @@ struct senf::ClockService::Impl void block(); void unblock(); + /// Internal: temporarily block signals (RAII idiom) struct Blocker { Blocker(Impl * i) : impl(i) { impl->block(); } ~Blocker() { impl->unblock(); } @@ -61,28 +65,23 @@ struct senf::ClockService::Impl prefix_ senf::ClockService::Impl::Impl() { - CheckErrno( sigemptyset, (&alrm_set) ); - CheckErrno( sigaddset, (&alrm_set, SIGALRM) ); + CheckError( sigemptyset, (&alrm_set) ); + CheckError( sigaddset, (&alrm_set, SIGALRM) ); } prefix_ void senf::ClockService::Impl::block() { - CheckErrno( sigprocmask, (SIG_BLOCK, &alrm_set, 0) ); + CheckError( sigprocmask, (SIG_BLOCK, &alrm_set, 0) ); } prefix_ void senf::ClockService::Impl::unblock() { - CheckErrno( sigprocmask, (SIG_UNBLOCK, &alrm_set, 0) ); + CheckError( sigprocmask, (SIG_UNBLOCK, &alrm_set, 0) ); } prefix_ void senf::ClockService::Impl::timer(int) { - boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time()); - if (ClockService::instance().checkSkew(time)) - ClockService::instance().clockSkew( - time, ClockService::instance().heartbeat_ + boost::posix_time::seconds( - ClockService::CheckInterval)); - ClockService::instance().heartbeat_ = time; + ClockService::instance().timer(); } /////////////////////////////////////////////////////////////////////////// @@ -98,54 +97,67 @@ prefix_ senf::ClockService::~ClockService() // private members prefix_ senf::ClockService::ClockService() - : base_ (boost::posix_time::microsec_clock::universal_time()), - heartbeat_ (base_), impl_(new ClockService::Impl()) + : impl_(new ClockService::Impl()) { - struct sigaction action; - action.sa_handler = & senf::ClockService::Impl::timer; - CheckErrno( sigemptyset, (&action.sa_mask) ); - action.sa_flags = SA_RESTART; - CheckErrno( sigaction, (SIGALRM, &action, &impl_->oldaction) ); + restart_m(false); +} - struct itimerval itimer; - itimer.it_interval.tv_sec = CheckInterval; - itimer.it_interval.tv_usec = 0; - itimer.it_value.tv_sec = CheckInterval; - itimer.it_value.tv_usec = 0; - CheckErrno( setitimer, (ITIMER_REAL, &itimer, &impl_->olditimer) ); - impl_->unblock(); +prefix_ void senf::ClockService::timer() +{ + boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time()); + if (checkSkew(time)) + clockSkew(time, heartbeat_ + boost::posix_time::seconds( + ClockService::CheckInterval)); + heartbeat_ = time; } -prefix_ void senf::ClockService::restart_i() +prefix_ void senf::ClockService::restart_m(bool restart) { - impl_->block(); // if any syscall fails, the alarm signal stays blocked which is correct + if (restart) + // if any syscall fails, the alarm signal stays blocked which is correct + impl_->block(); + base_ = boost::posix_time::microsec_clock::universal_time(); heartbeat_ = base_; struct sigaction action; action.sa_handler = & senf::ClockService::Impl::timer; - CheckErrno( sigemptyset, (&action.sa_mask) ); + CheckError( sigemptyset, (&action.sa_mask) ); action.sa_flags = SA_RESTART; - CheckErrno( sigaction, (SIGALRM, &action, 0) ); + CheckError( sigaction, (SIGALRM, &action, restart ? 0 : &impl_->oldaction) ); + restartTimer(restart); + + impl_->unblock(); +} + +prefix_ void senf::ClockService::restartTimer(bool restart) +{ struct itimerval itimer; itimer.it_interval.tv_sec = CheckInterval; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = CheckInterval; itimer.it_value.tv_usec = 0; - CheckErrno( setitimer, (ITIMER_REAL, &itimer, 0) ); - impl_->unblock(); + CheckError( setitimer, (ITIMER_REAL, &itimer, restart ? 0 : &impl_->olditimer) ); } prefix_ void senf::ClockService::updateSkew(boost::posix_time::ptime time) { Impl::Blocker alrmBlocker (impl_.get()); - struct itimerval itimer; - CheckErrno( getitimer, (ITIMER_REAL, &itimer) ); - clockSkew(time, (heartbeat_ - + boost::posix_time::seconds(CheckInterval) - - boost::posix_time::seconds(itimer.it_value.tv_sec) - - boost::posix_time::microseconds(itimer.it_value.tv_usec))); + + // Make a second 'checkSkew' test, this time with SIGALRM blocked. See + // senf::ClockService::now_i() + + if (checkSkew(time)) { + struct itimerval itimer; + CheckError( getitimer, (ITIMER_REAL, &itimer) ); + clockSkew(time, (heartbeat_ + + boost::posix_time::seconds(CheckInterval) + - boost::posix_time::seconds(itimer.it_value.tv_sec) + - boost::posix_time::microseconds(itimer.it_value.tv_usec))); + heartbeat_ = time; + restartTimer(); + } } ///////////////////////////////cc.e////////////////////////////////////////