/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide 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 dpavlin 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