Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | #include "base/time.h" |
michael@0 | 6 | |
michael@0 | 7 | #ifdef OS_MACOSX |
michael@0 | 8 | #include <mach/mach_time.h> |
michael@0 | 9 | #endif |
michael@0 | 10 | #include <sys/time.h> |
michael@0 | 11 | #ifdef ANDROID |
michael@0 | 12 | #include <time64.h> |
michael@0 | 13 | #else |
michael@0 | 14 | #include <time.h> |
michael@0 | 15 | #endif |
michael@0 | 16 | #if defined(ANDROID) || defined(OS_POSIX) |
michael@0 | 17 | #include <unistd.h> |
michael@0 | 18 | #endif |
michael@0 | 19 | |
michael@0 | 20 | #include <limits> |
michael@0 | 21 | |
michael@0 | 22 | #include "base/basictypes.h" |
michael@0 | 23 | #include "base/logging.h" |
michael@0 | 24 | |
michael@0 | 25 | namespace base { |
michael@0 | 26 | |
michael@0 | 27 | // The Time routines in this file use standard POSIX routines, or almost- |
michael@0 | 28 | // standard routines in the case of timegm. We need to use a Mach-specific |
michael@0 | 29 | // function for TimeTicks::Now() on Mac OS X. |
michael@0 | 30 | |
michael@0 | 31 | // Time ----------------------------------------------------------------------- |
michael@0 | 32 | |
michael@0 | 33 | // Some functions in time.cc use time_t directly, so we provide a zero offset |
michael@0 | 34 | // for them. The epoch is 1970-01-01 00:00:00 UTC. |
michael@0 | 35 | // static |
michael@0 | 36 | const int64_t Time::kTimeTToMicrosecondsOffset = GG_INT64_C(0); |
michael@0 | 37 | |
michael@0 | 38 | // static |
michael@0 | 39 | Time Time::Now() { |
michael@0 | 40 | struct timeval tv; |
michael@0 | 41 | struct timezone tz = { 0, 0 }; // UTC |
michael@0 | 42 | if (gettimeofday(&tv, &tz) != 0) { |
michael@0 | 43 | DCHECK(0) << "Could not determine time of day"; |
michael@0 | 44 | } |
michael@0 | 45 | // Combine seconds and microseconds in a 64-bit field containing microseconds |
michael@0 | 46 | // since the epoch. That's enough for nearly 600 centuries. |
michael@0 | 47 | return tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec; |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | // static |
michael@0 | 51 | Time Time::NowFromSystemTime() { |
michael@0 | 52 | // Just use Now() because Now() returns the system time. |
michael@0 | 53 | return Now(); |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | // static |
michael@0 | 57 | Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
michael@0 | 58 | struct tm timestruct; |
michael@0 | 59 | timestruct.tm_sec = exploded.second; |
michael@0 | 60 | timestruct.tm_min = exploded.minute; |
michael@0 | 61 | timestruct.tm_hour = exploded.hour; |
michael@0 | 62 | timestruct.tm_mday = exploded.day_of_month; |
michael@0 | 63 | timestruct.tm_mon = exploded.month - 1; |
michael@0 | 64 | timestruct.tm_year = exploded.year - 1900; |
michael@0 | 65 | timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this |
michael@0 | 66 | timestruct.tm_yday = 0; // mktime/timegm ignore this |
michael@0 | 67 | timestruct.tm_isdst = -1; // attempt to figure it out |
michael@0 | 68 | timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore |
michael@0 | 69 | timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
michael@0 | 70 | |
michael@0 | 71 | time_t seconds; |
michael@0 | 72 | #ifdef ANDROID |
michael@0 | 73 | seconds = mktime(×truct); |
michael@0 | 74 | #else |
michael@0 | 75 | if (is_local) |
michael@0 | 76 | seconds = mktime(×truct); |
michael@0 | 77 | else |
michael@0 | 78 | seconds = timegm(×truct); |
michael@0 | 79 | #endif |
michael@0 | 80 | |
michael@0 | 81 | int64_t milliseconds; |
michael@0 | 82 | // Handle overflow. Clamping the range to what mktime and timegm might |
michael@0 | 83 | // return is the best that can be done here. It's not ideal, but it's better |
michael@0 | 84 | // than failing here or ignoring the overflow case and treating each time |
michael@0 | 85 | // overflow as one second prior to the epoch. |
michael@0 | 86 | if (seconds == -1 && |
michael@0 | 87 | (exploded.year < 1969 || exploded.year > 1970)) { |
michael@0 | 88 | // If exploded.year is 1969 or 1970, take -1 as correct, with the |
michael@0 | 89 | // time indicating 1 second prior to the epoch. (1970 is allowed to handle |
michael@0 | 90 | // time zone and DST offsets.) Otherwise, return the most future or past |
michael@0 | 91 | // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. |
michael@0 | 92 | // |
michael@0 | 93 | // The minimum and maximum representible times that mktime and timegm could |
michael@0 | 94 | // return are used here instead of values outside that range to allow for |
michael@0 | 95 | // proper round-tripping between exploded and counter-type time |
michael@0 | 96 | // representations in the presence of possible truncation to time_t by |
michael@0 | 97 | // division and use with other functions that accept time_t. |
michael@0 | 98 | // |
michael@0 | 99 | // When representing the most distant time in the future, add in an extra |
michael@0 | 100 | // 999ms to avoid the time being less than any other possible value that |
michael@0 | 101 | // this function can return. |
michael@0 | 102 | if (exploded.year < 1969) { |
michael@0 | 103 | milliseconds = std::numeric_limits<time_t>::min() * |
michael@0 | 104 | kMillisecondsPerSecond; |
michael@0 | 105 | } else { |
michael@0 | 106 | milliseconds = (std::numeric_limits<time_t>::max() * |
michael@0 | 107 | kMillisecondsPerSecond) + |
michael@0 | 108 | kMillisecondsPerSecond - 1; |
michael@0 | 109 | } |
michael@0 | 110 | } else { |
michael@0 | 111 | milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | return Time(milliseconds * kMicrosecondsPerMillisecond); |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | void Time::Explode(bool is_local, Exploded* exploded) const { |
michael@0 | 118 | // Time stores times with microsecond resolution, but Exploded only carries |
michael@0 | 119 | // millisecond resolution, so begin by being lossy. |
michael@0 | 120 | int64_t milliseconds = us_ / kMicrosecondsPerMillisecond; |
michael@0 | 121 | time_t seconds = milliseconds / kMillisecondsPerSecond; |
michael@0 | 122 | |
michael@0 | 123 | struct tm timestruct; |
michael@0 | 124 | if (is_local) |
michael@0 | 125 | localtime_r(&seconds, ×truct); |
michael@0 | 126 | else |
michael@0 | 127 | gmtime_r(&seconds, ×truct); |
michael@0 | 128 | |
michael@0 | 129 | exploded->year = timestruct.tm_year + 1900; |
michael@0 | 130 | exploded->month = timestruct.tm_mon + 1; |
michael@0 | 131 | exploded->day_of_week = timestruct.tm_wday; |
michael@0 | 132 | exploded->day_of_month = timestruct.tm_mday; |
michael@0 | 133 | exploded->hour = timestruct.tm_hour; |
michael@0 | 134 | exploded->minute = timestruct.tm_min; |
michael@0 | 135 | exploded->second = timestruct.tm_sec; |
michael@0 | 136 | exploded->millisecond = milliseconds % kMillisecondsPerSecond; |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | // TimeTicks ------------------------------------------------------------------ |
michael@0 | 140 | |
michael@0 | 141 | // static |
michael@0 | 142 | TimeTicks TimeTicks::Now() { |
michael@0 | 143 | uint64_t absolute_micro; |
michael@0 | 144 | |
michael@0 | 145 | #if defined(OS_MACOSX) |
michael@0 | 146 | static mach_timebase_info_data_t timebase_info; |
michael@0 | 147 | if (timebase_info.denom == 0) { |
michael@0 | 148 | // Zero-initialization of statics guarantees that denom will be 0 before |
michael@0 | 149 | // calling mach_timebase_info. mach_timebase_info will never set denom to |
michael@0 | 150 | // 0 as that would be invalid, so the zero-check can be used to determine |
michael@0 | 151 | // whether mach_timebase_info has already been called. This is |
michael@0 | 152 | // recommended by Apple's QA1398. |
michael@0 | 153 | kern_return_t kr = mach_timebase_info(&timebase_info); |
michael@0 | 154 | DCHECK(kr == KERN_SUCCESS); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | // mach_absolute_time is it when it comes to ticks on the Mac. Other calls |
michael@0 | 158 | // with less precision (such as TickCount) just call through to |
michael@0 | 159 | // mach_absolute_time. |
michael@0 | 160 | |
michael@0 | 161 | // timebase_info converts absolute time tick units into nanoseconds. Convert |
michael@0 | 162 | // to microseconds up front to stave off overflows. |
michael@0 | 163 | absolute_micro = mach_absolute_time() / Time::kNanosecondsPerMicrosecond * |
michael@0 | 164 | timebase_info.numer / timebase_info.denom; |
michael@0 | 165 | |
michael@0 | 166 | // Don't bother with the rollover handling that the Windows version does. |
michael@0 | 167 | // With numer and denom = 1 (the expected case), the 64-bit absolute time |
michael@0 | 168 | // reported in nanoseconds is enough to last nearly 585 years. |
michael@0 | 169 | |
michael@0 | 170 | #elif defined(OS_OPENBSD) || defined(OS_POSIX) && \ |
michael@0 | 171 | defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 |
michael@0 | 172 | |
michael@0 | 173 | struct timespec ts; |
michael@0 | 174 | if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { |
michael@0 | 175 | NOTREACHED() << "clock_gettime(CLOCK_MONOTONIC) failed."; |
michael@0 | 176 | return TimeTicks(); |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | absolute_micro = |
michael@0 | 180 | (static_cast<int64_t>(ts.tv_sec) * Time::kMicrosecondsPerSecond) + |
michael@0 | 181 | (static_cast<int64_t>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond); |
michael@0 | 182 | |
michael@0 | 183 | #else // _POSIX_MONOTONIC_CLOCK |
michael@0 | 184 | #error No usable tick clock function on this platform. |
michael@0 | 185 | #endif // _POSIX_MONOTONIC_CLOCK |
michael@0 | 186 | |
michael@0 | 187 | return TimeTicks(absolute_micro); |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | // static |
michael@0 | 191 | TimeTicks TimeTicks::HighResNow() { |
michael@0 | 192 | return Now(); |
michael@0 | 193 | } |
michael@0 | 194 | |
michael@0 | 195 | } // namespace base |