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