24 #include "ppl-config.h"
27 #if PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
36 #ifdef PPL_TIME_WITH_SYS_TIME
37 # include <sys/time.h>
40 # ifdef PPL_HAVE_SYS_TIME_H
41 # include <sys/time.h>
51 #if defined(__CYGWIN__) || defined(__gnu_hurd__) || defined(PPL_PROFILING)
52 #define THE_TIMER ITIMER_REAL
53 #define THE_SIGNAL SIGALRM
55 #define THE_TIMER ITIMER_PROF
56 #define THE_SIGNAL SIGPROF
65 itimerval PPL::Watchdog::current_timer_status;
68 itimerval PPL::Watchdog::signal_once;
71 PPL::Implementation::Watchdog::Time PPL::Watchdog::last_time_requested;
74 PPL::Implementation::Watchdog::Time PPL::Watchdog::time_so_far;
77 PPL::Watchdog::WD_Pending_List PPL::Watchdog::pending;
80 volatile bool PPL::Watchdog::alarm_clock_running =
false;
83 volatile bool PPL::Watchdog::in_critical_section =
false;
88 throw_syscall_error(
const char* syscall_name) {
89 throw std::runtime_error(std::string(syscall_name) +
": " + strerror(errno));
93 my_getitimer(
int which,
struct itimerval*
value) {
94 if (getitimer(which, value) != 0) {
95 throw_syscall_error(
"getitimer");
100 my_setitimer(
int which,
101 const struct itimerval* value,
struct itimerval* old_value) {
102 if (setitimer(which, value, old_value) != 0) {
103 throw_syscall_error(
"setitimer");
108 my_sigaction(
int signum,
109 const struct sigaction* act,
struct sigaction* old_action) {
110 if (sigaction(signum, act, old_action) != 0) {
111 throw_syscall_error(
"sigaction");
118 PPL::Watchdog::get_timer(Implementation::Watchdog::Time& time) {
119 using namespace Implementation::Watchdog;
120 my_getitimer(THE_TIMER, ¤t_timer_status);
121 time = Time(current_timer_status.it_value.tv_sec,
122 current_timer_status.it_value.tv_usec);
126 PPL::Watchdog::set_timer(
const Implementation::Watchdog::Time& time) {
127 if (time.seconds() == 0 && time.microseconds() == 0) {
128 throw std::runtime_error(
"PPL internal error");
130 last_time_requested = time;
131 signal_once.it_value.tv_sec = time.seconds();
132 signal_once.it_value.tv_usec = time.microseconds();
133 my_setitimer(THE_TIMER, &signal_once, 0);
137 PPL::Watchdog::stop_timer() {
138 signal_once.it_value.tv_sec = 0;
139 signal_once.it_value.tv_usec = 0;
140 my_setitimer(THE_TIMER, &signal_once, 0);
144 PPL::Watchdog::handle_timeout(
int) {
145 if (in_critical_section) {
149 time_so_far += last_time_requested;
150 if (!pending.empty()) {
151 WD_Pending_List::iterator i = pending.begin();
154 i->expired_flag() =
true;
155 i = pending.erase(i);
156 }
while (i != pending.end() && i->deadline() <= time_so_far);
157 if (pending.empty()) {
158 alarm_clock_running =
false;
161 set_timer((*pending.begin()).deadline() - time_so_far);
165 alarm_clock_running =
false;
172 PPL::Watchdog::handle_timeout(signum);
175 PPL::Watchdog::WD_Pending_List::iterator
176 PPL::Watchdog::new_watchdog_event(
long csecs,
177 const WD_Handler& handler,
178 bool& expired_flag) {
179 using namespace Implementation::Watchdog;
181 WD_Pending_List::iterator position;
182 const Time deadline(csecs);
183 if (!alarm_clock_running) {
184 position = pending.insert(deadline, handler, expired_flag);
185 time_so_far = Time(0);
187 alarm_clock_running =
true;
191 get_timer(time_to_shoot);
192 Time elapsed_time(last_time_requested);
193 elapsed_time -= time_to_shoot;
194 Time current_time(time_so_far);
195 current_time += elapsed_time;
196 Time real_deadline(deadline);
197 real_deadline += current_time;
198 position = pending.insert(real_deadline, handler, expired_flag);
199 if (deadline < time_to_shoot) {
200 time_so_far = current_time;
208 PPL::Watchdog::remove_watchdog_event(WD_Pending_List::iterator position) {
209 using namespace Implementation::Watchdog;
210 assert(!pending.empty());
211 if (position == pending.begin()) {
212 WD_Pending_List::iterator next = position;
214 if (next != pending.end()) {
215 const Time first_deadline(position->deadline());
216 Time next_deadline(next->deadline());
217 if (first_deadline != next_deadline) {
219 get_timer(time_to_shoot);
220 Time elapsed_time(last_time_requested);
221 elapsed_time -= time_to_shoot;
222 time_so_far += elapsed_time;
223 next_deadline -= first_deadline;
224 time_to_shoot += next_deadline;
225 set_timer(time_to_shoot);
230 alarm_clock_running =
false;
233 pending.erase(position);
236 PPL::Implementation::Watchdog::Time PPL::Watchdog::reschedule_time(1);
240 signal_once.it_interval.tv_sec = 0;
241 signal_once.it_interval.tv_usec = 0;
251 my_sigaction(THE_SIGNAL, &s, 0);
258 #endif // PPL_HAVE_DECL_SETITIMER && PPL_HAVE_DECL_SIGACTION
void finalize()
Finalizes the library.
void initialize()
Initializes the library.
The entire library is confined to this namespace.
void PPL_handle_timeout(int signum)