1 /*---------------------------------------------------------------------------*
2 * pcputimer.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 "pcputimer.h"
23 #include "pmemory.h"
24
25 #if defined(_WIN32)
26
27 /*
28 Note that this implementation assumes that GetThreadTimes is
29 available (requires NT 3.5 and above) and that 64 bit arithmetic is
30 available (requires VC)
31 */
32
33 struct PCPUTimer_t
34 {
35 HANDLE hThread;
36 LARGE_INTEGER RefTime;
37 asr_uint32_t elapsed;
38 };
39
40
41 /**
42 * Creates a new timer object.
43 **/
PCPUTimerCreate(PCPUTimer ** timer)44 ESR_ReturnCode PCPUTimerCreate(PCPUTimer **timer)
45 {
46 PCPUTimer *tmp = NULL;
47
48 if (timer == NULL)
49 return ESR_INVALID_ARGUMENT;
50 tmp = NEW(PCPUTimer, "PCPUTimer");
51 if (tmp == NULL) return ESR_OUT_OF_MEMORY;
52
53 tmp->hThread = GetCurrentThread();
54 tmp->RefTime.QuadPart = -1;
55 tmp->elapsed = 0;
56 *timer = tmp;
57
58 return ESR_SUCCESS;
59 }
60
PCPUTimerDestroy(PCPUTimer * timer)61 ESR_ReturnCode PCPUTimerDestroy(PCPUTimer *timer)
62 {
63 if (timer == NULL) return ESR_INVALID_ARGUMENT;
64 FREE(timer);
65 return ESR_SUCCESS;
66 }
67
68 /**
69 * Starts the timer. This sets the reference time from which all new elapsed
70 * time are computed. This does not reset the elapsed time to 0. This is
71 * useful to pause the timer.
72 **/
PCPUTimerStart(PCPUTimer * timer)73 ESR_ReturnCode PCPUTimerStart(PCPUTimer *timer)
74 {
75 FILETIME CreationTime;
76 FILETIME ExitTime;
77 FILETIME KernelTime;
78 FILETIME UserTime;
79
80 if (timer == NULL) return ESR_INVALID_ARGUMENT;
81 if (!GetThreadTimes(timer->hThread,
82 &CreationTime, &ExitTime, &KernelTime, &UserTime))
83 {
84 return ESR_FATAL_ERROR;
85 }
86
87 timer->RefTime.QuadPart = (((LARGE_INTEGER*) & KernelTime)->QuadPart +
88 ((LARGE_INTEGER*) & UserTime)->QuadPart);
89
90 return ESR_SUCCESS;
91 }
92
93 /**
94 * Stops the timer.
95 **/
PCPUTimerStop(PCPUTimer * timer)96 ESR_ReturnCode PCPUTimerStop(PCPUTimer *timer)
97 {
98 if (timer == NULL) return ESR_INVALID_ARGUMENT;
99 if (timer->RefTime.QuadPart != -1)
100 {
101 FILETIME CreationTime;
102 FILETIME ExitTime;
103 FILETIME KernelTime;
104 FILETIME UserTime;
105
106 if (!GetThreadTimes(timer->hThread,
107 &CreationTime, &ExitTime, &KernelTime, &UserTime))
108 return ESR_FATAL_ERROR;
109
110 timer->elapsed =
111 (asr_uint32_t) (((LARGE_INTEGER*) &KernelTime)->QuadPart +
112 ((LARGE_INTEGER*) &UserTime)->QuadPart -
113 timer->RefTime.QuadPart) / 10;
114 }
115 return ESR_SUCCESS;
116 }
117
118 /**
119 * Returns the timer elapsed time. If the Timer is in the stopped state,
120 * successive calls to getElapsed() will always return the same value. If
121 * the Timer is in the started state, successive calls will return the
122 * elapsed time since the last time PCPUTimerStart() was called.
123 */
PCPUTimerGetElapsed(PCPUTimer * timer,asr_uint32_t * elapsed)124 ESR_ReturnCode PCPUTimerGetElapsed(PCPUTimer *timer, asr_uint32_t *elapsed)
125 {
126 if (timer == NULL || elapsed == NULL) return ESR_INVALID_ARGUMENT;
127 if (timer->RefTime.QuadPart != -1)
128 {
129 FILETIME CreationTime;
130 FILETIME ExitTime;
131 FILETIME KernelTime;
132 FILETIME UserTime;
133
134 if (!GetThreadTimes(timer->hThread,
135 &CreationTime, &ExitTime, &KernelTime, &UserTime))
136 return ESR_FATAL_ERROR;
137
138 *elapsed = timer->elapsed +
139 (asr_uint32_t)(((LARGE_INTEGER*) & KernelTime)->QuadPart +
140 ((LARGE_INTEGER*) & UserTime)->QuadPart -
141 timer->RefTime.QuadPart) / 10;
142 }
143 else
144 *elapsed = timer->elapsed;
145 return ESR_SUCCESS;
146 }
147
148
149 /**
150 * Resets the elapsed time to 0 and resets the reference time of the Timer.
151 * This effectively reset the timer in the same state it was right after creation.
152 **/
PCPUTimerReset(PCPUTimer * timer)153 ESR_ReturnCode PCPUTimerReset(PCPUTimer *timer)
154 {
155 if (timer == NULL) return ESR_INVALID_ARGUMENT;
156 timer->RefTime.QuadPart = -1;
157 timer->elapsed = 0;
158 return ESR_SUCCESS;
159 }
160
161 #elif defined(POSIX)
162 /*
163 */
164
165 struct PCPUTimer_t
166 {
167 HANDLE hThread;
168 asr_uint32_t RefTime;
169 asr_uint32_t elapsed;
170 };
171
172 /**
173 * Creates a new timer object.
174 **/
PCPUTimerCreate(PCPUTimer ** timer)175 ESR_ReturnCode PCPUTimerCreate(PCPUTimer **timer)
176 {
177 PCPUTimer *tmp = NULL;
178
179 if (timer == NULL) return ESR_INVALID_ARGUMENT;
180 tmp = NEW(PCPUTimer, "PCPUTimer");
181 if (tmp == NULL) return ESR_OUT_OF_MEMORY;
182
183 tmp->hThread = (HANDLE)pthread_self();
184 tmp->elapsed = 0;
185 *timer = tmp;
186
187 return ESR_SUCCESS;
188 }
189
PCPUTimerDestroy(PCPUTimer * timer)190 ESR_ReturnCode PCPUTimerDestroy(PCPUTimer *timer)
191 {
192 if (timer == NULL) return ESR_INVALID_ARGUMENT;
193 FREE(timer);
194 return ESR_SUCCESS;
195 }
196
197 /**
198 * Starts the timer. This sets the reference time from which all new elapsed
199 * time are computed. This does not reset the elapsed time to 0. This is
200 * useful to pause the timer.
201 **/
PCPUTimerStart(PCPUTimer * timer)202 ESR_ReturnCode PCPUTimerStart(PCPUTimer *timer)
203 {
204 return ESR_SUCCESS;
205 }
206
207 /**
208 * Stops the timer.
209 **/
PCPUTimerStop(PCPUTimer * timer)210 ESR_ReturnCode PCPUTimerStop(PCPUTimer *timer)
211 {
212 return ESR_SUCCESS;
213 }
214
215 /**
216 * Returns the timer elapsed time. If the Timer is in the stopped state,
217 * successive calls to getElapsed() will always return the same value. If
218 * the Timer is in the started state, successive calls will return the
219 * elapsed time since the last time PCPUTimerStart() was called.
220 */
PCPUTimerGetElapsed(PCPUTimer * timer,asr_uint32_t * elapsed)221 ESR_ReturnCode PCPUTimerGetElapsed(PCPUTimer *timer, asr_uint32_t *elapsed)
222 {
223 return ESR_SUCCESS;
224 }
225
226
227 /**
228 * Resets the elapsed time to 0 and resets the reference time of the Timer.
229 * This effectively reset the timer in the same state it was right after creation.
230 **/
PCPUTimerReset(PCPUTimer * timer)231 ESR_ReturnCode PCPUTimerReset(PCPUTimer *timer)
232 {
233 return ESR_SUCCESS;
234 }
235
236 #else
237 /* #error "Ptimer not implemented for this platform." */
238 #endif
239