X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FFIFORunner.cc;h=2b54eb6dc30d075421c4631c76825037bc3769e4;hb=04b5fd6be72efd504de15a215a268f8b82f4d132;hp=10cfdc2facc0ea84764703227ce8e84e05742766;hpb=40fa3e3f1e0f639c68bd15bf469e35045f94abee;p=senf.git diff --git a/Scheduler/FIFORunner.cc b/Scheduler/FIFORunner.cc index 10cfdc2..2b54eb6 100644 --- a/Scheduler/FIFORunner.cc +++ b/Scheduler/FIFORunner.cc @@ -30,13 +30,14 @@ #include #include #include "../Utils/Exception.hh" +#include "../Utils/senfassert.hh" //#include "FIFORunner.mpp" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ senf::scheduler::FIFORunner::FIFORunner() - : tasks_ (), next_ (tasks_.end()), hangCount_ (0) +prefix_ senf::scheduler::detail::FIFORunner::FIFORunner() + : tasks_ (), next_ (tasks_.end()), watchdogMs_ (1000), watchdogCount_(0), hangCount_ (0) { struct sigevent ev; ::memset(&ev, 0, sizeof(ev)); @@ -60,7 +61,7 @@ prefix_ senf::scheduler::FIFORunner::FIFORunner() SENF_THROW_SYSTEM_EXCEPTION("sigprocmask()"); } -prefix_ senf::scheduler::FIFORunner::~FIFORunner() +prefix_ senf::scheduler::detail::FIFORunner::~FIFORunner() { timer_delete(watchdogId_); signal(SIGURG, SIG_DFL); @@ -88,7 +89,7 @@ prefix_ senf::scheduler::FIFORunner::~FIFORunner() // will mostly be localized to the end of the queue. only occasionally one of the dormant tasks will // be runnable. This additional traversal time will be amortized over a larger time. -prefix_ void senf::scheduler::FIFORunner::dequeue(TaskInfo * task) +prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task) { TaskList::iterator i (TaskList::current(*task)); if (next_ == i) @@ -98,13 +99,14 @@ prefix_ void senf::scheduler::FIFORunner::dequeue(TaskInfo * task) namespace { struct NullTask - : public senf::scheduler::FIFORunner::TaskInfo + : public senf::scheduler::detail::FIFORunner::TaskInfo { + NullTask() : senf::scheduler::detail::FIFORunner::TaskInfo ("") {} void run() {}; }; } -prefix_ void senf::scheduler::FIFORunner::run() +prefix_ void senf::scheduler::detail::FIFORunner::run() { // This algorithm is carefully adjusted to make it work even when arbitrary tasks are removed // from the queue @@ -116,51 +118,74 @@ prefix_ void senf::scheduler::FIFORunner::run() // - We keep the next to-be-processed node in a class variable which is checked and updated // whenever a node is removed. NullTask null; + struct itimerspec timer; + timer.it_interval.tv_sec = watchdogMs_ / 1000; + timer.it_interval.tv_nsec = (watchdogMs_ % 1000) * 1000000ul; + timer.it_value.tv_sec = timer.it_interval.tv_sec; + timer.it_value.tv_nsec = timer.it_interval.tv_nsec; tasks_.push_back(null); TaskList::iterator end (TaskList::current(null)); next_ = tasks_.begin(); - struct itimerspec timer; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_nsec = 0; - timer.it_value.tv_sec = 1; - timer.it_value.tv_nsec = 0; - while (next_ != end) { - TaskInfo & task (*next_); - if (task.runnable) { - task.runnable = false; - if (timer_settime(watchdogId_, 0, &timer, 0) < 0) - SENF_THROW_SYSTEM_EXCEPTION("timer_settime()"); - runningName_ = task.name; -# ifdef SENF_DEBUG - runningBacktrace_ = task.backtrace; -# endif - TaskList::iterator i (next_); - ++ next_; - tasks_.splice(tasks_.end(), tasks_, i); - task.run(); + try { + if (timer_settime(watchdogId_, 0, &timer, 0) < 0) + SENF_THROW_SYSTEM_EXCEPTION("timer_settime()"); + while (next_ != end) { + TaskInfo & task (*next_); + if (task.runnable_) { + task.runnable_ = false; + runningName_ = task.name_; +# ifdef SENF_DEBUG + runningBacktrace_ = task.backtrace_; +# endif + TaskList::iterator i (next_); + ++ next_; + tasks_.splice(tasks_.end(), tasks_, i); + watchdogCount_ = 1; + task.run(); + } + else + ++ next_; } - else - ++ next_; } + catch (...) { + watchdogCount_ = 0; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_nsec = 0; + timer.it_value.tv_sec = 0; + timer.it_value.tv_nsec = 0; + timer_settime(watchdogId_, 0, &timer, 0); + tasks_.erase(end); + next_ = tasks_.end(); + throw; + } + watchdogCount_ = 0; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_nsec = 0; timer.it_value.tv_sec = 0; + timer.it_value.tv_nsec = 0; if (timer_settime(watchdogId_, 0, &timer, 0) < 0) SENF_THROW_SYSTEM_EXCEPTION("timer_settime()"); tasks_.erase(end); next_ = tasks_.end(); } -prefix_ void senf::scheduler::FIFORunner::watchdog(int, siginfo_t * si, void *) +prefix_ void senf::scheduler::detail::FIFORunner::watchdog(int, siginfo_t * si, void *) { FIFORunner & runner (*static_cast(si->si_value.sival_ptr)); - ++ runner.hangCount_; - write(1, "\n\n*** Scheduler task hanging: ", 30); - write(1, runner.runningName_.c_str(), runner.runningName_.size()); - write(1, "\n", 1); + if (runner.watchdogCount_ > 0) { + ++ runner.watchdogCount_; + if (runner.watchdogCount_ > 2) { + ++ runner.hangCount_; + write(1, "\n\n*** Scheduler task hanging: ", 30); + write(1, runner.runningName_.c_str(), runner.runningName_.size()); + write(1, "\n", 1); #ifdef SENF_DEBUG - write(1, "Task was initialized at\n", 24); - write(1, runner.runningBacktrace_.c_str(), runner.runningBacktrace_.size()); + write(1, "Task was initialized at\n", 24); + write(1, runner.runningBacktrace_.c_str(), runner.runningBacktrace_.size()); #endif - write(1, "\n", 1); + write(1, "\n", 1); + } + } } ///////////////////////////////cc.e////////////////////////////////////////