00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #include "TimerSource.hh"
00027
00028
00029
00030 #include "IdleEvent.hh"
00031 #ifdef HAVE_TIMERFD_CREATE
00032 #include TIMERFD_H_PATH
00033 #endif
00034 #include "senf/Utils/IgnoreValue.hh"
00035
00036
00037 #define prefix_
00038
00039
00040
00041
00042
00043 prefix_ senf::scheduler::detail::TimerSource::~TimerSource()
00044 {}
00045
00046
00047
00048
00049 prefix_ senf::scheduler::detail::POSIXTimerSource::POSIXTimerSource()
00050 : timeoutEnabled_ (false), timeout_ (0), signalEnabled_ (false)
00051 {
00052 if (pipe(timerPipe_) < 0)
00053 SENF_THROW_SYSTEM_EXCEPTION("pipe()");
00054 FdManager::instance().set( timerPipe_[0], FdManager::EV_READ, this);
00055
00056 sigemptyset(&sigSet_);
00057 sigaddset(&sigSet_, SIGALRM);
00058 sigprocmask(SIG_BLOCK, &sigSet_, 0);
00059
00060 struct sigaction act;
00061 act.sa_sigaction = &sigHandler;
00062 act.sa_mask = sigSet_;
00063 act.sa_flags = SA_SIGINFO | SA_RESTART;
00064 if (sigaction(SIGALRM, &act, 0) < 0)
00065 SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
00066
00067 struct sigevent ev;
00068 ::memset(&ev, 0, sizeof(ev));
00069 ev.sigev_notify = SIGEV_SIGNAL;
00070 ev.sigev_signo = SIGALRM;
00071 ev.sigev_value.sival_ptr = this;
00072 if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
00073 SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
00074 }
00075
00076 prefix_ senf::scheduler::detail::POSIXTimerSource::~POSIXTimerSource()
00077 {
00078 timer_delete(timerId_);
00079 ::signal(SIGALRM, SIG_IGN);
00080 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
00081 FdManager::instance().remove(timerPipe_[0]);
00082 close(timerPipe_[0]);
00083 close(timerPipe_[1]);
00084 }
00085
00086 prefix_ void
00087 senf::scheduler::detail::POSIXTimerSource::timeout(ClockService::clock_type timeout)
00088 {
00089 if (! timeoutEnabled_ || timeout_ != timeout) {
00090 timeout_ = timeout;
00091 if (timeout_ <= 0)
00092 timeout_ = 1;
00093 timeoutEnabled_ = true;
00094 reschedule();
00095 }
00096 }
00097
00098 prefix_ void senf::scheduler::detail::POSIXTimerSource::notimeout()
00099 {
00100 if (timeoutEnabled_) {
00101 timeoutEnabled_ = false;
00102 reschedule();
00103 }
00104 }
00105
00106 prefix_ void senf::scheduler::detail::POSIXTimerSource::enable()
00107 {
00108 if (! signalEnabled_) {
00109 signalEnabled_ = true;
00110 sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
00111 }
00112 }
00113
00114 prefix_ void senf::scheduler::detail::POSIXTimerSource::disable()
00115 {
00116 if (signalEnabled_) {
00117 signalEnabled_ = false;
00118 sigprocmask(SIG_BLOCK, &sigSet_, 0);
00119 }
00120 }
00121
00122 prefix_ void senf::scheduler::detail::POSIXTimerSource::sigHandler(int,
00123 ::siginfo_t * siginfo,
00124 void *)
00125 {
00126 if (siginfo->si_value.sival_ptr == 0)
00127 return;
00128 static char data = '\xD0';
00129
00130 senf::IGNORE( write(static_cast<POSIXTimerSource*>(siginfo->si_value.sival_ptr)->timerPipe_[1],
00131 &data, sizeof(data)) );
00132 }
00133
00134 prefix_ void senf::scheduler::detail::POSIXTimerSource::signal(int events)
00135 {
00136 char data;
00137
00138
00139 senf::IGNORE( read(timerPipe_[0], &data, sizeof(data)) );
00140 timeoutEnabled_ = false;
00141 }
00142
00143 prefix_ void senf::scheduler::detail::POSIXTimerSource::reschedule()
00144 {
00145 struct itimerspec timer;
00146 memset(&timer, 0, sizeof(timer));
00147 if (timeoutEnabled_) {
00148 timer.it_value.tv_sec = ClockService::in_seconds(timeout_);
00149 timer.it_value.tv_nsec = ClockService::in_nanoseconds(
00150 timeout_ - ClockService::seconds(timer.it_value.tv_sec));
00151 }
00152 if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0)
00153 SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
00154 }
00155
00156
00157
00158
00159 prefix_ void senf::scheduler::detail::PollTimerSource::timeout(ClockService::clock_type timeout)
00160 {
00161 ClockService::clock_type now (ClockService::now());
00162 int delay (ClockService::in_milliseconds(timeout-now)+1);
00163 IdleEventDispatcher::instance().timeout(delay<0?0:delay);
00164 }
00165
00166 prefix_ void senf::scheduler::detail::PollTimerSource::notimeout()
00167 {
00168 IdleEventDispatcher::instance().timeout(-1);
00169 }
00170
00171 prefix_ void senf::scheduler::detail::PollTimerSource::enable()
00172 {}
00173
00174 prefix_ void senf::scheduler::detail::PollTimerSource::disable()
00175 {}
00176
00177
00178
00179
00180 #ifdef HAVE_TIMERFD_CREATE
00181 prefix_ senf::scheduler::detail::TimerFDTimerSource::TimerFDTimerSource()
00182 : timerfd_ (-1), timeoutEnabled_ (false), timeout_ (0)
00183 {
00184 timerfd_ = timerfd_create(CLOCK_MONOTONIC, 0);
00185 if (timerfd_ < 0)
00186 SENF_THROW_SYSTEM_EXCEPTION("timerfd_create()");
00187 FdManager::instance().set( timerfd_, FdManager::EV_READ, this);
00188 }
00189
00190 prefix_ senf::scheduler::detail::TimerFDTimerSource::~TimerFDTimerSource()
00191 {
00192 FdManager::instance().remove(timerfd_);
00193 close(timerfd_);
00194 }
00195
00196 prefix_ void
00197 senf::scheduler::detail::TimerFDTimerSource::timeout(ClockService::clock_type timeout)
00198 {
00199 if (!timeoutEnabled_ || timeout_ != timeout) {
00200 timeout_ = timeout;
00201 if (timeout_ <= 0)
00202 timeout_ = 1;
00203 timeoutEnabled_ = true;
00204 reschedule();
00205 }
00206 }
00207
00208 prefix_ void senf::scheduler::detail::TimerFDTimerSource::notimeout()
00209 {
00210 if (timeoutEnabled_) {
00211 timeoutEnabled_ = false;
00212 reschedule();
00213 }
00214 }
00215
00216 prefix_ void senf::scheduler::detail::TimerFDTimerSource::enable()
00217 {}
00218
00219 prefix_ void senf::scheduler::detail::TimerFDTimerSource::disable()
00220 {}
00221
00222 namespace {
00223
00224 struct TimerFdCheck
00225 {
00226 TimerFdCheck();
00227 bool timerFdOk;
00228 };
00229
00230 TimerFdCheck::TimerFdCheck()
00231 : timerFdOk (false)
00232 {
00233 int fd (timerfd_create(CLOCK_MONOTONIC, 0));
00234 if (fd == -1) {
00235 if (errno != EINVAL)
00236 SENF_THROW_SYSTEM_EXCEPTION("timerfd_create()");
00237 }
00238 else {
00239 timerFdOk = true;
00240 close(fd);
00241 }
00242 }
00243
00244 }
00245 prefix_ bool senf::scheduler::detail::TimerFDTimerSource::haveTimerFD()
00246 {
00247 static TimerFdCheck check;
00248 return check.timerFdOk;
00249 }
00250
00251 prefix_ void senf::scheduler::detail::TimerFDTimerSource::signal(int events)
00252 {
00253 uint64_t expirations (0);
00254
00255 senf::IGNORE( read(timerfd_, &expirations, sizeof(expirations)) );
00256 }
00257
00258 prefix_ void senf::scheduler::detail::TimerFDTimerSource::reschedule()
00259 {
00260 struct itimerspec timer;
00261 memset(&timer, 0, sizeof(timer));
00262 if (timeoutEnabled_) {
00263 timer.it_value.tv_sec = ClockService::in_seconds(timeout_);
00264 timer.it_value.tv_nsec = ClockService::in_nanoseconds(
00265 timeout_ - ClockService::seconds(timer.it_value.tv_sec));
00266 }
00267 if (timerfd_settime(timerfd_, TFD_TIMER_ABSTIME, &timer, 0)<0)
00268 SENF_THROW_SYSTEM_EXCEPTION("timerfd_settime()");
00269 }
00270 #endif
00271
00272
00273 #undef prefix_
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285