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