00001 // $Id: Scheduler.cc 1772 2011-03-10 12:45:21Z tho $ 00002 // 00003 // Copyright (C) 2006 00004 // Fraunhofer (FOKUS) 00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY 00006 // Stefan Bund <g0dil@berlios.de> 00007 // 00008 // This program is free software; you can redistribute it and/or modify 00009 // it under the terms of the GNU General Public License as published by 00010 // the Free Software Foundation; either version 2 of the License, or 00011 // (at your option) any later version. 00012 // 00013 // This program is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU General Public License 00019 // along with this program; if not, write to the 00020 // Free Software Foundation, Inc., 00021 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 00034 #include "Scheduler.hh" 00035 //#include "Scheduler.ih" 00036 00037 // Custom includes 00038 00039 #define prefix_ 00040 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00041 00042 namespace { 00043 bool terminate_ (false); 00044 bool running_ (false); 00045 } 00046 00047 prefix_ void senf::scheduler::terminate() 00048 { 00049 terminate_ = true; 00050 } 00051 00052 prefix_ void senf::scheduler::yield() 00053 { 00054 detail::FIFORunner::instance().yield(); 00055 } 00056 00057 prefix_ bool senf::scheduler::running() 00058 { 00059 return running_; 00060 } 00061 00062 prefix_ senf::ClockService::clock_type senf::scheduler::now() 00063 { 00064 return running() ? eventTime() : ClockService::now(); 00065 } 00066 00067 namespace { 00068 00069 // We don't want try { } catch(...) { ... throw; } since that will make debugging more 00070 // difficult: the stack backtrace for an unexpected exception would always end here. 00071 struct SchedulerScopedInit 00072 { 00073 SchedulerScopedInit() 00074 { 00075 senf::scheduler::detail::FIFORunner::instance().startWatchdog(); 00076 senf::scheduler::detail::SignalDispatcher::instance().unblockSignals(); 00077 senf::scheduler::detail::TimerDispatcher::instance().enable(); 00078 running_ = true; 00079 } 00080 00081 ~SchedulerScopedInit() 00082 { 00083 senf::scheduler::detail::TimerDispatcher::instance().disable(); 00084 senf::scheduler::detail::SignalDispatcher::instance().blockSignals(); 00085 senf::scheduler::detail::FIFORunner::instance().stopWatchdog(); 00086 running_ = false; 00087 } 00088 }; 00089 } 00090 00091 prefix_ void senf::scheduler::process() 00092 { 00093 SchedulerScopedInit initScheduler; 00094 terminate_ = false; 00095 detail::TimerDispatcher::instance().reschedule(); 00096 while(! terminate_ && ! (detail::FdDispatcher::instance().empty() && 00097 detail::TimerDispatcher::instance().empty() && 00098 detail::FileDispatcher::instance().empty() && 00099 detail::IdleEventDispatcher::instance().empty()) ) { 00100 detail::FdManager::instance().processOnce(); 00101 detail::FileDispatcher::instance().prepareRun(); 00102 detail::EventHookDispatcher::instance().prepareRun(); 00103 detail::TimerDispatcher::instance().prepareRun(); 00104 detail::IdleEventDispatcher::instance().prepareRun(); 00105 detail::FIFORunner::instance().run(); 00106 detail::TimerDispatcher::instance().reschedule(); 00107 } 00108 } 00109 00110 prefix_ void senf::scheduler::restart() 00111 { 00112 detail::FdManager* fdm (&detail::FdManager::instance()); 00113 detail::FIFORunner* ffr (&detail::FIFORunner::instance()); 00114 detail::FdDispatcher* fdd (&detail::FdDispatcher::instance()); 00115 detail::TimerDispatcher* tdd (&detail::TimerDispatcher::instance()); 00116 detail::SignalDispatcher* sdd (&detail::SignalDispatcher::instance()); 00117 detail::FileDispatcher* fld (&detail::FileDispatcher::instance()); 00118 detail::IdleEventDispatcher* ied (&detail::IdleEventDispatcher::instance()); 00119 detail::EventHookDispatcher* eed (&detail::EventHookDispatcher::instance()); 00120 00121 eed->~EventHookDispatcher(); 00122 ied->~IdleEventDispatcher(); 00123 fld->~FileDispatcher(); 00124 sdd->~SignalDispatcher(); 00125 tdd->~TimerDispatcher(); 00126 fdd->~FdDispatcher(); 00127 ffr->~FIFORunner(); 00128 fdm->~FdManager(); 00129 00130 new (fdm) detail::FdManager(); 00131 new (ffr) detail::FIFORunner(); 00132 new (fdd) detail::FdDispatcher(); 00133 new (tdd) detail::TimerDispatcher(); 00134 new (sdd) detail::SignalDispatcher(); 00135 new (fld) detail::FileDispatcher(); 00136 new (ied) detail::IdleEventDispatcher(); 00137 new (eed) detail::EventHookDispatcher(); 00138 } 00139 00140 prefix_ bool senf::scheduler::empty() 00141 { 00142 return detail::FdDispatcher::instance().empty() 00143 && detail::TimerDispatcher::instance().empty() 00144 && detail::FileDispatcher::instance().empty() 00145 && detail::SignalDispatcher::instance().empty() 00146 && detail::IdleEventDispatcher::instance().empty() 00147 && detail::EventHookDispatcher::instance().empty(); 00148 } 00149 00150 prefix_ void senf::scheduler::hiresTimers() 00151 { 00152 #ifdef HAVE_TIMERFD_CREATE 00153 if (haveScalableHiresTimers()) 00154 detail::TimerDispatcher::instance().timerSource( 00155 std::auto_ptr<detail::TimerSource>(new detail::TimerFDTimerSource())); 00156 else 00157 #endif 00158 detail::TimerDispatcher::instance().timerSource( 00159 std::auto_ptr<detail::TimerSource>(new detail::POSIXTimerSource())); 00160 } 00161 00162 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00163 // senf::schedulerLogTimeSource 00164 00165 prefix_ senf::log::time_type senf::scheduler::LogTimeSource::operator()() 00166 const 00167 { 00168 return scheduler::now(); 00169 } 00170 00171 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00172 // senf::scheduler::BlockSignals 00173 00174 prefix_ senf::scheduler::BlockSignals::BlockSignals(bool initiallyBlocked) 00175 : blocked_ (false) 00176 { 00177 ::sigfillset(&allSigs_); 00178 if (initiallyBlocked) 00179 block(); 00180 } 00181 00182 prefix_ void senf::scheduler::BlockSignals::block() 00183 { 00184 if (blocked_) 00185 return; 00186 ::sigprocmask(SIG_BLOCK, &allSigs_, &savedSigs_); 00187 blocked_ = true; 00188 } 00189 00190 prefix_ void senf::scheduler::BlockSignals::unblock() 00191 { 00192 if (!blocked_) 00193 return; 00194 ::sigprocmask(SIG_SETMASK, &savedSigs_, 0); 00195 blocked_ = false; 00196 } 00197 00198 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00199 #undef prefix_ 00200 00201 00202 // Local Variables: 00203 // mode: c++ 00204 // fill-column: 100 00205 // c-file-style: "senf" 00206 // indent-tabs-mode: nil 00207 // ispell-local-dictionary: "american" 00208 // compile-command: "scons -u test" 00209 // comment-column: 40 00210 // End: