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 33struct 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 **/ 44ESR_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 61ESR_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 **/ 73ESR_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 **/ 96ESR_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 */ 124ESR_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 **/ 153ESR_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 165struct 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**/ 175ESR_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 190ESR_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**/ 202ESR_ReturnCode PCPUTimerStart(PCPUTimer *timer) 203{ 204 return ESR_SUCCESS; 205} 206 207/** 208* Stops the timer. 209**/ 210ESR_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*/ 221ESR_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**/ 231ESR_ReturnCode PCPUTimerReset(PCPUTimer *timer) 232{ 233 return ESR_SUCCESS; 234} 235 236#else 237/* #error "Ptimer not implemented for this platform." */ 238#endif 239