• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------------------*
2  *  ptimer.c  *
3  *                                                                           *
4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5  *                                                                           *
6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7  *  you may not use this file except in compliance with the License.         *
8  *                                                                           *
9  *  You may obtain a copy of the License at                                  *
10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
11  *                                                                           *
12  *  Unless required by applicable law or agreed to in writing, software      *
13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15  *  See the License for the specific language governing permissions and      *
16  *  limitations under the License.                                           *
17  *                                                                           *
18  *---------------------------------------------------------------------------*/
19 
20 
21 
22 #include "pmemory.h"
23 #include "ptimer.h"
24 #include "pmutex.h"
25 
26 #ifdef _WIN32
27 
28 /*
29   Note that this implementation assumes that QueryPerformanceCounter is
30   available (requires NT 3.1 and above) and that 64 bit arithmetic is
31   available (requires VC)
32 */
33 
34 struct PTimer_t
35 {
36   LARGE_INTEGER PerformanceFreq;
37   LARGE_INTEGER RefTime;
38   LARGE_INTEGER elapsed;
39 };
40 
41 
42 
43 /**
44  * Creates a new timer object.
45  **/
PTimerCreate(PTimer ** timer)46 ESR_ReturnCode PTimerCreate(PTimer **timer)
47 {
48   PTimer *tmp = NULL;
49 
50   if (timer == NULL)
51     return ESR_INVALID_ARGUMENT;
52   tmp = NEW(PTimer, "PTimer");
53   if (tmp == NULL)
54     return ESR_OUT_OF_MEMORY;
55 
56   if (QueryPerformanceFrequency(&tmp->PerformanceFreq) == 0)
57   {
58     FREE(tmp);
59     return ESR_NOT_SUPPORTED;
60   }
61   tmp->PerformanceFreq.QuadPart /= 1000;
62 
63   tmp->RefTime.QuadPart = 0;
64   tmp->elapsed.QuadPart = 0;
65   *timer = tmp;
66   return ESR_SUCCESS;
67 }
68 
PTimerDestroy(PTimer * timer)69 ESR_ReturnCode PTimerDestroy(PTimer *timer)
70 {
71   if (timer == NULL) return ESR_INVALID_ARGUMENT;
72   FREE(timer);
73   return ESR_SUCCESS;
74 }
75 
76 /**
77  * Starts the timer. This sets the reference time from which all new elapsed
78  * time are computed.  This does not reset the elapsed time to 0.  This is
79  * useful to pause the timer.
80  **/
PTimerStart(PTimer * timer)81 ESR_ReturnCode PTimerStart(PTimer *timer)
82 {
83   if (timer == NULL) return ESR_INVALID_ARGUMENT;
84   return (QueryPerformanceCounter(&timer->RefTime) ?
85           ESR_SUCCESS :
86           ESR_NOT_SUPPORTED);
87 }
88 
89 /**
90  * Stops the timer.
91  **/
PTimerStop(PTimer * timer)92 ESR_ReturnCode PTimerStop(PTimer *timer)
93 {
94   if (timer == NULL) return ESR_INVALID_ARGUMENT;
95   if (timer->RefTime.QuadPart != 0)
96   {
97     LARGE_INTEGER now;
98     if (!QueryPerformanceCounter(&now)) return ESR_NOT_SUPPORTED;
99     timer->elapsed.QuadPart += now.QuadPart - timer->RefTime.QuadPart;
100     timer->RefTime.QuadPart = 0;
101   }
102   return ESR_SUCCESS;
103 }
104 
105 /**
106  * Returns the timer elapsed time.  If the Timer is in the stopped state,
107  * successive calls to getElapsed() will always return the same value.  If
108  * the Timer is in the started state, successive calls will return the
109  * elapsed time since the last time PTimerStart() was called.
110  */
PTimerGetElapsed(PTimer * timer,asr_uint32_t * elapsed)111 ESR_ReturnCode PTimerGetElapsed(PTimer *timer, asr_uint32_t* elapsed)
112 {
113   if (timer == NULL || elapsed == NULL)
114     return ESR_INVALID_ARGUMENT;
115 
116   if (timer->RefTime.QuadPart != 0)
117   {
118     LARGE_INTEGER now;
119     if (!QueryPerformanceCounter(&now)) return ESR_NOT_SUPPORTED;
120     *elapsed = (asr_uint32_t) ((timer->elapsed.QuadPart + (now.QuadPart - timer->RefTime.QuadPart))
121                            / timer->PerformanceFreq.QuadPart);
122   }
123   else
124     *elapsed = (asr_uint32_t) (timer->elapsed.QuadPart / timer->PerformanceFreq.QuadPart);
125 
126   return ESR_SUCCESS;
127 }
128 
129 
130 /**
131  * Resets the elapsed time to 0 and resets the reference time of the Timer.
132  * This effectively reset the timer in the same state it was right after creation.
133  **/
PTimerReset(PTimer * timer)134 ESR_ReturnCode PTimerReset(PTimer *timer)
135 {
136   if (timer == NULL) return ESR_INVALID_ARGUMENT;
137   timer->RefTime.QuadPart = 0;
138   timer->elapsed.QuadPart = 0;
139   return ESR_SUCCESS;
140 }
141 
142 #elif defined(POSIX)
143 #include "ptrd.h"
144 /*
145 POSIX has a timer
146 */
147 /* Clocks and timers: clock_settime, clock_gettime, clock_getres, timer_xxx and nanosleep */
148 #ifndef _POSIX_TIMERS
149 #ifndef __vxworks /* __vxworks does not define it! */
150 #error "Timer is not defined!"
151 #endif /* __vxworks */
152 #endif /* _POSIX_TIMERS */
153 
154 #define TIMER_MAX_VAL 10000
155 
156 struct PTimer_t
157 {
158   timer_t  timer;
159   asr_uint32_t elapsed;
160 };
161 
162 /**
163 * Creates a new timer object.
164 **/
PTimerCreate(PTimer ** timer)165 ESR_ReturnCode PTimerCreate(PTimer **timer)
166 {
167   PTimer *tmp = NULL;
168 
169   if (timer == NULL) return ESR_INVALID_ARGUMENT;
170   tmp = NEW(PTimer, "PTimer");
171   if (tmp == NULL) return ESR_OUT_OF_MEMORY;
172 
173   *timer = tmp;
174   if (timer_create(CLOCK_REALTIME, NULL, &(tmp->timer)) < 0)
175     return ESR_NOT_SUPPORTED;
176 
177   return ESR_SUCCESS;
178 }
179 
PTimerDestroy(PTimer * timer)180 ESR_ReturnCode PTimerDestroy(PTimer *timer)
181 {
182   if (timer == NULL) return ESR_INVALID_ARGUMENT;
183   timer_delete(timer->timer);
184   FREE(timer);
185 
186   return ESR_SUCCESS;
187 }
188 
189 /**
190 * Starts the timer. This sets the reference time from which all new elapsed
191 * time are computed.  This does not reset the elapsed time to 0.  This is
192 * useful to pause the timer.
193 **/
PTimerStart(PTimer * timer)194 ESR_ReturnCode PTimerStart(PTimer *timer)
195 {
196   struct itimerspec expire_time;
197 
198   if (timer == NULL) return ESR_INVALID_ARGUMENT;
199 
200   expire_time.it_value.tv_sec = TIMER_MAX_VAL; /* set a large time for the timer */
201   expire_time.it_value.tv_nsec = 0;
202   return (timer_settime(timer->timer, 0, &expire_time, NULL) == 0 ?
203           ESR_SUCCESS :
204           ESR_NOT_SUPPORTED);
205 }
206 
207 /**
208 * Stops the timer.
209 **/
PTimerStop(PTimer * timer)210 ESR_ReturnCode PTimerStop(PTimer *timer)
211 {
212   struct itimerspec remaining;
213 
214   if (timer == NULL) return ESR_INVALID_ARGUMENT;
215 
216   if (timer_gettime(timer->timer, &remaining) != 0) return ESR_NOT_SUPPORTED;
217 #if defined(__vxworks)
218   timer_cancel(timer->timer);
219 #endif
220   timer->elapsed = (asr_uint32_t) ((TIMER_MAX_VAL - remaining.it_value.tv_sec) * SECOND2MSECOND
221 						- remaining.it_value.tv_nsec / MSECOND2NSECOND);
222 
223   return ESR_SUCCESS;
224 }
225 
226 /**
227 * Returns the timer elapsed time.  If the Timer is in the stopped state,
228 * successive calls to getElapsed() will always return the same value.  If
229 * the Timer is in the started state, successive calls will return the
230 * elapsed time since the last time PTimerStart() was called.
231 */
PTimerGetElapsed(PTimer * timer,asr_uint32_t * elapsed)232 ESR_ReturnCode PTimerGetElapsed(PTimer *timer, asr_uint32_t* elapsed)
233 {
234   if (timer == NULL || elapsed == NULL)
235     return ESR_INVALID_ARGUMENT;
236 
237   if (timer->elapsed == 0) /* stop is not called */
238   {
239     struct itimerspec remaining;
240     if (timer_gettime(timer->timer, &remaining) != 0) return ESR_NOT_SUPPORTED;
241     *elapsed = (asr_uint32_t) ((TIMER_MAX_VAL - remaining.it_value.tv_sec) * SECOND2MSECOND
242 						- remaining.it_value.tv_nsec / MSECOND2NSECOND);
243   }
244   else
245     *elapsed = timer->elapsed;
246 
247   return ESR_SUCCESS;
248 }
249 
250 
251 /**
252 * Resets the elapsed time to 0 and resets the reference time of the Timer.
253 * This effectively reset the timer in the same state it was right after creation.
254 **/
PTimerReset(PTimer * timer)255 ESR_ReturnCode PTimerReset(PTimer *timer)
256 {
257   if (timer == NULL) return ESR_INVALID_ARGUMENT;
258   timer->elapsed = 0;
259   return ESR_SUCCESS;
260 }
261 
262 #else
263 #error "Ptimer not implemented for this platform."
264 #endif
265