Home | History | Annotate | Download | only in src
      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