| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
|  | 35 | nsecs_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 | */ | 
|  | 69 | int 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 |  | 
|  | 187 | using namespace android; | 
|  | 188 |  | 
|  | 189 | // Start the timer. | 
|  | 190 | void DurationTimer::start(void) | 
|  | 191 | { | 
|  | 192 | gettimeofday(&mStartWhen, NULL); | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | // Stop the timer. | 
|  | 196 | void DurationTimer::stop(void) | 
|  | 197 | { | 
|  | 198 | gettimeofday(&mStopWhen, NULL); | 
|  | 199 | } | 
|  | 200 |  | 
|  | 201 | // Get the duration in microseconds. | 
|  | 202 | long 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 |  |