Timers.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* 2 * Copyright (C) 2005 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17// 18// Timer functions. 19// 20#include <utils/Timers.h> 21#include <utils/ported.h> // may need usleep 22#include <utils/Log.h> 23 24#include <stdlib.h> 25#include <stdio.h> 26#include <unistd.h> 27#include <sys/time.h> 28#include <time.h> 29#include <errno.h> 30 31#ifdef HAVE_WIN32_THREADS 32#include <windows.h> 33#endif 34 35nsecs_t systemTime(int clock) 36{ 37#if defined(HAVE_POSIX_CLOCKS) 38 static const clockid_t clocks[] = { 39 CLOCK_REALTIME, 40 CLOCK_MONOTONIC, 41 CLOCK_PROCESS_CPUTIME_ID, 42 CLOCK_THREAD_CPUTIME_ID 43 }; 44 struct timespec t; 45 t.tv_sec = t.tv_nsec = 0; 46 clock_gettime(clocks[clock], &t); 47 return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec; 48#else 49 // we don't support the clocks here. 50 struct timeval t; 51 t.tv_sec = t.tv_usec = 0; 52 gettimeofday(&t, NULL); 53 return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL; 54#endif 55} 56 57//#define MONITOR_USLEEP 58 59/* 60 * Sleep long enough that we'll wake up "interval" milliseconds after 61 * the previous snooze. 62 * 63 * The "nextTick" argument is updated on each call, and should be passed 64 * in every time. Set its fields to zero on the first call. 65 * 66 * Returns the #of intervals we have overslept, which will be zero if we're 67 * on time. [Currently just returns 0 or 1.] 68 */ 69int sleepForInterval(long interval, struct timeval* pNextTick) 70{ 71 struct timeval now; 72 long long timeBeforeNext; 73 long sleepTime = 0; 74 bool overSlept = false; 75 //int usleepBias = 0; 76 77#ifdef USLEEP_BIAS 78 /* 79 * Linux likes to add 9000ms or so. 80 * [not using this for now] 81 */ 82 //usleepBias = USLEEP_BIAS; 83#endif 84 85 gettimeofday(&now, NULL); 86 87 if (pNextTick->tv_sec == 0) { 88 /* special-case for first time through */ 89 *pNextTick = now; 90 sleepTime = interval; 91 android::DurationTimer::addToTimeval(pNextTick, interval); 92 } else { 93 /* 94 * Compute how much time there is before the next tick. If this 95 * value is negative, we've run over. If we've run over a little 96 * bit we can shorten the next frame to keep the pace steady, but 97 * if we've dramatically overshot we need to re-sync. 98 */ 99 timeBeforeNext = android::DurationTimer::subtractTimevals(pNextTick, &now); 100 //printf("TOP: now=%ld.%ld next=%ld.%ld diff=%ld\n", 101 // now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec, 102 // (long) timeBeforeNext); 103 if (timeBeforeNext < -interval) { 104 /* way over */ 105 overSlept = true; 106 sleepTime = 0; 107 *pNextTick = now; 108 } else if (timeBeforeNext <= 0) { 109 /* slightly over, keep the pace steady */ 110 overSlept = true; 111 sleepTime = 0; 112 } else if (timeBeforeNext <= interval) { 113 /* right on schedule */ 114 sleepTime = timeBeforeNext; 115 } else if (timeBeforeNext > interval && timeBeforeNext <= 2*interval) { 116 /* sleep call returned early; do a longer sleep this time */ 117 sleepTime = timeBeforeNext; 118 } else if (timeBeforeNext > interval) { 119 /* we went back in time -- somebody updated system clock? */ 120 /* (could also be a *seriously* broken usleep()) */ 121 LOG(LOG_DEBUG, "", 122 " Impossible: timeBeforeNext = %ld\n", (long)timeBeforeNext); 123 sleepTime = 0; 124 *pNextTick = now; 125 } 126 android::DurationTimer::addToTimeval(pNextTick, interval); 127 } 128 //printf(" Before sleep: now=%ld.%ld next=%ld.%ld sleepTime=%ld\n", 129 // now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec, 130 // sleepTime); 131 132 /* 133 * Sleep for the designated period of time. 134 * 135 * Linux tends to sleep for longer than requested, often by 17-18ms. 136 * MinGW tends to sleep for less than requested, by as much as 14ms, 137 * but occasionally oversleeps for 40+ms (looks like some external 138 * factors plus round-off on a 64Hz clock). Cygwin is pretty steady. 139 * 140 * If you start the MinGW version, and then launch the Cygwin version, 141 * the MinGW clock becomes more erratic. Not entirely sure why. 142 * 143 * (There's a lot of stuff here; it's really just a usleep() call with 144 * a bunch of instrumentation.) 145 */ 146 if (sleepTime > 0) { 147#if defined(MONITOR_USLEEP) 148 struct timeval before, after; 149 long long actual; 150 151 gettimeofday(&before, NULL); 152 usleep((long) sleepTime); 153 gettimeofday(&after, NULL); 154 155 /* check usleep() accuracy; default Linux threads are pretty sloppy */ 156 actual = android::DurationTimer::subtractTimevals(&after, &before); 157 if ((long) actual < sleepTime - 14000 /*(sleepTime/10)*/ || 158 (long) actual > sleepTime + 20000 /*(sleepTime/10)*/) 159 { 160 LOG(LOG_DEBUG, "", " Odd usleep: req=%ld, actual=%ld\n", sleepTime, 161 (long) actual); 162 } 163#else 164#ifdef HAVE_WIN32_THREADS 165 Sleep( sleepTime/1000 ); 166#else 167 usleep((long) sleepTime); 168#endif 169#endif 170 } 171 172 //printf("slept %d\n", sleepTime); 173 174 if (overSlept) 175 return 1; // close enough 176 else 177 return 0; 178} 179 180 181/* 182 * =========================================================================== 183 * DurationTimer 184 * =========================================================================== 185 */ 186 187using namespace android; 188 189// Start the timer. 190void DurationTimer::start(void) 191{ 192 gettimeofday(&mStartWhen, NULL); 193} 194 195// Stop the timer. 196void DurationTimer::stop(void) 197{ 198 gettimeofday(&mStopWhen, NULL); 199} 200 201// Get the duration in microseconds. 202long long DurationTimer::durationUsecs(void) const 203{ 204 return (long) subtractTimevals(&mStopWhen, &mStartWhen); 205} 206 207// Subtract two timevals. Returns the difference (ptv1-ptv2) in 208// microseconds. 209/*static*/ long long DurationTimer::subtractTimevals(const struct timeval* ptv1, 210 const struct timeval* ptv2) 211{ 212 long long stop = ((long long) ptv1->tv_sec) * 1000000LL + 213 ((long long) ptv1->tv_usec); 214 long long start = ((long long) ptv2->tv_sec) * 1000000LL + 215 ((long long) ptv2->tv_usec); 216 return stop - start; 217} 218 219// Add the specified amount of time to the timeval. 220/*static*/ void DurationTimer::addToTimeval(struct timeval* ptv, long usec) 221{ 222 if (usec < 0) { 223 LOG(LOG_WARN, "", "Negative values not supported in addToTimeval\n"); 224 return; 225 } 226 227 // normalize tv_usec if necessary 228 if (ptv->tv_usec >= 1000000) { 229 ptv->tv_sec += ptv->tv_usec / 1000000; 230 ptv->tv_usec %= 1000000; 231 } 232 233 ptv->tv_usec += usec % 1000000; 234 if (ptv->tv_usec >= 1000000) { 235 ptv->tv_usec -= 1000000; 236 ptv->tv_sec++; 237 } 238 ptv->tv_sec += usec / 1000000; 239} 240 241