1 /* 2 * Copyright (C) 2008 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 /* 19 * System clock functions. 20 */ 21 22 #if defined(__ANDROID__) 23 #include <linux/ioctl.h> 24 #include <linux/rtc.h> 25 #include <utils/Atomic.h> 26 #include <linux/android_alarm.h> 27 #endif 28 29 #include <sys/time.h> 30 #include <limits.h> 31 #include <fcntl.h> 32 #include <string.h> 33 34 #include <utils/SystemClock.h> 35 #include <utils/Timers.h> 36 37 #define LOG_TAG "SystemClock" 38 #include <utils/Log.h> 39 40 namespace android { 41 42 /* 43 * native public static long uptimeMillis(); 44 */ 45 int64_t uptimeMillis() 46 { 47 int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); 48 return (int64_t) nanoseconds_to_milliseconds(when); 49 } 50 51 /* 52 * native public static long elapsedRealtime(); 53 */ 54 int64_t elapsedRealtime() 55 { 56 return nanoseconds_to_milliseconds(elapsedRealtimeNano()); 57 } 58 59 #define METHOD_CLOCK_GETTIME 0 60 #define METHOD_IOCTL 1 61 #define METHOD_SYSTEMTIME 2 62 63 /* 64 * To debug/verify the timestamps returned by the kernel, change 65 * DEBUG_TIMESTAMP to 1 and call the timestamp routine from a single thread 66 * in the test program. b/10899829 67 */ 68 #define DEBUG_TIMESTAMP 0 69 70 #if DEBUG_TIMESTAMP && defined(__arm__) 71 static inline void checkTimeStamps(int64_t timestamp, 72 int64_t volatile *prevTimestampPtr, 73 int volatile *prevMethodPtr, 74 int curMethod) 75 { 76 /* 77 * Disable the check for SDK since the prebuilt toolchain doesn't contain 78 * gettid, and int64_t is different on the ARM platform 79 * (ie long vs long long). 80 */ 81 int64_t prevTimestamp = *prevTimestampPtr; 82 int prevMethod = *prevMethodPtr; 83 84 if (timestamp < prevTimestamp) { 85 static const char *gettime_method_names[] = { 86 "clock_gettime", 87 "ioctl", 88 "systemTime", 89 }; 90 91 ALOGW("time going backwards: prev %lld(%s) vs now %lld(%s), tid=%d", 92 prevTimestamp, gettime_method_names[prevMethod], 93 timestamp, gettime_method_names[curMethod], 94 gettid()); 95 } 96 // NOTE - not atomic and may generate spurious warnings if the 64-bit 97 // write is interrupted or not observed as a whole. 98 *prevTimestampPtr = timestamp; 99 *prevMethodPtr = curMethod; 100 } 101 #else 102 #define checkTimeStamps(timestamp, prevTimestampPtr, prevMethodPtr, curMethod) 103 #endif 104 105 /* 106 * native public static long elapsedRealtimeNano(); 107 */ 108 int64_t elapsedRealtimeNano() 109 { 110 #if defined(__ANDROID__) 111 struct timespec ts; 112 int result; 113 int64_t timestamp; 114 #if DEBUG_TIMESTAMP 115 static volatile int64_t prevTimestamp; 116 static volatile int prevMethod; 117 #endif 118 119 static int s_fd = -1; 120 121 if (s_fd == -1) { 122 int fd = open("/dev/alarm", O_RDONLY); 123 if (android_atomic_cmpxchg(-1, fd, &s_fd)) { 124 close(fd); 125 } 126 } 127 128 result = ioctl(s_fd, 129 ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); 130 131 if (result == 0) { 132 timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; 133 checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL); 134 return timestamp; 135 } 136 137 // /dev/alarm doesn't exist, fallback to CLOCK_BOOTTIME 138 result = clock_gettime(CLOCK_BOOTTIME, &ts); 139 if (result == 0) { 140 timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; 141 checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, 142 METHOD_CLOCK_GETTIME); 143 return timestamp; 144 } 145 146 // XXX: there was an error, probably because the driver didn't 147 // exist ... this should return 148 // a real error, like an exception! 149 timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 150 checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, 151 METHOD_SYSTEMTIME); 152 return timestamp; 153 #else 154 return systemTime(SYSTEM_TIME_MONOTONIC); 155 #endif 156 } 157 158 }; // namespace android 159