xpcom/ds/TimeStamp_darwin.cpp

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 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 //
     8 // Implement TimeStamp::Now() with mach_absolute_time
     9 //
    10 // The "tick" unit for mach_absolute_time is defined using mach_timebase_info() which
    11 // gives a conversion ratio to nanoseconds. For more information see Apple's QA1398.
    12 //
    13 // This code is inspired by Chromium's time_mac.cc. The biggest
    14 // differences are that we explicitly initialize using
    15 // TimeStamp::Initialize() instead of lazily in Now() and that
    16 // we store the time value in ticks and convert when needed instead
    17 // of storing the time value in nanoseconds.
    19 #include <mach/mach_time.h>
    20 #include <sys/time.h>
    21 #include <sys/sysctl.h>
    22 #include <time.h>
    23 #include <unistd.h>
    25 #include "mozilla/TimeStamp.h"
    26 #include "nsDebug.h"
    28 // Estimate of the smallest duration of time we can measure.
    29 static uint64_t sResolution;
    30 static uint64_t sResolutionSigDigs;
    32 static const uint64_t kNsPerMs   =    1000000;
    33 static const uint64_t kUsPerSec  =    1000000;
    34 static const double kNsPerMsd    =    1000000.0;
    35 static const double kNsPerSecd   = 1000000000.0;
    37 static bool gInitialized = false;
    38 static double sNsPerTick;
    40 static uint64_t
    41 ClockTime()
    42 {
    43   // mach_absolute_time is it when it comes to ticks on the Mac.  Other calls
    44   // with less precision (such as TickCount) just call through to
    45   // mach_absolute_time.
    46   //
    47   // At the time of writing mach_absolute_time returns the number of nanoseconds
    48   // since boot. This won't overflow 64bits for 500+ years so we aren't going
    49   // to worry about that possiblity
    50   return mach_absolute_time();
    51 }
    53 static uint64_t
    54 ClockResolutionNs()
    55 {
    56   uint64_t start = ClockTime();
    57   uint64_t end = ClockTime();
    58   uint64_t minres = (end - start);
    60   // 10 total trials is arbitrary: what we're trying to avoid by
    61   // looping is getting unlucky and being interrupted by a context
    62   // switch or signal, or being bitten by paging/cache effects
    63   for (int i = 0; i < 9; ++i) {
    64     start = ClockTime();
    65     end = ClockTime();
    67     uint64_t candidate = (start - end);
    68     if (candidate < minres)
    69       minres = candidate;
    70   }
    72   if (0 == minres) {
    73     // measurable resolution is either incredibly low, ~1ns, or very
    74     // high.  fall back on NSPR's resolution assumption
    75     minres = 1 * kNsPerMs;
    76   }
    78   return minres;
    79 }
    81 namespace mozilla {
    83 double
    84 TimeDuration::ToSeconds() const
    85 {
    86   NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early");
    87   return (mValue * sNsPerTick) / kNsPerSecd;
    88 }
    90 double
    91 TimeDuration::ToSecondsSigDigits() const
    92 {
    93   NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early");
    94   // don't report a value < mResolution ...
    95   int64_t valueSigDigs = sResolution * (mValue / sResolution);
    96   // and chop off insignificant digits
    97   valueSigDigs = sResolutionSigDigs * (valueSigDigs / sResolutionSigDigs);
    98   return (valueSigDigs * sNsPerTick) / kNsPerSecd;
    99 }
   101 TimeDuration
   102 TimeDuration::FromMilliseconds(double aMilliseconds)
   103 {
   104   NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early");
   105   return TimeDuration::FromTicks(int64_t((aMilliseconds * kNsPerMsd) / sNsPerTick));
   106 }
   108 TimeDuration
   109 TimeDuration::Resolution()
   110 {
   111   NS_ABORT_IF_FALSE(gInitialized, "calling TimeDuration too early");
   112   return TimeDuration::FromTicks(int64_t(sResolution));
   113 }
   115 nsresult
   116 TimeStamp::Startup()
   117 {
   118   if (gInitialized)
   119     return NS_OK;
   121   mach_timebase_info_data_t timebaseInfo;
   122   // Apple's QA1398 suggests that the output from mach_timebase_info
   123   // will not change while a program is running, so it should be safe
   124   // to cache the result.
   125   kern_return_t kr = mach_timebase_info(&timebaseInfo);
   126   if (kr != KERN_SUCCESS)
   127     NS_RUNTIMEABORT("mach_timebase_info failed");
   129   sNsPerTick = double(timebaseInfo.numer) / timebaseInfo.denom;
   131   sResolution = ClockResolutionNs();
   133   // find the number of significant digits in sResolution, for the
   134   // sake of ToSecondsSigDigits()
   135   for (sResolutionSigDigs = 1;
   136        !(sResolutionSigDigs == sResolution
   137          || 10*sResolutionSigDigs > sResolution);
   138        sResolutionSigDigs *= 10);
   140   gInitialized = true;
   142   return NS_OK;
   143 }
   145 void
   146 TimeStamp::Shutdown()
   147 {
   148 }
   150 TimeStamp
   151 TimeStamp::Now(bool aHighResolution)
   152 {
   153   return TimeStamp(ClockTime());
   154 }
   156 // Computes and returns the process uptime in microseconds.
   157 // Returns 0 if an error was encountered.
   159 uint64_t
   160 TimeStamp::ComputeProcessUptime()
   161 {
   162   struct timeval tv;
   163   int rv = gettimeofday(&tv, nullptr);
   165   if (rv == -1) {
   166     return 0;
   167   }
   169   int mib[] = {
   170     CTL_KERN,
   171     KERN_PROC,
   172     KERN_PROC_PID,
   173     getpid(),
   174   };
   175   u_int mibLen = sizeof(mib) / sizeof(mib[0]);
   177   struct kinfo_proc proc;
   178   size_t bufferSize = sizeof(proc);
   179   rv = sysctl(mib, mibLen, &proc, &bufferSize, nullptr, 0);
   181   if (rv == -1)
   182     return 0;
   184   uint64_t startTime =
   185     ((uint64_t)proc.kp_proc.p_un.__p_starttime.tv_sec * kUsPerSec) +
   186     proc.kp_proc.p_un.__p_starttime.tv_usec;
   187   uint64_t now = (tv.tv_sec * kUsPerSec) + tv.tv_usec;
   189   if (startTime > now)
   190     return 0;
   192   return now - startTime;
   193 }
   195 } // namespace mozilla

mercurial