00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00026 #ifndef QOLYESTER_SCH_SCHEDULER_HXX
00027 #define QOLYESTER_SCH_SCHEDULER_HXX 1
00028
00029 # include <unistd.h>
00030 # include <signal.h>
00031 # include <sys/times.h>
00032 # include <cassert>
00033 # include <cstring>
00034 # include <cerrno>
00035 # include "scheduler.hh"
00036 # include "utl/mark.hh"
00037 # include "utl/log.hh"
00038
00039 namespace olsr {
00040
00041 extern std::ostream dump_prof;
00042 extern debug_ostream_t debug;
00043 extern utl::Mark terminate_now;
00044 extern bool do_dump_prof;
00045 extern sched_t scheduler;
00046
00047 namespace sch {
00048
00049 bool
00050 LoopHandler::operator()() const {
00051 if (terminate_now.mark())
00052 return true;
00053 return false;
00054 }
00055
00056 # ifdef DEBUG
00057 Event::Event(const std::string& name)
00058 : name_(name)
00059 {}
00060 # else // !DEBUG
00061 Event::Event()
00062 {}
00063 # endif
00064
00065 template <class I>
00066 void
00067 PeriodicEvent_<I>::handle() {
00068 do
00069 increment_(next_, period_);
00070 while (next_.is_past());
00071 scheduler.insert(this);
00072 }
00073
00074 namespace internal {
00075
00076 template <class C, class A>
00077 void
00078 PollData::poll(std::multiset<IOEvent*, C, A>& s, int timeout) {
00079 typedef std::multiset<IOEvent*, C, A> set_t;
00080 ::pollfd ufds[s.size()];
00081 typename set_t::iterator ievs[s.size()];
00082
00083 unsigned counter = 0;
00084
00085 for (typename set_t::iterator i = s.begin();
00086 i != s.end(); ++i, ++counter) {
00087 ufds[counter] = (*i)->p().pfd;
00088 ufds[counter].revents = 0;
00089 ievs[counter] = i;
00090 }
00091
00092 int ret = ::poll(ufds, s.size(), timeout);
00093 assert(ret >= 0 || (ret < 0 && errno == EINTR));
00094
00095 if (ret > 0) {
00096 for (unsigned i = 0; i < counter; ++i) {
00097 assert(ufds[i].events == (*ievs[i])->p().pfd.events);
00098 if (ufds[i].events & ufds[i].revents) {
00099 IOEvent* e = *ievs[i];
00100 s.erase(ievs[i]);
00101 e->p().pfd = ufds[i];
00102 s.insert(e);
00103 }
00104 }
00105 }
00106 }
00107
00108
00109 void (*old_term_handler)(int) = SIG_IGN;
00110 void (*old_int_handler)(int) = SIG_IGN;
00111 void (*old_quit_handler)(int) = SIG_IGN;
00112
00113 void install_sighandlers()
00114 {
00115 # define GET_OLD_HANDLER(Signal, SmallSignal) \
00116 do { \
00117 struct sigaction sa; \
00118 int ret; \
00119 while ((ret = ::sigaction(Signal, NULL, &sa)) < 0 && \
00120 errno == EINTR); \
00121 assert(ret == 0); \
00122 old_ ## SmallSignal ## _handler = sa.sa_handler; \
00123 } while (0)
00124
00125 GET_OLD_HANDLER(SIGTERM, term);
00126 GET_OLD_HANDLER(SIGINT, int);
00127 GET_OLD_HANDLER(SIGQUIT, quit);
00128
00129 # define PUT_NEW_HANDLER(Signal, SmallSignal) \
00130 do { \
00131 if (old_ ## SmallSignal ## _handler != SIG_IGN) { \
00132 struct sigaction sa; \
00133 memset(&sa, 0, sizeof sa); \
00134 sa.sa_handler = SmallSignal ## _handler; \
00135 sigemptyset(&sa.sa_mask); \
00136 sa.sa_flags = SA_RESTART; \
00137 int ret; \
00138 while ((ret = ::sigaction(Signal, &sa, NULL)) < 0 && \
00139 errno == EINTR); \
00140 assert(ret == 0); \
00141 } \
00142 } while (0)
00143
00144 PUT_NEW_HANDLER(SIGTERM, term);
00145 PUT_NEW_HANDLER(SIGINT, int);
00146 PUT_NEW_HANDLER(SIGQUIT, quit);
00147
00148 {
00149 struct sigaction sa;
00150 memset(&sa, 0, sizeof sa);
00151 sa.sa_handler = SIG_IGN;
00152 sa.sa_flags = 0;
00153 int ret;
00154 while ((ret = ::sigaction(SIGPIPE, &sa, NULL)) < 0 &&
00155 errno == EINTR);
00156 assert(ret == 0);
00157 }
00158 }
00159
00160 }
00161
00162
00163
00164
00165 Scheduler::Scheduler(LoopHandler& lh)
00166 : loophandler_(lh),
00167 current_event_(0) {
00168 internal::install_sighandlers();
00169 }
00170
00171 Scheduler::~Scheduler() {
00172 while (!ioevent_set_.empty())
00173 destroy(*ioevent_set_.begin());
00174 while (!tevent_set_.empty())
00175 destroy(*tevent_set_.begin());
00176 }
00177
00178
00179
00180 void
00181 Scheduler::insert(TimedEvent* e) {
00182 tevent_set_.insert(e);
00183 debug << up << "Registering TimedEvent " << e->name() << " to "
00184 << e->next().diff() << std::endl;
00185 }
00186
00187 void
00188 Scheduler::erase(TimedEvent* e) {
00189 typedef teventset_t::iterator iter_t;
00190 std::pair<iter_t, iter_t> ep = tevent_set_.equal_range(e);
00191
00192 for (iter_t i = ep.first; i != ep.second;)
00193 if (*i == e) {
00194 debug << up << "Unregistering " << e->name() << " to "
00195 << e->next().diff() << std::endl;
00196 iter_t tmp = i++;
00197 tevent_set_.erase(tmp);
00198 } else
00199 ++i;
00200 }
00201
00202 template <class E>
00203 void
00204 Scheduler::destroy(E* e) {
00205 erase(e);
00206 if (current_event_ == e)
00207 delete_ = true;
00208 else
00209 delete e;
00210 }
00211
00212
00213
00214
00215
00216 void
00217 Scheduler::insert(IOEvent* e) {
00218 debug << up << "Registering IOEvent " << e->name() << std::endl;
00219 ioevent_set_.insert(e);
00220 }
00221
00222 void
00223 Scheduler::erase(IOEvent* e) {
00224 typedef ioeventset_t::iterator iter_t;
00225 std::pair<iter_t, iter_t> ep = ioevent_set_.equal_range(e);
00226
00227 for (iter_t i = ep.first; i != ep.second;)
00228 if (*i == e) {
00229 iter_t tmp = i++;
00230 debug << up << "Unregistering IOEvent " << e->name() << std::endl;
00231 ioevent_set_.erase(tmp);
00232 } else
00233 ++i;
00234 }
00235
00236
00237
00238 void
00239 Scheduler::handle_tevents() {
00240 # ifdef DEBUG
00241 debug << up(2) << "TimedEvents before {\n";
00242 for (teventset_t::iterator i = tevent_set_.begin();
00243 i != tevent_set_.end(); ++i)
00244 debug << " " << (*i)->name() << " " << (*i)->next().diff()
00245 << ((*i)->next().is_past() ? " A\n" : "\n");
00246 debug << "}" << std::endl;
00247 # endif // !DEBUG
00248
00249
00250 while (!tevent_set_.empty()) {
00251 TimedEvent* e = *tevent_set_.begin();
00252
00253 if (e->next() > timeval_t::now())
00254 break;
00255
00256 current_event_ = e;
00257 tevent_set_.erase(tevent_set_.begin());
00258
00259 delete_ = false;
00260 debug << up << "Handling TimedEvent " << e->name() << " with "
00261 << e->next().diff() << std::endl;
00262 e->handle();
00263 if (delete_)
00264 delete e;
00265 current_event_ = 0;
00266 }
00267
00268 # ifdef DEBUG
00269 debug << up(2) << "TimedEvents after {\n";
00270 for (teventset_t::iterator i = tevent_set_.begin();
00271 i != tevent_set_.end(); ++i)
00272 debug << " " << (*i)->name() << " " << (*i)->next().diff()
00273 << ((*i)->next().is_past() ? " A\n" : "\n");
00274 debug << "}" << std::endl;
00275 # endif // !DEBUG
00276 }
00277
00278
00279 void
00280 Scheduler::handle_ioevents() {
00281
00282 # ifdef DEBUG
00283 debug << up(2) << "IOEvents before {\n";
00284 for (ioeventset_t::iterator i = ioevent_set_.begin();
00285 i != ioevent_set_.end(); ++i)
00286 debug << " " << (*i)->name()
00287 << ((*i)->p().active() ? " A\n" : "\n");
00288 debug << "}" << std::endl;
00289 # endif // !DEBUG
00290
00291 while (!ioevent_set_.empty()) {
00292 IOEvent* e = *ioevent_set_.begin();
00293
00294 if (!e->p().active())
00295 break;
00296
00297 current_event_ = e;
00298 ioevent_set_.erase(ioevent_set_.begin());
00299
00300 delete_ = false;
00301 debug << up << "Handling IOEvent " << e->name() << std::endl;
00302 e->handle();
00303 if (delete_)
00304 delete e;
00305 current_event_ = 0;
00306 }
00307
00308 # ifdef DEBUG
00309 debug << up(2) << "IOEvents after {\n";
00310 for (ioeventset_t::iterator i = ioevent_set_.begin();
00311 i != ioevent_set_.end(); ++i)
00312 debug << " " << (*i)->name()
00313 << ((*i)->p().active() ? " A\n" : "\n");
00314 debug << "}" << std::endl;
00315 # endif // !DEBUG
00316
00317 }
00318
00319
00320 void
00321 Scheduler::loop() {
00322
00323
00324
00325
00326 while (true) {
00327
00328
00329 ::tms t;
00330 if (do_dump_prof)
00331 ::times(&t);
00332
00333 if (tevent_set_.empty())
00334 IOEvent::p_t::poll(ioevent_set_);
00335 else if ((*tevent_set_.begin())->next().is_past())
00336 IOEvent::p_t::poll(ioevent_set_, 0);
00337 else
00338 IOEvent::p_t::poll(ioevent_set_, ((*tevent_set_.begin())->next() -
00339 timeval_t::now()).poll_time());
00340
00341
00342 timeval_t::set_now();
00343
00344 handle_ioevents();
00345 handle_tevents();
00346
00347 if (loophandler_())
00348 break;
00349
00350
00351 if (do_dump_prof) {
00352 ::tms nt;
00353 ::times(&nt);
00354
00355 dump_prof << "Seconds spent computing: ";
00356 dump_prof.precision(3);
00357 dump_prof.flags(std::ios::fixed);
00358 if (nt.tms_utime >= t.tms_utime)
00359 dump_prof << (float) (nt.tms_utime - t.tms_utime) /
00360 sysconf(_SC_CLK_TCK)
00361 << std::endl;
00362 else
00363 dump_prof << (float) (LONG_MAX - nt.tms_utime + t.tms_utime) /
00364 sysconf(_SC_CLK_TCK)
00365 << std::endl;
00366 }
00367 }
00368
00369 }
00370
00371
00372 void term_handler(int)
00373 {
00374 terminate_now.set_mark();
00375 }
00376
00377 void int_handler(int)
00378 {
00379 terminate_now.set_mark();
00380 }
00381
00382 void quit_handler(int)
00383 {
00384 ::signal(SIGQUIT, SIG_DFL);
00385 ::raise(SIGQUIT);
00386 }
00387
00388 }
00389
00390 }
00391
00392 #endif // ! QOLYESTER_SCH_SCHEDULER_HXX