Scheduler: Restructure signal blocking/unblocking
g0dil [Tue, 2 Dec 2008 09:59:33 +0000 (09:59 +0000)]
Scheduler: Optimize watchdog implementation
Socket: Change read-into-container implementation to skip unnecessary available() call
Add 'profile=1' compile option
Exclude 'boost' and 'std' symbols from documentation

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@993 270642c3-0616-0410-b53a-bc976706d245

13 files changed:
PPI/SocketSink.hh
Packets/DefaultBundle/ICMPv6TypePacket.cc
Packets/ListParser.ih
Packets/PacketImpl.cc
Scheduler/Console/Server.ih
Scheduler/FIFORunner.cc
Scheduler/FIFORunner.cci
Scheduler/FIFORunner.hh
Scheduler/Scheduler.cc
Socket/ClientSocketHandle.ct
doclib/Doxyfile.global
senfscons/SENFSCons.py
senfscons/senfutil.py

index 985befd..65926d7 100644 (file)
@@ -91,7 +91,7 @@ namespace ppi {
         senf::INet4Address source_;
         senf::INet4Address destination_;
         unsigned int protocolId_;
-};
+    };
 
     class IPv6SourceForcingDgramWriter : ConnectedDgramWriter
     {
index f0c434b..6e5d9d8 100644 (file)
@@ -27,6 +27,8 @@
 #include "ICMPv6Packet.hh"
 #include "ICMPv6TypePacket.hh"
 
+#ifndef DOXYGEN
+
 namespace {
 //Implementing the ICMPv6 Type registry
     senf::PacketRegistry<senf::ICMPTypes>::RegistrationProxy<senf::ICMPV6ErrDestUnreachable>
@@ -46,3 +48,5 @@ namespace {
     senf::PacketRegistry<senf::ICMPTypes>::RegistrationProxy<senf::MLDv2ListenerReport>
         registerMLDv2ListenerReport (143);
 }
+
+#endif
index 0be4b02..bf60983 100644 (file)
@@ -44,7 +44,9 @@ namespace detail {
                                          typename Container::value_type,
                                          boost::forward_traversal_tag,
                                          typename Container::value_type >,
+#ifndef DOXYGEN
           private Container::policy::iterator_data
+#endif
     {
     public:
         typedef typename Container::value_type value_type;
index 95b45cd..f6d06ae 100644 (file)
@@ -52,7 +52,7 @@ prefix_ senf::detail::PacketImpl::~PacketImpl()
 }
 
 // This function has a problem being inlined. Somehow, often when calling this, the size of the 
-// resulting inlined code would be huge. Need to further debug this.
+// resulting inlined code would be huge. Need to further debug this. (Disabled inliningfor now)
 
 prefix_ void senf::detail::PacketImpl::release(refcount_t n)
 {
index 9db9d4c..a886bb6 100644 (file)
@@ -71,9 +71,9 @@ namespace detail {
     {
     public:
         typedef ClientSocketHandle< 
-            MakeSocketPolicy<StreamFramingPolicy,
-                             WriteablePolicy,
-                             ConnectedCommunicationPolicy>::policy > Handle;
+            senf::MakeSocketPolicy<StreamFramingPolicy,
+                                   WriteablePolicy,
+                                   ConnectedCommunicationPolicy>::policy > Handle;
 
         NonblockingSocketSink(Client & client);
         std::streamsize write(const char * s, std::streamsize n);
index 446859c..545b4ae 100644 (file)
@@ -37,7 +37,8 @@
 ///////////////////////////////cc.p////////////////////////////////////////
 
 prefix_ senf::scheduler::detail::FIFORunner::FIFORunner()
-    : tasks_ (), next_ (tasks_.end()), watchdogMs_ (1000), watchdogCount_(0), hangCount_ (0)
+    : tasks_ (), next_ (tasks_.end()), watchdogRunning_ (false), watchdogMs_ (1000), 
+      watchdogCount_(0), hangCount_ (0)
 {
     struct sigevent ev;
     ::memset(&ev, 0, sizeof(ev));
@@ -70,6 +71,33 @@ prefix_ senf::scheduler::detail::FIFORunner::~FIFORunner()
     signal(SIGURG, SIG_DFL);
 }
 
+prefix_ void senf::scheduler::detail::FIFORunner::startWatchdog()
+{
+    struct itimerspec timer;
+    ::memset(&timer, 0, sizeof(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;
+
+    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
+
+    watchdogRunning_ = true;
+}
+
+prefix_ void senf::scheduler::detail::FIFORunner::stopWatchdog()
+{
+    struct itimerspec timer;
+    ::memset(&timer, 0, sizeof(timer));
+
+    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
+
+    watchdogRunning_ = false;
+}
+
 // At the moment, the FIFORunner is not very efficient with many non-runnable tasks since the
 // complete list of tasks is traversed on each run().
 //
@@ -102,40 +130,17 @@ prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task)
 
 prefix_ void senf::scheduler::detail::FIFORunner::run()
 {
-    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;
-
-    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
-
-    timer.it_interval.tv_sec = 0;
-    timer.it_interval.tv_nsec = 0;
-    timer.it_value.tv_sec = 0;
-    timer.it_value.tv_nsec = 0;
-    
-    try {
-        TaskList::iterator f (tasks_.begin());
-        TaskList::iterator l (TaskList::current(highPriorityEnd_));
-        run(f, l);
+    TaskList::iterator f (tasks_.begin());
+    TaskList::iterator l (TaskList::current(highPriorityEnd_));
+    run(f, l);
 
-        f = l; ++f;
-        l = TaskList::current(normalPriorityEnd_);
-        run(f, l);
+    f = l; ++f;
+    l = TaskList::current(normalPriorityEnd_);
+    run(f, l);
         
-        f = l; ++f;
-        l = tasks_.end();
-        run(f, l);
-    }
-    catch(...) {
-        timer_settime(watchdogId_, 0, &timer, 0);
-        throw;
-    }
-
-    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
+    f = l; ++f;
+    l = tasks_.end();
+    run(f, l);
 }
 
 
index b2f6fe6..d363dac 100644 (file)
@@ -113,6 +113,8 @@ prefix_ void senf::scheduler::detail::FIFORunner::enqueue(TaskInfo * task)
 prefix_ void senf::scheduler::detail::FIFORunner::taskTimeout(unsigned ms)
 {
     watchdogMs_ = ms;
+    if (watchdogRunning_)
+        startWatchdog();
 }
 
 prefix_ unsigned senf::scheduler::detail::FIFORunner::taskTimeout()
index 11ab3ee..27b626f 100644 (file)
@@ -100,6 +100,9 @@ namespace detail {
         void taskTimeout(unsigned ms);
         unsigned taskTimeout() const;
 
+        void startWatchdog();
+        void stopWatchdog();
+
         unsigned hangCount() const;
 
         iterator begin() const;
@@ -132,6 +135,7 @@ namespace detail {
         NullTask highPriorityEnd_;
         
         timer_t watchdogId_;
+        bool watchdogRunning_;
         unsigned watchdogMs_;
         std::string runningName_;
 #   ifdef SENF_DEBUG
index 7d86523..e7550bb 100644 (file)
@@ -50,19 +50,29 @@ prefix_ void senf::scheduler::terminate()
 
 prefix_ void senf::scheduler::process()
 {
-    terminate_ = false;
-    while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
-                             detail::TimerDispatcher::instance().empty() &&
-                             detail::FileDispatcher::instance().empty())) {
+    try {
+        detail::FIFORunner::instance().startWatchdog();
         detail::SignalDispatcher::instance().unblockSignals();
         detail::TimerDispatcher::instance().unblockSignals();
-        detail::FdManager::instance().processOnce();
+        terminate_ = false;
+        while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
+                                 detail::TimerDispatcher::instance().empty() &&
+                                 detail::FileDispatcher::instance().empty())) {
+            detail::FdManager::instance().processOnce();
+            detail::FileDispatcher::instance().prepareRun();
+            detail::EventHookDispatcher::instance().prepareRun();
+            detail::FIFORunner::instance().run();
+        }
+    }
+    catch(...) {
         detail::TimerDispatcher::instance().blockSignals();
         detail::SignalDispatcher::instance().blockSignals();
-        detail::FileDispatcher::instance().prepareRun();
-        detail::EventHookDispatcher::instance().prepareRun();
-        detail::FIFORunner::instance().run();
+        detail::FIFORunner::instance().stopWatchdog();
+        throw;
     }
+    detail::TimerDispatcher::instance().blockSignals();
+    detail::SignalDispatcher::instance().blockSignals();
+    detail::FIFORunner::instance().stopWatchdog();
 }
 
 prefix_ void senf::scheduler::restart()
@@ -73,7 +83,7 @@ prefix_ void senf::scheduler::restart()
     detail::TimerDispatcher*      tdd (&detail::TimerDispatcher::instance());
     detail::SignalDispatcher*     sdd (&detail::SignalDispatcher::instance());
     detail::FileDispatcher*       fld (&detail::FileDispatcher::instance());
-    detail::EventHookDispatcher* eed (&detail::EventHookDispatcher::instance());
+    detail::EventHookDispatcher*  eed (&detail::EventHookDispatcher::instance());
 
     eed->~EventHookDispatcher();
     fld->~FileDispatcher();
index 376ad68..c6fa8fd 100644 (file)
@@ -106,10 +106,9 @@ template <class SPolicy>
 template <class Sequence>
 prefix_ void senf::ClientSocketHandle<SPolicy>::read(Sequence & container, unsigned limit)
 {
-    unsigned nread (available());
-    if (limit>0 && nread>limit)
-        nread = limit;
-    container.resize(nread);
+    if (limit == 0) 
+        limit = available();
+    container.resize(limit);
     container.erase(read( std::make_pair(container.begin(), container.end()) ), 
                     container.end());
 }
index 9603551..8224df8 100644 (file)
@@ -582,7 +582,7 @@ EXCLUDE_PATTERNS       = *.test.cc \
 # wildcard * is used, a substring. Examples: ANamespace, AClass, 
 # AClass::ANamespace, ANamespace::*Test
 
-##EXCLUDE_SYMBOLS        = 
+EXCLUDE_SYMBOLS        = boost std
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or 
 # directories that contain example code fragments that are included (see 
index 90a04ff..d8d287c 100644 (file)
@@ -73,6 +73,7 @@ def InitOpts():
     opts.Add('EXTRA_LIBS', 'Additional libraries to link against', '')
     opts.Add(SCons.Options.BoolOption('final','Enable optimization',0))
     opts.Add(SCons.Options.BoolOption('debug','Enable debug symbols in binaries',0))
+    opts.Add(SCons.Options.BoolOption('profile','Enable profiling',0))
     opts.Add('PREFIX', 'Installation prefix', '/usr/local')
     opts.Add('LIBINSTALLDIR', 'Library install dir', '$PREFIX/lib')
     opts.Add('BININSTALLDIR', 'Executable install dir', '$PREFIX/bin')
@@ -264,12 +265,18 @@ def MakeEnvironment():
 
     if env['final']:
         env.Append(CXXFLAGS = [ '-O3' ])
+        if env['profile']:
+            env.Append(CXXFLAGS = [ '-g', '-pg' ],
+                       LINKFLAGS = [ '-g', '-pg' ])
     else:
         # The boost-regex library is not compiled with _GLIBCXX_DEBUG so this fails:
         #          CPPDEFINES = [ '_GLIBCXX_DEBUG' ],
         env.Append(CXXFLAGS = [ '-O0', '-g' ],
                    CPPDEFINES = { 'SENF_DEBUG': ''})
-        if env['debug']:
+        if env['profile']:
+            env.Append(CXXFLAGS = [ '-pg' ],
+                       LINKFLAGS = [ '-pg' ])
+        if env['debug'] or env['profile']:
             env.Append(LINKFLAGS = [ '-g', '-rdynamic' ])
         else:
             env.Append(LINKFLAGS = [ '-Wl,-S', '-rdynamic' ])
index c704a1f..3d2a742 100644 (file)
@@ -12,8 +12,10 @@ def SetupForSENF(env):
                 BOOSTREGEXLIB  = 'boost_regex',
                 BOOSTIOSTREAMSLIB = 'boost_iostreams',
                 CXXFLAGS       = [ '-Wno-long-long',
-                                   '${"$CXXFLAGS_"+(final and "final" or "debug")}' ],
-                LINKFLAGS      = [ '${"$LINKFLAGS_"+(final and "final" or "debug")}' ],
+                                   '${"$CXXFLAGS_"+(final and "final" or "debug")}',
+                                   '${profile and ("-g","-pg") or None}' ],
+                LINKFLAGS      = [ '${"$LINKFLAGS_"+(final and "final" or "debug")}',
+                                   '${profile and "-pg" or None}' ],
                 SENF_BUILDOPTS = [ '-j%s' % (env.GetOption('num_jobs') or "1") ],
                 CXXFLAGS_debug  = [ '-O0', '-g', '-fno-inline' ],
                 LINKFLAGS_debug = [ '-g', '-rdynamic' ],
@@ -35,6 +37,8 @@ def SetupForSENF(env):
     opts.Add( 'LOGLEVELS', 'Special log levels. Syntax: <stream>|[<area>]|<level> ...',
               '${"$LOGLEVELS_"+(final and "final" or "debug")}' )
     opts.Add( BoolOption('final', 'Build final (optimized) build', False) )
+    opts.Add( BoolOption('debug', 'Link in debug symbols', False) )
+    opts.Add( BoolOption('profile', 'Add profile information', False) )
     opts.Update(env)
 
     if env.subst('$LOGLEVELS'):
@@ -49,7 +53,9 @@ def SetupForSENF(env):
         print "\nUsing SENF in './senf'\n"
         env.Append( LIBPATH = [ 'senf' ],
                     CPPPATH = [ 'senf/include' ],
-                    SENF_BUILDOPTS = [ '${final and "final=1" or None}' ],
+                    SENF_BUILDOPTS = [ '${final and "final=1" or None}',
+                                       '${debug and "debug=1" or None}',
+                                       '${profile and "profile=1" or None}' ],
                     CPPDEFINES = [ '${not(final) and "SENF_DEBUG" or None}' ] )
 
         env.Default(