TimeStamp_darwin.cpp (3924B)
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 /* 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/. */ 6 7 // 8 // Implement TimeStamp::Now() with mach_absolute_time 9 // 10 // The "tick" unit for mach_absolute_time is defined using mach_timebase_info() 11 // which gives a conversion ratio to nanoseconds. For more information see 12 // Apple's QA1398. 13 // 14 // This code is inspired by Chromium's time_mac.cc. The biggest 15 // differences are that we explicitly initialize using 16 // TimeStamp::Initialize() instead of lazily in Now() and that 17 // we store the time value in ticks and convert when needed instead 18 // of storing the time value in nanoseconds. 19 20 #include <mach/mach_time.h> 21 #include <sys/time.h> 22 #include <sys/sysctl.h> 23 #include <time.h> 24 #include <unistd.h> 25 26 #include "mozilla/TimeStamp.h" 27 #include "mozilla/Uptime.h" 28 29 static const uint64_t kUsPerSec = 1000000; 30 static const double kNsPerMsd = 1000000.0; 31 static const double kNsPerSecd = 1000000000.0; 32 33 static bool gInitialized = false; 34 static double sNsPerTickd; 35 36 static uint64_t ClockTime() { 37 // mach_absolute_time is it when it comes to ticks on the Mac. Other calls 38 // with less precision (such as TickCount) just call through to 39 // mach_absolute_time. 40 // 41 // At the time of writing mach_absolute_time returns the number of nanoseconds 42 // since boot. This won't overflow 64bits for 500+ years so we aren't going 43 // to worry about that possiblity 44 return mach_absolute_time(); 45 } 46 47 namespace mozilla { 48 49 double BaseTimeDurationPlatformUtils::ToSeconds(int64_t aTicks) { 50 MOZ_ASSERT(gInitialized, "calling TimeDuration too early"); 51 return (aTicks * sNsPerTickd) / kNsPerSecd; 52 } 53 54 int64_t BaseTimeDurationPlatformUtils::TicksFromMilliseconds( 55 double aMilliseconds) { 56 MOZ_ASSERT(gInitialized, "calling TimeDuration too early"); 57 double result = (aMilliseconds * kNsPerMsd) / sNsPerTickd; 58 // NOTE: this MUST be a >= test, because int64_t(double(INT64_MAX)) 59 // overflows and gives INT64_MIN. 60 if (result >= double(INT64_MAX)) { 61 return INT64_MAX; 62 } else if (result <= double(INT64_MIN)) { 63 return INT64_MIN; 64 } 65 66 return result; 67 } 68 69 void TimeStamp::Startup() { 70 if (gInitialized) { 71 return; 72 } 73 74 mach_timebase_info_data_t timebaseInfo; 75 // Apple's QA1398 suggests that the output from mach_timebase_info 76 // will not change while a program is running, so it should be safe 77 // to cache the result. 78 kern_return_t kr = mach_timebase_info(&timebaseInfo); 79 if (kr != KERN_SUCCESS) { 80 MOZ_RELEASE_ASSERT(false, "mach_timebase_info failed"); 81 } 82 83 sNsPerTickd = double(timebaseInfo.numer) / timebaseInfo.denom; 84 85 gInitialized = true; 86 } 87 88 void TimeStamp::Shutdown() {} 89 90 TimeStamp TimeStamp::Now(bool aHighResolution) { 91 return TimeStamp(ClockTime()); 92 } 93 94 uint64_t TimeStamp::RawMachAbsoluteTimeNanoseconds() const { 95 return static_cast<uint64_t>(double(mValue) * sNsPerTickd); 96 } 97 98 // Computes and returns the process uptime in microseconds. 99 // Returns 0 if an error was encountered. 100 uint64_t TimeStamp::ComputeProcessUptime() { 101 struct timeval tv; 102 int rv = gettimeofday(&tv, nullptr); 103 104 if (rv == -1) { 105 return 0; 106 } 107 108 int mib[] = { 109 CTL_KERN, 110 KERN_PROC, 111 KERN_PROC_PID, 112 getpid(), 113 }; 114 u_int mibLen = sizeof(mib) / sizeof(mib[0]); 115 116 struct kinfo_proc proc; 117 size_t bufferSize = sizeof(proc); 118 rv = sysctl(mib, mibLen, &proc, &bufferSize, nullptr, 0); 119 120 if (rv == -1) { 121 return 0; 122 } 123 124 uint64_t startTime = 125 ((uint64_t)proc.kp_proc.p_un.__p_starttime.tv_sec * kUsPerSec) + 126 proc.kp_proc.p_un.__p_starttime.tv_usec; 127 uint64_t now = (tv.tv_sec * kUsPerSec) + tv.tv_usec; 128 129 if (startTime > now) { 130 return 0; 131 } 132 133 return now - startTime; 134 } 135 136 } // namespace mozilla