00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <unistd.h>
00021 #include <errno.h>
00022 #include <sys/time.h>
00023 #include <sys/poll.h>
00024
00025 #include "Timer.h"
00026 #include "io/IO.h"
00027 #include "../util/InitSequencer.h"
00028
00029 namespace oasys {
00030
00031 template <> TimerSystem* Singleton<TimerSystem>::instance_ = 0;
00032
00033
00034 TimerSystem::TimerSystem()
00035 : Logger("TimerSystem", "/timer"),
00036 system_lock_(new SpinLock()),
00037 notifier_(logpath_),
00038 timers_()
00039 {
00040 memset(handlers_, 0, sizeof(handlers_));
00041 memset(signals_, 0, sizeof(signals_));
00042 sigfired_ = false;
00043 }
00044
00045
00046 TimerSystem::~TimerSystem()
00047 {
00048 while (! timers_.empty()) {
00049 Timer* t = timers_.top();
00050 t->pending_ = false;
00051 timers_.pop();
00052 delete t;
00053 }
00054 }
00055
00056
00057 void
00058 TimerSystem::schedule_at(struct timeval *when, Timer* timer)
00059 {
00060 ScopeLock l(system_lock_, "TimerSystem::schedule_at");
00061
00062 struct timeval now;
00063
00064 if (when == 0) {
00065
00066 log_debug("scheduling timer %p immediately", timer);
00067
00068 timer->when_.tv_sec = 0;
00069 timer->when_.tv_usec = 0;
00070 } else {
00071 ::gettimeofday(&now, 0);
00072 log_debug("scheduling timer %p in %ld ms at %u:%u",
00073 timer, TIMEVAL_DIFF_MSEC(*when, now),
00074 (u_int)when->tv_sec, (u_int)when->tv_usec);
00075
00076 timer->when_ = *when;
00077 }
00078
00079 if (timer->pending_) {
00080
00081
00082
00083
00084 PANIC("rescheduling timers not implemented");
00085 }
00086
00087 timer->pending_ = 1;
00088 timer->cancelled_ = 0;
00089 timers_.push(timer);
00090
00091 notifier_.signal();
00092 }
00093
00094
00095 void
00096 TimerSystem::schedule_in(int milliseconds, Timer* timer)
00097 {
00098 struct timeval when;
00099 ::gettimeofday(&when, 0);
00100 when.tv_sec += milliseconds / 1000;
00101 when.tv_usec += (milliseconds % 1000) * 1000;
00102 while (when.tv_usec > 1000000) {
00103 when.tv_sec += 1;
00104 when.tv_usec -= 1000000;
00105 }
00106
00107 return schedule_at(&when, timer);
00108 }
00109
00110
00111 void
00112 TimerSystem::schedule_immediate(Timer* timer)
00113 {
00114 return schedule_at(0, timer);
00115 }
00116
00117
00118 bool
00119 TimerSystem::cancel(Timer* timer)
00120 {
00121 ScopeLock l(system_lock_, "TimerSystem::cancel");
00122
00123
00124
00125
00126
00127 if (timer->pending_) {
00128 timer->cancelled_ = true;
00129 return true;
00130 }
00131
00132 return false;
00133 }
00134
00135
00136 void
00137 TimerSystem::post_signal(int sig)
00138 {
00139 TimerSystem* _this = TimerSystem::instance();
00140
00141 _this->sigfired_ = true;
00142 _this->signals_[sig] = true;
00143
00144 _this->notifier_.signal();
00145 }
00146
00147
00148 void
00149 TimerSystem::add_sighandler(int sig, sighandlerfn_t* handler)
00150 {
00151 log_debug("adding signal handler %p for signal %d", handler, sig);
00152 handlers_[sig] = handler;
00153 signal(sig, post_signal);
00154 }
00155
00156
00157 void
00158 TimerSystem::pop_timer(const struct timeval& now)
00159 {
00160 ASSERT(system_lock_->is_locked_by_me());
00161
00162 Timer* next_timer = timers_.top();
00163 timers_.pop();
00164
00165
00166 ASSERT(next_timer->pending_);
00167 next_timer->pending_ = 0;
00168
00169 int late = TIMEVAL_DIFF_MSEC(now, next_timer->when());
00170 if (late > 2000) {
00171 log_warn("timer thread running slow -- timer is %d msecs late", late);
00172 }
00173
00174 if (! next_timer->cancelled_) {
00175 log_debug("popping timer %p at %u.%u", next_timer,
00176 (u_int)now.tv_sec, (u_int)now.tv_usec);
00177 next_timer->timeout(now);
00178 } else {
00179 log_debug("popping cancelled timer %p at %u.%u", next_timer,
00180 (u_int)now.tv_sec, (u_int)now.tv_usec);
00181 next_timer->cancelled_ = 0;
00182
00183 if (next_timer->cancel_flags_ == Timer::DELETE_ON_CANCEL) {
00184 log_debug("deleting cancelled timer %p at %u.%u", next_timer,
00185 (u_int)now.tv_sec, (u_int)now.tv_usec);
00186 delete next_timer;
00187 }
00188 }
00189 }
00190
00191
00192 void
00193 TimerSystem::handle_signals()
00194 {
00195
00196
00197
00198 if (sigfired_) {
00199 sigfired_ = 0;
00200
00201 log_debug("sigfired_ set, calling registered handlers");
00202 for (int i = 0; i < NSIG; ++i) {
00203 if (signals_[i]) {
00204 handlers_[i](i);
00205 signals_[i] = 0;
00206 }
00207 }
00208 }
00209 }
00210
00211
00212 int
00213 TimerSystem::run_expired_timers()
00214 {
00215 ScopeLock l(system_lock_, "TimerSystem::run_expired_timers");
00216
00217 handle_signals();
00218
00219 struct timeval now;
00220 while (! timers_.empty())
00221 {
00222 if (::gettimeofday(&now, 0) != 0) {
00223 PANIC("gettimeofday");
00224 }
00225
00226 Timer* next_timer = timers_.top();
00227 if (TIMEVAL_LT(now, next_timer->when_)) {
00228 int diff_ms = TIMEVAL_DIFF_MSEC(next_timer->when_, now);
00229 ASSERT(diff_ms >= 0);
00230
00231
00232
00233
00234
00235 if (diff_ms != 0) {
00236 log_debug("new timeout %d", diff_ms);
00237 return diff_ms;
00238 } else {
00239 log_debug("sub-millisecond difference found, falling through");
00240 }
00241 }
00242 pop_timer(now);
00243 }
00244
00245 return -1;
00246 }
00247
00248
00249 void
00250 TimerThread::run()
00251 {
00252 TimerSystem* sys = TimerSystem::instance();
00253 while (true)
00254 {
00255 int timeout = sys->run_expired_timers();
00256 sys->notifier()->wait(NULL, timeout);
00257 }
00258
00259 NOTREACHED;
00260 }
00261
00262
00263 void
00264 TimerThread::init()
00265 {
00266 ASSERT(instance_ == NULL);
00267 instance_ = new TimerThread();
00268 instance_->start();
00269 }
00270
00271 TimerThread* TimerThread::instance_ = NULL;
00272
00273 }