/[pearpc]/src/system/osapi/posix/systimer.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/system/osapi/posix/systimer.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 5889 byte(s)
import upstream CVS
1 /// @file systimer.cc
2 /// @author Kimball Thurston
3 ///
4
5 //
6 // Copyright (c) 2004 Kimball Thurston
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License version 2 as
10 // published by the Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21
22 #include <signal.h>
23 #include <time.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/time.h>
27
28 #include "system/systimer.h"
29 #include "tools/snprintf.h"
30
31 static const int kTimerSignal = SYSTIMER_SIGNAL;
32 #ifdef USE_POSIX_REALTIME_CLOCK
33 static void signal_handler(int signo, siginfo_t *extra, void *junk);
34 static const int kClockRT = CLOCK_PROCESS_CPUTIME_ID;
35 static const int kClock = CLOCK_REALTIME;
36 #elif USE_POSIX_SETITIMER
37 static void signal_handler(int signo);
38 static const int kClock = ITIMER_REAL;
39 struct sys_timer_struct;
40 static sys_timer_struct *gSingleTimer = NULL;
41 static const int kSignalFlags = 0;
42 #else
43 #error no timer support
44 #endif
45
46 struct sys_timer_struct
47 {
48 #ifdef USE_POSIX_REALTIME_CLOCK
49 struct sigevent event_info;
50 timer_t timer_id;
51 #endif
52 sys_timer_callback callback;
53 int clock;
54 uint64 timer_res;
55
56 sys_timer_struct(sys_timer_callback cb)
57 : callback(cb), clock(kClock), timer_res(0)
58 {
59 #ifdef USE_POSIX_REALTIME_CLOCK
60 memset(&event_info, 0, sizeof event_info);
61 timer_id = 0;
62
63 event_info.sigev_notify = SIGEV_SIGNAL;
64 event_info.sigev_signo = kTimerSignal;
65 event_info.sigev_value.sival_ptr = this;
66 #endif
67 }
68 };
69
70 #ifdef USE_POSIX_REALTIME_CLOCK
71 static void signal_handler(int signo, siginfo_t *extra, void *junk)
72 {
73 sys_timer_struct *timer = reinterpret_cast<sys_timer_struct *>(extra->si_value.sival_ptr);
74 timer->callback(reinterpret_cast<sys_timer>(timer));
75 }
76 #else
77 # ifdef USE_POSIX_SETITIMER
78 static void signal_handler(int signo)
79 {
80 if (gSingleTimer != NULL) {
81 gSingleTimer->callback(reinterpret_cast<sys_timer>(gSingleTimer));
82 }
83 }
84 # endif
85 #endif
86
87 bool sys_create_timer(sys_timer *t, sys_timer_callback cb_func)
88 {
89 *t = 0;
90
91 sys_timer_struct *newTimer = new sys_timer_struct(cb_func);
92
93 #ifdef USE_POSIX_REALTIME_CLOCK
94 int clocks[] = {kClockRT, kClock};
95
96 struct timespec clockRes;
97 bool foundTimer = false;
98
99 for (uint i=0; i < (sizeof clocks / sizeof clocks[0]); i++) {
100 if (clock_getres(clocks[i], &clockRes) == 0
101 && timer_create(clocks[i], &newTimer->event_info,
102 &newTimer->timer_id) == 0) {
103
104 newTimer->clock = clocks[i];
105 foundTimer = true;
106 break;
107 }
108 }
109
110 if (!foundTimer) {
111 perror("Timer create error");
112 delete newTimer;
113 return false;
114 }
115
116 newTimer->timer_res = (uint64)clockRes.tv_sec * 1000 * 1000 * 1000;
117 newTimer->timer_res += (uint64)clockRes.tv_nsec;
118 #else
119 # ifdef USE_POSIX_SETITIMER
120 if (gSingleTimer != NULL) {
121 ht_printf("There can only be one active sys timer at a time using\n"
122 "interval timers.\n");
123 delete newTimer;
124 return false;
125 }
126 newTimer->timer_res = 10 * 1000 * 1000;
127 # endif
128 #endif
129
130 struct sigaction act;
131
132 sigemptyset(&act.sa_mask);
133 #ifdef USE_POSIX_REALTIME_CLOCK
134 act.sa_sigaction = signal_handler;
135 act.sa_flags = SA_SIGINFO;
136 #else
137 # ifdef USE_POSIX_SETITIMER
138 act.sa_handler = signal_handler;
139 act.sa_flags = 0;
140 # endif
141 #endif
142
143 if (sigemptyset(&act.sa_mask) == -1) {
144 perror("Error calling sigemptyset");
145 return false;
146 }
147
148 if (sigaction(kTimerSignal, &act, 0) == -1) {
149 perror("Error calling sigaction");
150 return false;
151 }
152
153 *t = reinterpret_cast<sys_timer>(newTimer);
154 #ifdef USE_POSIX_SETITIMER
155 gSingleTimer = newTimer;
156 #endif
157
158 return true;
159 }
160
161 void sys_delete_timer(sys_timer t)
162 {
163 sys_timer_struct *timer = reinterpret_cast<sys_timer_struct *>(t);
164
165 #ifdef USE_POSIX_REALTIME_CLOCK
166 timer_delete(timer->timer_id);
167 #else
168 # ifdef USE_POSIX_SETITIMER
169 struct itimerval itime;
170
171 itime.it_value.tv_sec = 0;
172 itime.it_value.tv_usec = 0;
173 itime.it_interval.tv_sec = 0;
174 itime.it_interval.tv_usec = 0;
175
176 setitimer(timer->clock, &itime, NULL);
177 gSingleTimer = NULL;
178 # endif
179 #endif
180
181 delete timer;
182 }
183
184 void sys_set_timer(sys_timer t, time_t secs, long int nanosecs, bool periodic)
185 {
186 sys_timer_struct *timer = reinterpret_cast<sys_timer_struct *>(t);
187 #ifdef USE_POSIX_REALTIME_CLOCK
188 struct itimerspec itime;
189
190 itime.it_value.tv_sec = secs;
191 // FIXME: Do we need to have rounding based on timer resolution here?
192 itime.it_value.tv_nsec = nanosecs;// + (nanosecs % timer->timer_res);
193
194 if (periodic) {
195 itime.it_interval.tv_sec = secs;
196 itime.it_interval.tv_nsec = nanosecs;
197 } else {
198 itime.it_interval.tv_sec = 0;
199 itime.it_interval.tv_nsec = 0;
200 }
201
202 if (timer_settime(timer->timer_id, 0, &itime, NULL) < 0) {
203 perror(__FUNCTION__);
204 }
205
206 #else
207 # ifdef USE_POSIX_SETITIMER
208 struct itimerval itime;
209
210 itime.it_value.tv_sec = secs;
211 itime.it_value.tv_usec = (nanosecs + 500) / 1000;
212
213 if (periodic) {
214 itime.it_interval = itime.it_value;
215 } else {
216 itime.it_interval.tv_sec = 0;
217 itime.it_interval.tv_usec = 0;
218 }
219
220 setitimer(timer->clock, &itime, NULL);
221 # endif
222 #endif
223 }
224
225 uint64 sys_get_timer_resolution(sys_timer t)
226 {
227 sys_timer_struct *timer = reinterpret_cast<sys_timer_struct *>(t);
228 return timer->timer_res;
229 }
230
231 uint64 sys_get_hiresclk_ticks()
232 {
233 #if HAVE_GETTIMEOFDAY
234 struct timeval tv;
235 struct timezone tz;
236
237 gettimeofday(&tv, &tz);
238 //__asm__ __volatile__("rdtsc" : "=A" (retval));
239
240 return ((uint64)tv.tv_sec * 1000000) + tv.tv_usec;
241 #else
242 return clock();
243 #endif
244 }
245
246 uint64 sys_get_hiresclk_ticks_per_second()
247 {
248 #if HAVE_GETTIMEOFDAY
249 return 1000000;
250 #else
251 return clock();
252 #endif
253 }

  ViewVC Help
Powered by ViewVC 1.1.26