1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/time/time.h" 6 7#include <stdint.h> 8#include <sys/time.h> 9#include <time.h> 10#if defined(OS_ANDROID) && !defined(__LP64__) 11#include <time64.h> 12#endif 13#include <unistd.h> 14 15#include <limits> 16#include <ostream> 17 18#include "base/basictypes.h" 19#include "base/logging.h" 20#include "base/port.h" 21#include "build/build_config.h" 22 23#if defined(OS_ANDROID) 24#include "base/os_compat_android.h" 25#elif defined(OS_NACL) 26#include "base/os_compat_nacl.h" 27#endif 28 29#if !defined(OS_MACOSX) 30#include "base/lazy_instance.h" 31#include "base/synchronization/lock.h" 32#endif 33 34namespace { 35 36#if !defined(OS_MACOSX) 37// This prevents a crash on traversing the environment global and looking up 38// the 'TZ' variable in libc. See: crbug.com/390567. 39base::LazyInstance<base::Lock>::Leaky 40 g_sys_time_to_time_struct_lock = LAZY_INSTANCE_INITIALIZER; 41 42// Define a system-specific SysTime that wraps either to a time_t or 43// a time64_t depending on the host system, and associated convertion. 44// See crbug.com/162007 45#if defined(OS_ANDROID) && !defined(__LP64__) 46typedef time64_t SysTime; 47 48SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { 49 base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); 50 if (is_local) 51 return mktime64(timestruct); 52 else 53 return timegm64(timestruct); 54} 55 56void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { 57 base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); 58 if (is_local) 59 localtime64_r(&t, timestruct); 60 else 61 gmtime64_r(&t, timestruct); 62} 63 64#else // OS_ANDROID && !__LP64__ 65typedef time_t SysTime; 66 67SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { 68 base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); 69 if (is_local) 70 return mktime(timestruct); 71 else 72 return timegm(timestruct); 73} 74 75void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { 76 base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); 77 if (is_local) 78 localtime_r(&t, timestruct); 79 else 80 gmtime_r(&t, timestruct); 81} 82#endif // OS_ANDROID 83 84// Helper function to get results from clock_gettime() as TimeTicks object. 85// Minimum requirement is MONOTONIC_CLOCK to be supported on the system. 86// FreeBSD 6 has CLOCK_MONOTONIC but defines _POSIX_MONOTONIC_CLOCK to -1. 87#if (defined(OS_POSIX) && \ 88 defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \ 89 defined(OS_BSD) || defined(OS_ANDROID) 90base::TimeTicks ClockNow(clockid_t clk_id) { 91 uint64_t absolute_micro; 92 93 struct timespec ts; 94 if (clock_gettime(clk_id, &ts) != 0) { 95 NOTREACHED() << "clock_gettime(" << clk_id << ") failed."; 96 return base::TimeTicks(); 97 } 98 99 absolute_micro = 100 (static_cast<int64>(ts.tv_sec) * base::Time::kMicrosecondsPerSecond) + 101 (static_cast<int64>(ts.tv_nsec) / base::Time::kNanosecondsPerMicrosecond); 102 103 return base::TimeTicks::FromInternalValue(absolute_micro); 104} 105#else // _POSIX_MONOTONIC_CLOCK 106#error No usable tick clock function on this platform. 107#endif // _POSIX_MONOTONIC_CLOCK 108#endif // !defined(OS_MACOSX) 109 110} // namespace 111 112namespace base { 113 114struct timespec TimeDelta::ToTimeSpec() const { 115 int64 microseconds = InMicroseconds(); 116 time_t seconds = 0; 117 if (microseconds >= Time::kMicrosecondsPerSecond) { 118 seconds = InSeconds(); 119 microseconds -= seconds * Time::kMicrosecondsPerSecond; 120 } 121 struct timespec result = 122 {seconds, 123 static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)}; 124 return result; 125} 126 127#if !defined(OS_MACOSX) 128// The Time routines in this file use standard POSIX routines, or almost- 129// standard routines in the case of timegm. We need to use a Mach-specific 130// function for TimeTicks::Now() on Mac OS X. 131 132// Time ----------------------------------------------------------------------- 133 134// Windows uses a Gregorian epoch of 1601. We need to match this internally 135// so that our time representations match across all platforms. See bug 14734. 136// irb(main):010:0> Time.at(0).getutc() 137// => Thu Jan 01 00:00:00 UTC 1970 138// irb(main):011:0> Time.at(-11644473600).getutc() 139// => Mon Jan 01 00:00:00 UTC 1601 140static const int64 kWindowsEpochDeltaSeconds = GG_INT64_C(11644473600); 141 142// static 143const int64 Time::kWindowsEpochDeltaMicroseconds = 144 kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; 145 146// Some functions in time.cc use time_t directly, so we provide an offset 147// to convert from time_t (Unix epoch) and internal (Windows epoch). 148// static 149const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; 150 151// static 152Time Time::Now() { 153 struct timeval tv; 154 struct timezone tz = { 0, 0 }; // UTC 155 if (gettimeofday(&tv, &tz) != 0) { 156 DCHECK(0) << "Could not determine time of day"; 157 PLOG(ERROR) << "Call to gettimeofday failed."; 158 // Return null instead of uninitialized |tv| value, which contains random 159 // garbage data. This may result in the crash seen in crbug.com/147570. 160 return Time(); 161 } 162 // Combine seconds and microseconds in a 64-bit field containing microseconds 163 // since the epoch. That's enough for nearly 600 centuries. Adjust from 164 // Unix (1970) to Windows (1601) epoch. 165 return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) + 166 kWindowsEpochDeltaMicroseconds); 167} 168 169// static 170Time Time::NowFromSystemTime() { 171 // Just use Now() because Now() returns the system time. 172 return Now(); 173} 174 175void Time::Explode(bool is_local, Exploded* exploded) const { 176 // Time stores times with microsecond resolution, but Exploded only carries 177 // millisecond resolution, so begin by being lossy. Adjust from Windows 178 // epoch (1601) to Unix epoch (1970); 179 int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; 180 // The following values are all rounded towards -infinity. 181 int64 milliseconds; // Milliseconds since epoch. 182 SysTime seconds; // Seconds since epoch. 183 int millisecond; // Exploded millisecond value (0-999). 184 if (microseconds >= 0) { 185 // Rounding towards -infinity <=> rounding towards 0, in this case. 186 milliseconds = microseconds / kMicrosecondsPerMillisecond; 187 seconds = milliseconds / kMillisecondsPerSecond; 188 millisecond = milliseconds % kMillisecondsPerSecond; 189 } else { 190 // Round these *down* (towards -infinity). 191 milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / 192 kMicrosecondsPerMillisecond; 193 seconds = (milliseconds - kMillisecondsPerSecond + 1) / 194 kMillisecondsPerSecond; 195 // Make this nonnegative (and between 0 and 999 inclusive). 196 millisecond = milliseconds % kMillisecondsPerSecond; 197 if (millisecond < 0) 198 millisecond += kMillisecondsPerSecond; 199 } 200 201 struct tm timestruct; 202 SysTimeToTimeStruct(seconds, ×truct, is_local); 203 204 exploded->year = timestruct.tm_year + 1900; 205 exploded->month = timestruct.tm_mon + 1; 206 exploded->day_of_week = timestruct.tm_wday; 207 exploded->day_of_month = timestruct.tm_mday; 208 exploded->hour = timestruct.tm_hour; 209 exploded->minute = timestruct.tm_min; 210 exploded->second = timestruct.tm_sec; 211 exploded->millisecond = millisecond; 212} 213 214// static 215Time Time::FromExploded(bool is_local, const Exploded& exploded) { 216 struct tm timestruct; 217 timestruct.tm_sec = exploded.second; 218 timestruct.tm_min = exploded.minute; 219 timestruct.tm_hour = exploded.hour; 220 timestruct.tm_mday = exploded.day_of_month; 221 timestruct.tm_mon = exploded.month - 1; 222 timestruct.tm_year = exploded.year - 1900; 223 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this 224 timestruct.tm_yday = 0; // mktime/timegm ignore this 225 timestruct.tm_isdst = -1; // attempt to figure it out 226#if !defined(OS_NACL) && !defined(OS_SOLARIS) 227 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore 228 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore 229#endif 230 231 232 int64 milliseconds; 233 SysTime seconds; 234 235 // Certain exploded dates do not really exist due to daylight saving times, 236 // and this causes mktime() to return implementation-defined values when 237 // tm_isdst is set to -1. On Android, the function will return -1, while the 238 // C libraries of other platforms typically return a liberally-chosen value. 239 // Handling this requires the special code below. 240 241 // SysTimeFromTimeStruct() modifies the input structure, save current value. 242 struct tm timestruct0 = timestruct; 243 244 seconds = SysTimeFromTimeStruct(×truct, is_local); 245 if (seconds == -1) { 246 // Get the time values with tm_isdst == 0 and 1, then select the closest one 247 // to UTC 00:00:00 that isn't -1. 248 timestruct = timestruct0; 249 timestruct.tm_isdst = 0; 250 int64 seconds_isdst0 = SysTimeFromTimeStruct(×truct, is_local); 251 252 timestruct = timestruct0; 253 timestruct.tm_isdst = 1; 254 int64 seconds_isdst1 = SysTimeFromTimeStruct(×truct, is_local); 255 256 // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones. 257 // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'. 258 if (seconds_isdst0 < 0) 259 seconds = seconds_isdst1; 260 else if (seconds_isdst1 < 0) 261 seconds = seconds_isdst0; 262 else 263 seconds = std::min(seconds_isdst0, seconds_isdst1); 264 } 265 266 // Handle overflow. Clamping the range to what mktime and timegm might 267 // return is the best that can be done here. It's not ideal, but it's better 268 // than failing here or ignoring the overflow case and treating each time 269 // overflow as one second prior to the epoch. 270 if (seconds == -1 && 271 (exploded.year < 1969 || exploded.year > 1970)) { 272 // If exploded.year is 1969 or 1970, take -1 as correct, with the 273 // time indicating 1 second prior to the epoch. (1970 is allowed to handle 274 // time zone and DST offsets.) Otherwise, return the most future or past 275 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. 276 // 277 // The minimum and maximum representible times that mktime and timegm could 278 // return are used here instead of values outside that range to allow for 279 // proper round-tripping between exploded and counter-type time 280 // representations in the presence of possible truncation to time_t by 281 // division and use with other functions that accept time_t. 282 // 283 // When representing the most distant time in the future, add in an extra 284 // 999ms to avoid the time being less than any other possible value that 285 // this function can return. 286 287 // On Android, SysTime is int64, special care must be taken to avoid 288 // overflows. 289 const int64 min_seconds = (sizeof(SysTime) < sizeof(int64)) 290 ? std::numeric_limits<SysTime>::min() 291 : std::numeric_limits<int32_t>::min(); 292 const int64 max_seconds = (sizeof(SysTime) < sizeof(int64)) 293 ? std::numeric_limits<SysTime>::max() 294 : std::numeric_limits<int32_t>::max(); 295 if (exploded.year < 1969) { 296 milliseconds = min_seconds * kMillisecondsPerSecond; 297 } else { 298 milliseconds = max_seconds * kMillisecondsPerSecond; 299 milliseconds += (kMillisecondsPerSecond - 1); 300 } 301 } else { 302 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; 303 } 304 305 // Adjust from Unix (1970) to Windows (1601) epoch. 306 return Time((milliseconds * kMicrosecondsPerMillisecond) + 307 kWindowsEpochDeltaMicroseconds); 308} 309 310// TimeTicks ------------------------------------------------------------------ 311// static 312TimeTicks TimeTicks::Now() { 313 return ClockNow(CLOCK_MONOTONIC); 314} 315 316// static 317TimeTicks TimeTicks::HighResNow() { 318 return Now(); 319} 320 321// static 322bool TimeTicks::IsHighResNowFastAndReliable() { 323 return true; 324} 325 326// static 327TimeTicks TimeTicks::ThreadNow() { 328#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ 329 defined(OS_ANDROID) 330 return ClockNow(CLOCK_THREAD_CPUTIME_ID); 331#else 332 NOTREACHED(); 333 return TimeTicks(); 334#endif 335} 336 337// Use the Chrome OS specific system-wide clock. 338#if defined(OS_CHROMEOS) 339// static 340TimeTicks TimeTicks::NowFromSystemTraceTime() { 341 uint64_t absolute_micro; 342 343 struct timespec ts; 344 if (clock_gettime(kClockSystemTrace, &ts) != 0) { 345 // NB: fall-back for a chrome os build running on linux 346 return HighResNow(); 347 } 348 349 absolute_micro = 350 (static_cast<int64>(ts.tv_sec) * Time::kMicrosecondsPerSecond) + 351 (static_cast<int64>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond); 352 353 return TimeTicks(absolute_micro); 354} 355 356#else // !defined(OS_CHROMEOS) 357 358// static 359TimeTicks TimeTicks::NowFromSystemTraceTime() { 360 return HighResNow(); 361} 362 363#endif // defined(OS_CHROMEOS) 364 365#endif // !OS_MACOSX 366 367// static 368Time Time::FromTimeVal(struct timeval t) { 369 DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond)); 370 DCHECK_GE(t.tv_usec, 0); 371 if (t.tv_usec == 0 && t.tv_sec == 0) 372 return Time(); 373 if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 && 374 t.tv_sec == std::numeric_limits<time_t>::max()) 375 return Max(); 376 return Time( 377 (static_cast<int64>(t.tv_sec) * Time::kMicrosecondsPerSecond) + 378 t.tv_usec + 379 kTimeTToMicrosecondsOffset); 380} 381 382struct timeval Time::ToTimeVal() const { 383 struct timeval result; 384 if (is_null()) { 385 result.tv_sec = 0; 386 result.tv_usec = 0; 387 return result; 388 } 389 if (is_max()) { 390 result.tv_sec = std::numeric_limits<time_t>::max(); 391 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; 392 return result; 393 } 394 int64 us = us_ - kTimeTToMicrosecondsOffset; 395 result.tv_sec = us / Time::kMicrosecondsPerSecond; 396 result.tv_usec = us % Time::kMicrosecondsPerSecond; 397 return result; 398} 399 400} // namespace base 401