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 **/ 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 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 **/ 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 **/ 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 */ 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 **/ 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 **/ 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 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 **/ 202 ESR_ReturnCode PCPUTimerStart(PCPUTimer *timer) 203 { 204 return ESR_SUCCESS; 205 } 206 207 /** 208 * Stops the timer. 209 **/ 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 */ 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 **/ 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