text: /*
   * Copyright (C) 2005 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  //
  // Timer functions.
  //
  #include <utils/Timers.h>
  #include <utils/Log.h>
  
  #include <stdlib.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <sys/time.h>
  #include <time.h>
  #include <errno.h>
  #include <limits.h>
  
  #ifdef HAVE_WIN32_THREADS
  #include <windows.h>
  #endif
  
  nsecs_t systemTime(int clock)
  {
  #if defined(HAVE_POSIX_CLOCKS)
      static const clockid_t clocks[] = {
              CLOCK_REALTIME,
              CLOCK_MONOTONIC,
              CLOCK_PROCESS_CPUTIME_ID,
              CLOCK_THREAD_CPUTIME_ID,
              CLOCK_BOOTTIME
      };
      struct timespec t;
      t.tv_sec = t.tv_nsec = 0;
      clock_gettime(clocks[clock], &t);
      return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
  #else
      // we don't support the clocks here.
      struct timeval t;
      t.tv_sec = t.tv_usec = 0;
      gettimeofday(&t, NULL);
      return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL;
  #endif
  }
  
  int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
  {
      int timeoutDelayMillis;
      if (timeoutTime > referenceTime) {
          uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
          if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
              timeoutDelayMillis = -1;
          } else {
              timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL;
          }
      } else {
          timeoutDelayMillis = 0;
      }
      return timeoutDelayMillis;
  }
  
  
  /*
   * ===========================================================================
   *      DurationTimer
   * ===========================================================================
   */
  
  using namespace android;
  
  // Start the timer.
  void DurationTimer::start(void)
  {
      gettimeofday(&mStartWhen, NULL);
  }
  
  // Stop the timer.
  void DurationTimer::stop(void)
  {
      gettimeofday(&mStopWhen, NULL);
  }
  
  // Get the duration in microseconds.
  long long DurationTimer::durationUsecs(void) const
  {
      return (long) subtractTimevals(&mStopWhen, &mStartWhen);
  }
  
  // Subtract two timevals.  Returns the difference (ptv1-ptv2) in
  // microseconds.
  /*static*/ long long DurationTimer::subtractTimevals(const struct timeval* ptv1,
      const struct timeval* ptv2)
  {
      long long stop  = ((long long) ptv1->tv_sec) * 1000000LL +
                        ((long long) ptv1->tv_usec);
      long long start = ((long long) ptv2->tv_sec) * 1000000LL +
                        ((long long) ptv2->tv_usec);
      return stop - start;
  }
  
  // Add the specified amount of time to the timeval.
  /*static*/ void DurationTimer::addToTimeval(struct timeval* ptv, long usec)
  {
      if (usec < 0) {
          ALOG(LOG_WARN, "", "Negative values not supported in addToTimeval\n");
          return;
      }
  
      // normalize tv_usec if necessary
      if (ptv->tv_usec >= 1000000) {
          ptv->tv_sec += ptv->tv_usec / 1000000;
          ptv->tv_usec %= 1000000;
      }
  
      ptv->tv_usec += usec % 1000000;
      if (ptv->tv_usec >= 1000000) {
          ptv->tv_usec -= 1000000;
          ptv->tv_sec++;
      }
      ptv->tv_sec += usec / 1000000;
  }
  
  