ipc/chromium/src/base/time_posix.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial