fixed 64bit issue: replace unsigned with ::intptr_t
[senf.git] / Scheduler / FIFORunner.cc
index a6fb824..6ddd914 100644 (file)
@@ -33,6 +33,9 @@
 #include "../Utils/Exception.hh"
 #include "../Utils/senfassert.hh"
 #include "../Utils/ScopeExit.hh"
+#include <execinfo.h>
+#include "../config.hh"
+#include <stdint.h>
 
 //#include "FIFORunner.mpp"
 #define prefix_
@@ -40,7 +43,7 @@
 
 prefix_ senf::scheduler::detail::FIFORunner::FIFORunner()
     : tasks_ (), next_ (tasks_.end()), watchdogRunning_ (false), watchdogMs_ (1000), 
-      watchdogAbort_ (false), watchdogCount_(0), hangCount_ (0)
+      watchdogAbort_ (false), watchdogCount_(0), hangCount_ (0), yield_ (false)
 {
     struct sigevent ev;
     ::memset(&ev, 0, sizeof(ev));
@@ -89,6 +92,8 @@ prefix_ void senf::scheduler::detail::FIFORunner::startWatchdog()
 
         watchdogRunning_ = true;
     }
+    else
+        stopWatchdog();
 }
 
 prefix_ void senf::scheduler::detail::FIFORunner::stopWatchdog()
@@ -134,17 +139,32 @@ prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task)
 
 prefix_ void senf::scheduler::detail::FIFORunner::run()
 {
-    TaskList::iterator f (tasks_.begin());
-    TaskList::iterator l (TaskList::current(highPriorityEnd_));
-    run(f, l);
+    for(;;) {
+        TaskList::iterator f (tasks_.begin());
+        TaskList::iterator l (TaskList::current(highPriorityEnd_));
+        run(f, l);
+        if (yield_) {
+            yield_ = false;
+            continue;
+        }
 
-    f = l; ++f;
-    l = TaskList::current(normalPriorityEnd_);
-    run(f, l);
-        
-    f = l; ++f;
-    l = tasks_.end();
-    run(f, l);
+        f = l; ++f;
+        l = TaskList::current(normalPriorityEnd_);
+        run(f, l); 
+        if (yield_) {
+            yield_ = false;
+            continue;
+        }
+       
+        f = l; ++f;
+        l = tasks_.end();
+        run(f, l);
+        if (yield_) {
+            yield_ = false;
+            continue;
+        }
+        break;
+    }
 }
 
 prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, TaskList::iterator l)
@@ -172,7 +192,7 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task
     ScopeExit atExit ((
                           var(watchdogCount_) = 0, 
                           var(next_) = l
-                          ));
+                     ));
     
     while (next_ != end) {
         TaskInfo & task (*next_);
@@ -186,7 +206,10 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task
             ++ next_;
             tasks_.splice(l, tasks_, i);
             watchdogCount_ = 1;
+            yield_ = false;
             task.run();
+            if (yield_)
+                return;
         }
         else
             ++ next_;
@@ -214,20 +237,41 @@ prefix_ void senf::scheduler::detail::FIFORunner::watchdog(int, siginfo_t * si,
         ++ 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());
-#endif
-            write(1, "\n", 1);
-            if (runner.watchdogAbort_)
-                assert(false);
+            runner.watchdogError();
         }
     }
 }
 
+prefix_ void senf::scheduler::detail::FIFORunner::watchdogError()
+{
+    static char const hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+                                'a', 'b', 'c', 'd', 'e', 'f' };
+    static void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS];
+    
+    write(1, "\n\n*** Scheduler task hanging: ", 30);
+    write(1, runningName_.c_str(), runningName_.size());
+    write(1, " at\n ", 3);
+
+    unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) );
+    for (unsigned i (0); i < nEntries; ++i) {
+        write(1, " 0x", 3);
+        for (unsigned j (sizeof(void*)); j > 0; --j) {
+             ::uintptr_t v( ::uintptr_t (entries[i])>>(8*(j-1)));
+            write(1, &(hex[ (v >> 4) & 0x0f ]), 1);
+            write(1, &(hex[ (v     ) & 0x0f ]), 1);
+        }
+    }
+    write(1, "\n", 1);
+        
+#ifdef SENF_DEBUG
+    write(1, "Task was initialized at\n", 24);
+    write(1, runningBacktrace_.c_str(), runningBacktrace_.size());
+#endif
+    write(1, "\n", 1);
+    if (watchdogAbort_)
+        assert(false);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "FIFORunner.mpp"