LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - time_posix.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 6 58 10.3 %
Date: 2017-07-14 16:53:18 Functions: 1 6 16.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13