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