Now.cpp (2990B)
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 #include "Now.h" 8 9 #ifdef XP_WIN 10 # include "mozilla/DynamicallyLinkedFunctionPtr.h" 11 #endif // XP_WIN 12 13 #include <stdint.h> 14 15 #include "mozilla/TimeStamp.h" 16 #include "mozilla/Maybe.h" 17 18 namespace mozilla { 19 20 // Apple things 21 #if defined(__APPLE__) && defined(__MACH__) 22 # include <time.h> 23 # include <sys/time.h> 24 # include <sys/types.h> 25 # include <mach/mach_time.h> 26 27 static constexpr uint64_t kNSperMS = 1000000; 28 29 Maybe<uint64_t> NowExcludingSuspendMs() { 30 return Some(clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / kNSperMS); 31 } 32 33 Maybe<uint64_t> NowIncludingSuspendMs() { 34 return Some(clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) / kNSperMS); 35 } 36 37 #elif defined(XP_WIN) 38 39 // Number of hundreds of nanoseconds in a millisecond 40 static constexpr uint64_t kHNSperMS = 10000; 41 42 Maybe<uint64_t> NowExcludingSuspendMs() { 43 ULONGLONG interrupt_time; 44 if (!QueryUnbiasedInterruptTime(&interrupt_time)) { 45 return Nothing(); 46 } 47 return Some(interrupt_time / kHNSperMS); 48 } 49 50 Maybe<uint64_t> NowIncludingSuspendMs() { 51 static const mozilla::StaticDynamicallyLinkedFunctionPtr<void(WINAPI*)( 52 PULONGLONG)> 53 pQueryInterruptTime(L"KernelBase.dll", "QueryInterruptTime"); 54 if (!pQueryInterruptTime) { 55 // On Windows, this does include the time the computer was suspended so it's 56 // an adequate fallback. 57 TimeStamp processCreation = TimeStamp::ProcessCreation(); 58 TimeStamp now = TimeStamp::Now(); 59 if (!processCreation.IsNull() && !now.IsNull()) { 60 return Some(uint64_t((now - processCreation).ToMilliseconds())); 61 } else { 62 return Nothing(); 63 } 64 } 65 ULONGLONG interrupt_time; 66 pQueryInterruptTime(&interrupt_time); 67 return Some(interrupt_time / kHNSperMS); 68 } 69 70 #elif defined(XP_UNIX) // including BSDs and Android 71 # include <time.h> 72 73 // Number of nanoseconds in a millisecond. 74 static constexpr uint64_t kNSperMS = 1000000; 75 76 static uint64_t TimespecToMilliseconds(struct timespec aTs) { 77 return aTs.tv_sec * 1000 + aTs.tv_nsec / kNSperMS; 78 } 79 80 Maybe<uint64_t> NowExcludingSuspendMs() { 81 struct timespec ts = {0}; 82 83 # ifdef XP_OPENBSD 84 if (clock_gettime(CLOCK_UPTIME, &ts)) { 85 # else 86 if (clock_gettime(CLOCK_MONOTONIC, &ts)) { 87 # endif 88 return Nothing(); 89 } 90 return Some(TimespecToMilliseconds(ts)); 91 } 92 93 Maybe<uint64_t> NowIncludingSuspendMs() { 94 # ifndef CLOCK_BOOTTIME 95 return Nothing(); 96 # else 97 struct timespec ts = {0}; 98 99 if (clock_gettime(CLOCK_BOOTTIME, &ts)) { 100 return Nothing(); 101 } 102 return Some(TimespecToMilliseconds(ts)); 103 # endif 104 } 105 106 #else // catch all 107 108 Maybe<uint64_t> NowExcludingSuspendMs() { return Nothing(); } 109 Maybe<uint64_t> NowIncludingSuspendMs() { return Nothing(); } 110 111 #endif 112 113 } // namespace mozilla