Remove base/threading and base/time Change-Id: I6dec7ba59f53e03fc81b877820b9e8fe1fbf6c84 Reviewed-on: https://gn-review.googlesource.com/1721 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/base/files/file.h b/base/files/file.h index e000636..61239ad 100644 --- a/base/files/file.h +++ b/base/files/file.h
@@ -13,8 +13,8 @@ #include "base/files/platform_file.h" #include "base/files/scoped_file.h" #include "base/macros.h" -#include "base/time/time.h" #include "util/build_config.h" +#include "util/ticks.h" #if defined(OS_POSIX) || defined(OS_FUCHSIA) #include <sys/stat.h> @@ -132,13 +132,13 @@ bool is_symbolic_link; // The last modified time of a file. - Time last_modified; + Ticks last_modified; // The last accessed time of a file. - Time last_accessed; + Ticks last_accessed; // The creation time of a file. - Time creation_time; + Ticks creation_time; }; File(); @@ -249,9 +249,6 @@ // 0.01 % > 7.6 seconds bool Flush(); - // Updates the file times. - bool SetTimes(Time last_access_time, Time last_modified_time); - // Returns some basic information for the given file. bool GetInfo(Info* info);
diff --git a/base/files/file_enumerator.h b/base/files/file_enumerator.h index edd5036..81f757b 100644 --- a/base/files/file_enumerator.h +++ b/base/files/file_enumerator.h
@@ -13,8 +13,8 @@ #include "base/containers/stack.h" #include "base/files/file_path.h" #include "base/macros.h" -#include "base/time/time.h" #include "util/build_config.h" +#include "util/ticks.h" #if defined(OS_WIN) #include <windows.h> @@ -52,7 +52,7 @@ FilePath GetName() const; int64_t GetSize() const; - Time GetLastModifiedTime() const; + Ticks GetLastModifiedTime() const; #if defined(OS_WIN) // Note that the cAlternateFileName (used to hold the "short" 8.3 name)
diff --git a/base/files/file_enumerator_posix.cc b/base/files/file_enumerator_posix.cc index 003f045..41d52b8 100644 --- a/base/files/file_enumerator_posix.cc +++ b/base/files/file_enumerator_posix.cc
@@ -49,8 +49,8 @@ return stat_.st_size; } -base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const { - return base::Time::FromTimeT(stat_.st_mtime); +Ticks FileEnumerator::FileInfo::GetLastModifiedTime() const { + return stat_.st_mtime; } // FileEnumerator --------------------------------------------------------------
diff --git a/base/files/file_enumerator_win.cc b/base/files/file_enumerator_win.cc index a2bfabf..803b7bd 100644 --- a/base/files/file_enumerator_win.cc +++ b/base/files/file_enumerator_win.cc
@@ -54,8 +54,8 @@ return static_cast<int64_t>(size.QuadPart); } -base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const { - return base::Time::FromFileTime(find_data_.ftLastWriteTime); +Ticks FileEnumerator::FileInfo::GetLastModifiedTime() const { + return *reinterpret_cast<const uint64_t*>(&find_data_.ftLastWriteTime); } // FileEnumerator --------------------------------------------------------------
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc index c4f1080..977eb1b 100644 --- a/base/files/file_posix.cc +++ b/base/files/file_posix.cc
@@ -46,23 +46,6 @@ return HANDLE_EINTR(ftruncate(file, length)); } -int CallFutimes(PlatformFile file, const struct timeval times[2]) { -#ifdef __USE_XOPEN2K8 - // futimens should be available, but futimes might not be - // http://pubs.opengroup.org/onlinepubs/9699919799/ - - timespec ts_times[2]; - ts_times[0].tv_sec = times[0].tv_sec; - ts_times[0].tv_nsec = times[0].tv_usec * 1000; - ts_times[1].tv_sec = times[1].tv_sec; - ts_times[1].tv_nsec = times[1].tv_usec * 1000; - - return futimens(file, ts_times); -#else - return futimes(file, times); -#endif -} - #if !defined(OS_FUCHSIA) File::Error CallFcntlFlock(PlatformFile file, bool do_lock) { struct flock lock; @@ -90,11 +73,6 @@ return 0; } -int CallFutimes(PlatformFile file, const struct timeval times[2]) { - NOTIMPLEMENTED(); // NaCl doesn't implement futimes. - return 0; -} - File::Error CallFcntlFlock(PlatformFile file, bool do_lock) { NOTIMPLEMENTED(); // NaCl doesn't implement flock struct. return File::FILE_ERROR_INVALID_OPERATION; @@ -126,17 +104,10 @@ #error #endif - last_modified = Time::FromTimeT(last_modified_sec) + - TimeDelta::FromMicroseconds(last_modified_nsec / - Time::kNanosecondsPerMicrosecond); - - last_accessed = Time::FromTimeT(last_accessed_sec) + - TimeDelta::FromMicroseconds(last_accessed_nsec / - Time::kNanosecondsPerMicrosecond); - - creation_time = Time::FromTimeT(creation_time_sec) + - TimeDelta::FromMicroseconds(creation_time_nsec / - Time::kNanosecondsPerMicrosecond); + constexpr uint64_t kNano = 1'000'000'000; + last_modified = last_modified_sec * kNano + last_modified_nsec; + last_accessed = last_accessed_sec * kNano + last_accessed_nsec; + creation_time = creation_time_sec * kNano + creation_time_nsec; } bool File::IsValid() const { @@ -281,16 +252,6 @@ return !CallFtruncate(file_.get(), length); } -bool File::SetTimes(Time last_access_time, Time last_modified_time) { - DCHECK(IsValid()); - - timeval times[2]; - times[0] = last_access_time.ToTimeVal(); - times[1] = last_modified_time.ToTimeVal(); - - return !CallFutimes(file_.get(), times); -} - bool File::GetInfo(Info* info) { DCHECK(IsValid());
diff --git a/base/files/file_util.cc b/base/files/file_util.cc index 674dd27..d087b00 100644 --- a/base/files/file_util.cc +++ b/base/files/file_util.cc
@@ -218,23 +218,6 @@ return true; } -bool TouchFile(const FilePath& path, - const Time& last_accessed, - const Time& last_modified) { - int flags = File::FLAG_OPEN | File::FLAG_WRITE_ATTRIBUTES; - -#if defined(OS_WIN) - // On Windows, FILE_FLAG_BACKUP_SEMANTICS is needed to open a directory. - if (DirectoryExists(path)) - flags |= File::FLAG_BACKUP_SEMANTICS; -#endif // OS_WIN - - File file(path, flags); - if (!file.IsValid()) - return false; - - return file.SetTimes(last_accessed, last_modified); -} #endif // !defined(OS_NACL_NONSFI) bool CloseFile(FILE* file) {
diff --git a/base/files/file_util.h b/base/files/file_util.h index 90f9cd6..bfcac01 100644 --- a/base/files/file_util.h +++ b/base/files/file_util.h
@@ -36,7 +36,6 @@ namespace base { class Environment; -class Time; //----------------------------------------------------------------------------- // Functions that involve filesystem access or modification: @@ -322,11 +321,6 @@ // Returns information about the given file path. bool GetFileInfo(const FilePath& file_path, File::Info* info); -// Sets the time of the last access and the time of the last modification. -bool TouchFile(const FilePath& path, - const Time& last_accessed, - const Time& last_modified); - // Wrapper for fopen-like calls. Returns non-NULL FILE* on success. The // underlying file descriptor (POSIX) or handle (Windows) is unconditionally // configured to not be propagated to child processes.
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc index 4c1360f..9415735 100644 --- a/base/files/file_util_posix.cc +++ b/base/files/file_util_posix.cc
@@ -36,7 +36,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" #include "util/build_config.h" #if defined(OS_MACOSX)
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc index 9133d7e..2a1e9ec 100644 --- a/base/files/file_util_win.cc +++ b/base/files/file_util_win.cc
@@ -28,7 +28,6 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" #include "base/win/scoped_handle.h" // #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the @@ -704,9 +703,9 @@ results->is_directory = (attr.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - results->last_modified = Time::FromFileTime(attr.ftLastWriteTime); - results->last_accessed = Time::FromFileTime(attr.ftLastAccessTime); - results->creation_time = Time::FromFileTime(attr.ftCreationTime); + results->last_modified = *reinterpret_cast<uint64_t*>(&attr.ftLastWriteTime); + results->last_accessed = *reinterpret_cast<uint64_t*>(&attr.ftLastAccessTime); + results->creation_time = *reinterpret_cast<uint64_t*>(&attr.ftCreationTime); return true; }
diff --git a/base/files/file_win.cc b/base/files/file_win.cc index 401ac33..7ca4461 100644 --- a/base/files/file_win.cc +++ b/base/files/file_win.cc
@@ -169,15 +169,6 @@ FALSE)); } -bool File::SetTimes(Time last_access_time, Time last_modified_time) { - DCHECK(IsValid()); - - FILETIME last_access_filetime = last_access_time.ToFileTime(); - FILETIME last_modified_filetime = last_modified_time.ToFileTime(); - return (::SetFileTime(file_.Get(), NULL, &last_access_filetime, - &last_modified_filetime) != FALSE); -} - bool File::GetInfo(Info* info) { DCHECK(IsValid()); @@ -192,9 +183,11 @@ info->is_directory = (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; info->is_symbolic_link = false; // Windows doesn't have symbolic links. - info->last_modified = Time::FromFileTime(file_info.ftLastWriteTime); - info->last_accessed = Time::FromFileTime(file_info.ftLastAccessTime); - info->creation_time = Time::FromFileTime(file_info.ftCreationTime); + info->last_modified = + *reinterpret_cast<uint64_t*>(&file_info.ftLastWriteTime); + info->last_accessed = + *reinterpret_cast<uint64_t*>(&file_info.ftLastAccessTime); + info->creation_time = *reinterpret_cast<uint64_t*>(&file_info.ftCreationTime); return true; }
diff --git a/base/json/json_perftest.cc b/base/json/json_perftest.cc deleted file mode 100644 index fc05bdc..0000000 --- a/base/json/json_perftest.cc +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/memory/ptr_util.h" -#include "base/time/time.h" -#include "base/values.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/perf/perf_test.h" - -namespace base { - -namespace { -// Generates a simple dictionary value with simple data types, a string and a -// list. -std::unique_ptr<DictionaryValue> GenerateDict() { - auto root = std::make_unique<DictionaryValue>(); - root->SetDouble("Double", 3.141); - root->SetBoolean("Bool", true); - root->SetInteger("Int", 42); - root->SetString("String", "Foo"); - - auto list = std::make_unique<ListValue>(); - list->Set(0, std::make_unique<Value>(2.718)); - list->Set(1, std::make_unique<Value>(false)); - list->Set(2, std::make_unique<Value>(123)); - list->Set(3, std::make_unique<Value>("Bar")); - root->Set("List", std::move(list)); - - return root; -} - -// Generates a tree-like dictionary value with a size of O(breadth ** depth). -std::unique_ptr<DictionaryValue> GenerateLayeredDict(int breadth, int depth) { - if (depth == 1) - return GenerateDict(); - - auto root = GenerateDict(); - auto next = GenerateLayeredDict(breadth, depth - 1); - - for (int i = 0; i < breadth; ++i) { - root->Set("Dict" + std::to_string(i), next->CreateDeepCopy()); - } - - return root; -} - -} // namespace - -class JSONPerfTest : public testing::Test { - public: - void TestWriteAndRead(int breadth, int depth) { - std::string description = "Breadth: " + std::to_string(breadth) + - ", Depth: " + std::to_string(depth); - auto dict = GenerateLayeredDict(breadth, depth); - std::string json; - - TimeTicks start_write = TimeTicks::Now(); - JSONWriter::Write(*dict, &json); - TimeTicks end_write = TimeTicks::Now(); - perf_test::PrintResult("Write", "", description, - (end_write - start_write).InMillisecondsF(), "ms", - true); - - TimeTicks start_read = TimeTicks::Now(); - JSONReader::Read(json); - TimeTicks end_read = TimeTicks::Now(); - perf_test::PrintResult("Read", "", description, - (end_read - start_read).InMillisecondsF(), "ms", - true); - } -}; - -TEST_F(JSONPerfTest, StressTest) { - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 12; ++j) { - TestWriteAndRead(i + 1, j + 1); - } - } -} - -} // namespace base
diff --git a/base/logging.cc b/base/logging.cc index f0ce6f5..c381a28 100644 --- a/base/logging.cc +++ b/base/logging.cc
@@ -7,6 +7,8 @@ #include <limits.h> #include <stdint.h> +#include <thread> + #include "base/macros.h" #include "util/build_config.h" @@ -19,6 +21,7 @@ #define STDERR_FILENO 2 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <sys/time.h> #include <time.h> #endif @@ -49,7 +52,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/platform_thread.h" #if defined(OS_POSIX) || defined(OS_FUCHSIA) #include "base/posix/safe_strerror.h" @@ -195,7 +197,7 @@ // TODO(darin): It might be nice if the columns were fixed width. stream_ << '['; - stream_ << base::PlatformThread::CurrentId() << ':'; + stream_ << std::this_thread::get_id() << ':'; #if defined(OS_WIN) SYSTEMTIME local_time; GetLocalTime(&local_time);
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h deleted file mode 100644 index 8b814c5..0000000 --- a/base/threading/platform_thread.h +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// WARNING: You should *NOT* be using this class directly. PlatformThread is -// the low-level platform-specific abstraction to the OS's threading interface. -// You should instead be using a message-loop driven Thread, see thread.h. - -#ifndef BASE_THREADING_PLATFORM_THREAD_H_ -#define BASE_THREADING_PLATFORM_THREAD_H_ - -#include <stddef.h> - -#include "base/macros.h" -#include "base/time/time.h" -#include "util/build_config.h" - -#if defined(OS_WIN) -#include "base/win/windows_types.h" -#elif defined(OS_MACOSX) -#include <mach/mach_types.h> -#elif defined(OS_POSIX) -#include <pthread.h> -#include <unistd.h> -#endif - -namespace base { - -// Used for logging. Always an integer value. -#if defined(OS_WIN) -typedef DWORD PlatformThreadId; -#elif defined(OS_MACOSX) -typedef mach_port_t PlatformThreadId; -#elif defined(OS_POSIX) -typedef pid_t PlatformThreadId; -#endif - -// Used for thread checking and debugging. -// Meant to be as fast as possible. -// These are produced by PlatformThread::CurrentRef(), and used to later -// check if we are on the same thread or not by using ==. These are safe -// to copy between threads, but can't be copied to another process as they -// have no meaning there. Also, the internal identifier can be re-used -// after a thread dies, so a PlatformThreadRef cannot be reliably used -// to distinguish a new thread from an old, dead thread. -class PlatformThreadRef { - public: -#if defined(OS_WIN) - typedef DWORD RefType; -#else // OS_POSIX - typedef pthread_t RefType; -#endif - constexpr PlatformThreadRef() : id_(0) {} - - explicit constexpr PlatformThreadRef(RefType id) : id_(id) {} - - bool operator==(PlatformThreadRef other) const { return id_ == other.id_; } - - bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; } - - bool is_null() const { return id_ == 0; } - - private: - RefType id_; -}; - -// Used to operate on threads. -class PlatformThreadHandle { - public: -#if defined(OS_WIN) - typedef void* Handle; -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) - typedef pthread_t Handle; -#endif - - constexpr PlatformThreadHandle() : handle_(0) {} - - explicit constexpr PlatformThreadHandle(Handle handle) : handle_(handle) {} - - bool is_equal(const PlatformThreadHandle& other) const { - return handle_ == other.handle_; - } - - bool is_null() const { return !handle_; } - - Handle platform_handle() const { return handle_; } - - private: - Handle handle_; -}; - -const PlatformThreadId kInvalidThreadId(0); - -// A namespace for low-level thread functions. -class PlatformThread { - public: - // Implement this interface to run code on a background thread. Your - // ThreadMain method will be called on the newly created thread. - class Delegate { - public: - virtual void ThreadMain() = 0; - - protected: - virtual ~Delegate() = default; - }; - - // Gets the current thread id, which may be useful for logging purposes. - static PlatformThreadId CurrentId(); - - // Gets the current thread reference, which can be used to check if - // we're on the right thread quickly. - static PlatformThreadRef CurrentRef(); - - // Get the handle representing the current thread. On Windows, this is a - // pseudo handle constant which will always represent the thread using it and - // hence should not be shared with other threads nor be used to differentiate - // the current thread from another. - static PlatformThreadHandle CurrentHandle(); - - // Yield the current thread so another thread can be scheduled. - static void YieldCurrentThread(); - - // Sleeps for the specified duration. - static void Sleep(base::TimeDelta duration); - - // Creates a new thread. The |stack_size| parameter can be 0 to indicate - // that the default stack size should be used. Upon success, - // |*thread_handle| will be assigned a handle to the newly created thread, - // and |delegate|'s ThreadMain method will be executed on the newly created - // thread. - // NOTE: When you are done with the thread handle, you must call Join to - // release system resources associated with the thread. You must ensure that - // the Delegate object outlives the thread. - static bool Create(size_t stack_size, - Delegate* delegate, - PlatformThreadHandle* thread_handle); - - // CreateNonJoinable() does the same thing as Create() except the thread - // cannot be Join()'d. Therefore, it also does not output a - // PlatformThreadHandle. - static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); - - // Joins with a thread created via the Create function. This function blocks - // the caller until the designated thread exits. This will invalidate - // |thread_handle|. - static void Join(PlatformThreadHandle thread_handle); - - // Detaches and releases the thread handle. The thread is no longer joinable - // and |thread_handle| is invalidated after this call. - static void Detach(PlatformThreadHandle thread_handle); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); -}; - -} // namespace base - -#endif // BASE_THREADING_PLATFORM_THREAD_H_
diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc deleted file mode 100644 index 1833c54..0000000 --- a/base/threading/platform_thread_linux.cc +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include <errno.h> -#include <sched.h> -#include <stddef.h> - -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "util/build_config.h" - -#if !defined(OS_NACL) && !defined(OS_AIX) -#include <pthread.h> -#include <sys/prctl.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#endif - -namespace base { - -void InitThreading() {} - -void TerminateOnThread() {} - -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { -#if !defined(THREAD_SANITIZER) - return 0; -#else - // ThreadSanitizer bloats the stack heavily. Evidence has been that the - // default stack size isn't enough for some browser tests. - return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). -#endif -} - -} // namespace base
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm deleted file mode 100644 index 770b618..0000000 --- a/base/threading/platform_thread_mac.mm +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#import <Foundation/Foundation.h> -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <mach/thread_policy.h> -#include <stddef.h> -#include <sys/resource.h> - -#include <algorithm> - -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/mac/mach_logging.h" -#include "util/build_config.h" - -namespace base { - -namespace { -NSString* const kThreadPriorityKey = @"CrThreadPriorityKey"; -} // namespace - -// If Cocoa is to be used on more than one thread, it must know that the -// application is multithreaded. Since it's possible to enter Cocoa code -// from threads created by pthread_thread_create, Cocoa won't necessarily -// be aware that the application is multithreaded. Spawning an NSThread is -// enough to get Cocoa to set up for multithreaded operation, so this is done -// if necessary before pthread_thread_create spawns any threads. -// -// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html -void InitThreading() { - static BOOL multithreaded = [NSThread isMultiThreaded]; - if (!multithreaded) { - // +[NSObject class] is idempotent. - [NSThread detachNewThreadSelector:@selector(class) - toTarget:[NSObject class] - withObject:nil]; - multithreaded = YES; - - DCHECK([NSThread isMultiThreaded]); - } -} - -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { -#if defined(OS_IOS) - return 0; -#else - // The Mac OS X default for a pthread stack size is 512kB. - // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses - // DEFAULT_STACK_SIZE for this purpose. - // - // 512kB isn't quite generous enough for some deeply recursive threads that - // otherwise request the default stack size by specifying 0. Here, adopt - // glibc's behavior as on Linux, which is to use the current stack size - // limit (ulimit -s) as the default stack size. See - // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To - // avoid setting the limit below the Mac OS X default or the minimum usable - // stack size, these values are also considered. If any of these values - // can't be determined, or if stack size is unlimited (ulimit -s unlimited), - // stack_size is left at 0 to get the system default. - // - // Mac OS X normally only applies ulimit -s to the main thread stack. On - // contemporary OS X and Linux systems alike, this value is generally 8MB - // or in that neighborhood. - size_t default_stack_size = 0; - struct rlimit stack_rlimit; - if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 && - getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 && - stack_rlimit.rlim_cur != RLIM_INFINITY) { - default_stack_size = std::max( - std::max(default_stack_size, static_cast<size_t>(PTHREAD_STACK_MIN)), - static_cast<size_t>(stack_rlimit.rlim_cur)); - } - return default_stack_size; -#endif -} - -void TerminateOnThread() {} - -} // namespace base
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc deleted file mode 100644 index 42fbce5..0000000 --- a/base/threading/platform_thread_posix.cc +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include <errno.h> -#include <pthread.h> -#include <sched.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> - -#include <memory> - -#include "base/logging.h" -#include "util/build_config.h" - -#if defined(OS_LINUX) -#include <sys/syscall.h> -#endif - -#include <sys/resource.h> - -namespace base { - -void InitThreading(); -void TerminateOnThread(); -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes); - -namespace { - -struct ThreadParams { - ThreadParams() : delegate(nullptr), joinable(false) {} - - PlatformThread::Delegate* delegate; - bool joinable; -}; - -void* ThreadFunc(void* params) { - PlatformThread::Delegate* delegate = nullptr; - - { - std::unique_ptr<ThreadParams> thread_params( - static_cast<ThreadParams*>(params)); - - delegate = thread_params->delegate; - } - - delegate->ThreadMain(); - - base::TerminateOnThread(); - return nullptr; -} - -bool CreateThread(size_t stack_size, - bool joinable, - PlatformThread::Delegate* delegate, - PlatformThreadHandle* thread_handle) { - DCHECK(thread_handle); - base::InitThreading(); - - pthread_attr_t attributes; - pthread_attr_init(&attributes); - - // Pthreads are joinable by default, so only specify the detached - // attribute if the thread should be non-joinable. - if (!joinable) - pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); - - // Get a better default if available. - if (stack_size == 0) - stack_size = base::GetDefaultThreadStackSize(attributes); - - if (stack_size > 0) - pthread_attr_setstacksize(&attributes, stack_size); - - std::unique_ptr<ThreadParams> params(new ThreadParams); - params->delegate = delegate; - params->joinable = joinable; - - pthread_t handle; - int err = pthread_create(&handle, &attributes, ThreadFunc, params.get()); - bool success = !err; - if (success) { - // ThreadParams should be deleted on the created thread after used. - ignore_result(params.release()); - } else { - // Value of |handle| is undefined if pthread_create fails. - handle = 0; - errno = err; - PLOG(ERROR) << "pthread_create"; - } - *thread_handle = PlatformThreadHandle(handle); - - pthread_attr_destroy(&attributes); - - return success; -} - -} // namespace - -// static -PlatformThreadId PlatformThread::CurrentId() { -// Pthreads doesn't have the concept of a thread ID, so we have to reach down -// into the kernel. -#if defined(OS_MACOSX) - return pthread_mach_thread_np(pthread_self()); -#elif defined(OS_LINUX) - return syscall(__NR_gettid); -#else -#error -#endif -} - -// static -PlatformThreadRef PlatformThread::CurrentRef() { - return PlatformThreadRef(pthread_self()); -} - -// static -PlatformThreadHandle PlatformThread::CurrentHandle() { - return PlatformThreadHandle(pthread_self()); -} - -// static -void PlatformThread::YieldCurrentThread() { - sched_yield(); -} - -// static -void PlatformThread::Sleep(TimeDelta duration) { - struct timespec sleep_time, remaining; - - // Break the duration into seconds and nanoseconds. - // NOTE: TimeDelta's microseconds are int64s while timespec's - // nanoseconds are longs, so this unpacking must prevent overflow. - sleep_time.tv_sec = duration.InSeconds(); - duration -= TimeDelta::FromSeconds(sleep_time.tv_sec); - sleep_time.tv_nsec = duration.InMicroseconds() * 1000; // nanoseconds - - while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) - sleep_time = remaining; -} - -// static -bool PlatformThread::Create(size_t stack_size, - Delegate* delegate, - PlatformThreadHandle* thread_handle) { - return CreateThread(stack_size, true /* joinable thread */, delegate, - thread_handle); -} - -// static -bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { - PlatformThreadHandle unused; - - bool result = CreateThread(stack_size, false /* non-joinable thread */, - delegate, &unused); - return result; -} - -// static -void PlatformThread::Join(PlatformThreadHandle thread_handle) { - CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), nullptr)); -} - -// static -void PlatformThread::Detach(PlatformThreadHandle thread_handle) { - CHECK_EQ(0, pthread_detach(thread_handle.platform_handle())); -} - -} // namespace base
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc deleted file mode 100644 index 349a6cf..0000000 --- a/base/threading/platform_thread_win.cc +++ /dev/null
@@ -1,189 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/scoped_handle.h" - -#include <windows.h> - -namespace base { - -namespace { - -// The information on how to set the thread name comes from -// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx -const DWORD kVCThreadNameException = 0x406D1388; - -typedef struct tagTHREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. -} THREADNAME_INFO; - -// The SetThreadDescription API was brought in version 1607 of Windows 10. -typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, - PCWSTR lpThreadDescription); - -// This function has try handling, so it is separated out of its caller. -void SetNameInternal(PlatformThreadId thread_id, const char* name) { - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = thread_id; - info.dwFlags = 0; - - __try { - RaiseException(kVCThreadNameException, 0, sizeof(info) / sizeof(DWORD), - reinterpret_cast<DWORD_PTR*>(&info)); - } __except (EXCEPTION_CONTINUE_EXECUTION) { - } -} - -struct ThreadParams { - PlatformThread::Delegate* delegate; - bool joinable; -}; - -DWORD __stdcall ThreadFunc(void* params) { - ThreadParams* thread_params = static_cast<ThreadParams*>(params); - PlatformThread::Delegate* delegate = thread_params->delegate; - - // Retrieve a copy of the thread handle to use as the key in the - // thread name mapping. - PlatformThreadHandle::Handle platform_handle; - BOOL did_dup = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &platform_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS); - - win::ScopedHandle scoped_platform_handle; - - if (did_dup) { - scoped_platform_handle.Set(platform_handle); - } - - delete thread_params; - delegate->ThreadMain(); - - return 0; -} - -// CreateThreadInternal() matches PlatformThread::CreateWithPriority(), except -// that |out_thread_handle| may be nullptr, in which case a non-joinable thread -// is created. -bool CreateThreadInternal(size_t stack_size, - PlatformThread::Delegate* delegate, - PlatformThreadHandle* out_thread_handle) { - unsigned int flags = 0; - if (stack_size > 0) { - flags = STACK_SIZE_PARAM_IS_A_RESERVATION; - } - - ThreadParams* params = new ThreadParams; - params->delegate = delegate; - params->joinable = out_thread_handle != nullptr; - - void* thread_handle; - { - // Using CreateThread here vs _beginthreadex makes thread creation a bit - // faster and doesn't require the loader lock to be available. Our code - // will have to work running on CreateThread() threads anyway, since we run - // code on the Windows thread pool, etc. For some background on the - // difference: - // http://www.microsoft.com/msj/1099/win32/win321099.aspx - thread_handle = - ::CreateThread(nullptr, stack_size, ThreadFunc, params, flags, nullptr); - } - - if (!thread_handle) { - delete params; - return false; - } - - if (out_thread_handle) - *out_thread_handle = PlatformThreadHandle(thread_handle); - else - CloseHandle(thread_handle); - return true; -} - -} // namespace - -// static -PlatformThreadId PlatformThread::CurrentId() { - return ::GetCurrentThreadId(); -} - -// static -PlatformThreadRef PlatformThread::CurrentRef() { - return PlatformThreadRef(::GetCurrentThreadId()); -} - -// static -PlatformThreadHandle PlatformThread::CurrentHandle() { - return PlatformThreadHandle(::GetCurrentThread()); -} - -// static -void PlatformThread::YieldCurrentThread() { - ::Sleep(0); -} - -// static -void PlatformThread::Sleep(TimeDelta duration) { - // When measured with a high resolution clock, Sleep() sometimes returns much - // too early. We may need to call it repeatedly to get the desired duration. - TimeTicks end = TimeTicks::Now() + duration; - for (TimeTicks now = TimeTicks::Now(); now < end; now = TimeTicks::Now()) - ::Sleep(static_cast<DWORD>((end - now).InMillisecondsRoundedUp())); -} - -// static -bool PlatformThread::Create(size_t stack_size, - Delegate* delegate, - PlatformThreadHandle* thread_handle) { - DCHECK(thread_handle); - return CreateThreadInternal(stack_size, delegate, thread_handle); -} - -// static -bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { - return CreateThreadInternal(stack_size, delegate, nullptr /* non-joinable */ - ); -} - -// static -void PlatformThread::Join(PlatformThreadHandle thread_handle) { - DCHECK(thread_handle.platform_handle()); - // TODO(willchan): Enable this check once I can get it to work for Windows - // shutdown. - // Joining another thread may block the current thread for a long time, since - // the thread referred to by |thread_handle| may still be running long-lived / - // blocking tasks. - // AssertBlockingAllowed(); - - DWORD thread_id = 0; - thread_id = ::GetThreadId(thread_handle.platform_handle()); - DWORD last_error = 0; - if (!thread_id) - last_error = ::GetLastError(); - - // Wait for the thread to exit. It should already have terminated but make - // sure this assumption is valid. - CHECK_EQ(WAIT_OBJECT_0, - WaitForSingleObject(thread_handle.platform_handle(), INFINITE)); - CloseHandle(thread_handle.platform_handle()); -} - -// static -void PlatformThread::Detach(PlatformThreadHandle thread_handle) { - CloseHandle(thread_handle.platform_handle()); -} - -} // namespace base
diff --git a/base/time/clock.cc b/base/time/clock.cc deleted file mode 100644 index 9e3f271..0000000 --- a/base/time/clock.cc +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/clock.h" - -namespace base { - -Clock::~Clock() = default; - -} // namespace base
diff --git a/base/time/clock.h b/base/time/clock.h deleted file mode 100644 index 8f3a27f..0000000 --- a/base/time/clock.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TIME_CLOCK_H_ -#define BASE_TIME_CLOCK_H_ - -#include "base/time/time.h" - -namespace base { - -// A Clock is an interface for objects that vend Times. It is -// intended to be able to test the behavior of classes with respect to -// time. -// -// See DefaultClock (base/time/default_clock.h) for the default -// implementation that simply uses Time::Now(). -// -// (An implementation that uses Time::SystemTime() should be added as -// needed.) -// -// See SimpleTestClock (base/test/simple_test_clock.h) for a simple -// test implementation. -// -// See TickClock (base/time/tick_clock.h) for the equivalent interface for -// TimeTicks. -class Clock { - public: - virtual ~Clock(); - - // Now() must be safe to call from any thread. The caller cannot - // make any ordering assumptions about the returned Time. For - // example, the system clock may change to an earlier time. - virtual Time Now() const = 0; -}; - -} // namespace base - -#endif // BASE_TIME_CLOCK_H_
diff --git a/base/time/time.cc b/base/time/time.cc deleted file mode 100644 index 13b2343..0000000 --- a/base/time/time.cc +++ /dev/null
@@ -1,339 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time.h" - -#include <cmath> -#include <ios> -#include <limits> -#include <ostream> -#include <sstream> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/no_destructor.h" -#include "base/strings/stringprintf.h" -#include "base/time/time_override.h" -#include "util/build_config.h" - -namespace base { - -namespace internal { - -TimeNowFunction g_time_now_function = &subtle::TimeNowIgnoringOverride; - -TimeNowFunction g_time_now_from_system_time_function = - &subtle::TimeNowFromSystemTimeIgnoringOverride; - -TimeTicksNowFunction g_time_ticks_now_function = - &subtle::TimeTicksNowIgnoringOverride; - -ThreadTicksNowFunction g_thread_ticks_now_function = - &subtle::ThreadTicksNowIgnoringOverride; - -} // namespace internal - -// TimeDelta ------------------------------------------------------------------ - -int TimeDelta::InDays() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int>::max(); - } - return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); -} - -int TimeDelta::InHours() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int>::max(); - } - return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); -} - -int TimeDelta::InMinutes() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int>::max(); - } - return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute); -} - -double TimeDelta::InSecondsF() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; -} - -int64_t TimeDelta::InSeconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_ / Time::kMicrosecondsPerSecond; -} - -double TimeDelta::InMillisecondsF() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; -} - -int64_t TimeDelta::InMilliseconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_ / Time::kMicrosecondsPerMillisecond; -} - -int64_t TimeDelta::InMillisecondsRoundedUp() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / - Time::kMicrosecondsPerMillisecond; -} - -int64_t TimeDelta::InMicroseconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_; -} - -double TimeDelta::InMicrosecondsF() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return static_cast<double>(delta_); -} - -int64_t TimeDelta::InNanoseconds() const { - if (is_max()) { - // Preserve max to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return delta_ * Time::kNanosecondsPerMicrosecond; -} - -namespace time_internal { - -int64_t SaturatedAdd(TimeDelta delta, int64_t value) { - CheckedNumeric<int64_t> rv(delta.delta_); - rv += value; - if (rv.IsValid()) - return rv.ValueOrDie(); - // Positive RHS overflows. Negative RHS underflows. - if (value < 0) - return std::numeric_limits<int64_t>::min(); - return std::numeric_limits<int64_t>::max(); -} - -int64_t SaturatedSub(TimeDelta delta, int64_t value) { - CheckedNumeric<int64_t> rv(delta.delta_); - rv -= value; - if (rv.IsValid()) - return rv.ValueOrDie(); - // Negative RHS overflows. Positive RHS underflows. - if (value < 0) - return std::numeric_limits<int64_t>::max(); - return std::numeric_limits<int64_t>::min(); -} - -} // namespace time_internal - -std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { - return os << time_delta.InSecondsF() << " s"; -} - -// Time ----------------------------------------------------------------------- - -// static -Time Time::Now() { - return internal::g_time_now_function(); -} - -// static -Time Time::NowFromSystemTime() { - // Just use g_time_now_function because it returns the system time. - return internal::g_time_now_from_system_time_function(); -} - -// static -Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) { - return Time(delta.InMicroseconds()); -} - -TimeDelta Time::ToDeltaSinceWindowsEpoch() const { - return TimeDelta::FromMicroseconds(us_); -} - -// static -Time Time::FromTimeT(time_t tt) { - if (tt == 0) - return Time(); // Preserve 0 so we can tell it doesn't exist. - if (tt == std::numeric_limits<time_t>::max()) - return Max(); - return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt); -} - -time_t Time::ToTimeT() const { - if (is_null()) - return 0; // Preserve 0 so we can tell it doesn't exist. - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<time_t>::max(); - } - if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) { - DLOG(WARNING) << "Overflow when converting base::Time with internal " - << "value " << us_ << " to time_t."; - return std::numeric_limits<time_t>::max(); - } - return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; -} - -// static -Time Time::FromDoubleT(double dt) { - if (dt == 0 || std::isnan(dt)) - return Time(); // Preserve 0 so we can tell it doesn't exist. - return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt); -} - -double Time::ToDoubleT() const { - if (is_null()) - return 0; // Preserve 0 so we can tell it doesn't exist. - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / - static_cast<double>(kMicrosecondsPerSecond)); -} - -#if defined(OS_POSIX) -// static -Time Time::FromTimeSpec(const timespec& ts) { - return FromDoubleT(ts.tv_sec + static_cast<double>(ts.tv_nsec) / - base::Time::kNanosecondsPerSecond); -} -#endif - -// static -Time Time::FromJsTime(double ms_since_epoch) { - // The epoch is a valid time, so this constructor doesn't interpret - // 0 as the null time. - return Time(kTimeTToMicrosecondsOffset) + - TimeDelta::FromMillisecondsD(ms_since_epoch); -} - -double Time::ToJsTime() const { - if (is_null()) { - // Preserve 0 so the invalid result doesn't depend on the platform. - return 0; - } - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<double>::infinity(); - } - return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / - kMicrosecondsPerMillisecond); -} - -Time Time::FromJavaTime(int64_t ms_since_epoch) { - return base::Time::UnixEpoch() + - base::TimeDelta::FromMilliseconds(ms_since_epoch); -} - -int64_t Time::ToJavaTime() const { - if (is_null()) { - // Preserve 0 so the invalid result doesn't depend on the platform. - return 0; - } - if (is_max()) { - // Preserve max without offset to prevent overflow. - return std::numeric_limits<int64_t>::max(); - } - return ((us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerMillisecond); -} - -// static -Time Time::UnixEpoch() { - Time time; - time.us_ = kTimeTToMicrosecondsOffset; - return time; -} - -// TimeTicks ------------------------------------------------------------------ - -// static -TimeTicks TimeTicks::Now() { - return internal::g_time_ticks_now_function(); -} - -// static -TimeTicks TimeTicks::UnixEpoch() { - static const base::NoDestructor<base::TimeTicks> epoch([]() { - return subtle::TimeTicksNowIgnoringOverride() - - (subtle::TimeNowIgnoringOverride() - Time::UnixEpoch()); - }()); - return *epoch; -} - -TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase, - TimeDelta tick_interval) const { - // |interval_offset| is the offset from |this| to the next multiple of - // |tick_interval| after |tick_phase|, possibly negative if in the past. - TimeDelta interval_offset = (tick_phase - *this) % tick_interval; - // If |this| is exactly on the interval (i.e. offset==0), don't adjust. - // Otherwise, if |tick_phase| was in the past, adjust forward to the next - // tick after |this|. - if (!interval_offset.is_zero() && tick_phase < *this) - interval_offset += tick_interval; - return *this + interval_offset; -} - -std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) { - // This function formats a TimeTicks object as "bogo-microseconds". - // The origin and granularity of the count are platform-specific, and may very - // from run to run. Although bogo-microseconds usually roughly correspond to - // real microseconds, the only real guarantee is that the number never goes - // down during a single run. - const TimeDelta as_time_delta = time_ticks - TimeTicks(); - return os << as_time_delta.InMicroseconds() << " bogo-microseconds"; -} - -// ThreadTicks ---------------------------------------------------------------- - -// static -ThreadTicks ThreadTicks::Now() { - return internal::g_thread_ticks_now_function(); -} - -std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) { - const TimeDelta as_time_delta = thread_ticks - ThreadTicks(); - return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds"; -} - -// Time::Exploded ------------------------------------------------------------- - -inline bool is_in_range(int value, int lo, int hi) { - return lo <= value && value <= hi; -} - -bool Time::Exploded::HasValidValues() const { - return is_in_range(month, 1, 12) && is_in_range(day_of_week, 0, 6) && - is_in_range(day_of_month, 1, 31) && is_in_range(hour, 0, 23) && - is_in_range(minute, 0, 59) && is_in_range(second, 0, 60) && - is_in_range(millisecond, 0, 999); -} - -} // namespace base
diff --git a/base/time/time.h b/base/time/time.h deleted file mode 100644 index 47d7536..0000000 --- a/base/time/time.h +++ /dev/null
@@ -1,871 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Time represents an absolute point in coordinated universal time (UTC), -// internally represented as microseconds (s/1,000,000) since the Windows epoch -// (1601-01-01 00:00:00 UTC). System-dependent clock interface routines are -// defined in time_PLATFORM.cc. Note that values for Time may skew and jump -// around as the operating system makes adjustments to synchronize (e.g., with -// NTP servers). Thus, client code that uses the Time class must account for -// this. -// -// TimeDelta represents a duration of time, internally represented in -// microseconds. -// -// TimeTicks and ThreadTicks represent an abstract time that is most of the time -// incrementing, for use in measuring time durations. Internally, they are -// represented in microseconds. They cannot be converted to a human-readable -// time, but are guaranteed not to decrease (unlike the Time class). Note that -// TimeTicks may "stand still" (e.g., if the computer is suspended), and -// ThreadTicks will "stand still" whenever the thread has been de-scheduled by -// the operating system. -// -// All time classes are copyable, assignable, and occupy 64-bits per instance. -// As a result, prefer passing them by value: -// void MyFunction(TimeDelta arg); -// If circumstances require, you may also pass by const reference: -// void MyFunction(const TimeDelta& arg); // Not preferred. -// -// Definitions of operator<< are provided to make these types work with -// DCHECK_EQ() and other log macros. For human-readable formatting, see -// "base/i18n/time_formatting.h". -// -// So many choices! Which time class should you use? Examples: -// -// Time: Interpreting the wall-clock time provided by a remote system. -// Detecting whether cached resources have expired. Providing the -// user with a display of the current date and time. Determining -// the amount of time between events across re-boots of the -// machine. -// -// TimeTicks: Tracking the amount of time a task runs. Executing delayed -// tasks at the right time. Computing presentation timestamps. -// Synchronizing audio and video using TimeTicks as a common -// reference clock (lip-sync). Measuring network round-trip -// latency. -// -// ThreadTicks: Benchmarking how long the current thread has been doing actual -// work. - -#ifndef BASE_TIME_TIME_H_ -#define BASE_TIME_TIME_H_ - -#include <stdint.h> -#include <time.h> - -#include <iosfwd> -#include <limits> - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/numerics/safe_math.h" -#include "util/build_config.h" - -#if defined(OS_MACOSX) -#include <CoreFoundation/CoreFoundation.h> -// Avoid Mac system header macro leak. -#undef TYPE_BOOL -#endif - -#if defined(OS_POSIX) -#include <sys/time.h> -#include <unistd.h> -#endif - -#if defined(OS_WIN) -#include "base/gtest_prod_util.h" -#include "base/win/windows_types.h" -#endif - -namespace base { - -class PlatformThreadHandle; -class TimeDelta; - -// The functions in the time_internal namespace are meant to be used only by the -// time classes and functions. Please use the math operators defined in the -// time classes instead. -namespace time_internal { - -// Add or subtract |value| from a TimeDelta. The int64_t argument and return -// value are in terms of a microsecond timebase. -int64_t SaturatedAdd(TimeDelta delta, int64_t value); -int64_t SaturatedSub(TimeDelta delta, int64_t value); - -} // namespace time_internal - -// TimeDelta ------------------------------------------------------------------ - -class TimeDelta { - public: - constexpr TimeDelta() : delta_(0) {} - - // Converts units of time to TimeDeltas. - static constexpr TimeDelta FromDays(int days); - static constexpr TimeDelta FromHours(int hours); - static constexpr TimeDelta FromMinutes(int minutes); - static constexpr TimeDelta FromSeconds(int64_t secs); - static constexpr TimeDelta FromMilliseconds(int64_t ms); - static constexpr TimeDelta FromMicroseconds(int64_t us); - static constexpr TimeDelta FromNanoseconds(int64_t ns); - static constexpr TimeDelta FromSecondsD(double secs); - static constexpr TimeDelta FromMillisecondsD(double ms); - static constexpr TimeDelta FromMicrosecondsD(double us); - static constexpr TimeDelta FromNanosecondsD(double ns); -#if defined(OS_WIN) - static TimeDelta FromQPCValue(LONGLONG qpc_value); - static TimeDelta FromFileTime(FILETIME ft); -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) - static TimeDelta FromTimeSpec(const timespec& ts); -#endif - - // Converts an integer value representing TimeDelta to a class. This is used - // when deserializing a |TimeDelta| structure, using a value known to be - // compatible. It is not provided as a constructor because the integer type - // may be unclear from the perspective of a caller. - // - // DEPRECATED - Do not use in new code. http://crbug.com/634507 - static constexpr TimeDelta FromInternalValue(int64_t delta) { - return TimeDelta(delta); - } - - // Returns the maximum time delta, which should be greater than any reasonable - // time delta we might compare it to. Adding or subtracting the maximum time - // delta to a time or another time delta has an undefined result. - static constexpr TimeDelta Max(); - - // Returns the minimum time delta, which should be less than than any - // reasonable time delta we might compare it to. Adding or subtracting the - // minimum time delta to a time or another time delta has an undefined result. - static constexpr TimeDelta Min(); - - // Returns the internal numeric value of the TimeDelta object. Please don't - // use this and do arithmetic on it, as it is more error prone than using the - // provided operators. - // For serializing, use FromInternalValue to reconstitute. - // - // DEPRECATED - Do not use in new code. http://crbug.com/634507 - constexpr int64_t ToInternalValue() const { return delta_; } - - // Returns the magnitude (absolute value) of this TimeDelta. - constexpr TimeDelta magnitude() const { - // Some toolchains provide an incomplete C++11 implementation and lack an - // int64_t overload for std::abs(). The following is a simple branchless - // implementation: - const int64_t mask = delta_ >> (sizeof(delta_) * 8 - 1); - return TimeDelta((delta_ + mask) ^ mask); - } - - // Returns true if the time delta is zero. - constexpr bool is_zero() const { return delta_ == 0; } - - // Returns true if the time delta is the maximum/minimum time delta. - constexpr bool is_max() const { - return delta_ == std::numeric_limits<int64_t>::max(); - } - constexpr bool is_min() const { - return delta_ == std::numeric_limits<int64_t>::min(); - } - -#if defined(OS_POSIX) || defined(OS_FUCHSIA) - struct timespec ToTimeSpec() const; -#endif - - // Returns the time delta in some unit. The F versions return a floating - // point value, the "regular" versions return a rounded-down value. - // - // InMillisecondsRoundedUp() instead returns an integer that is rounded up - // to the next full millisecond. - int InDays() const; - int InHours() const; - int InMinutes() const; - double InSecondsF() const; - int64_t InSeconds() const; - double InMillisecondsF() const; - int64_t InMilliseconds() const; - int64_t InMillisecondsRoundedUp() const; - int64_t InMicroseconds() const; - double InMicrosecondsF() const; - int64_t InNanoseconds() const; - - constexpr TimeDelta& operator=(TimeDelta other) { - delta_ = other.delta_; - return *this; - } - - // Computations with other deltas. Can easily be made constexpr with C++17 but - // hard to do until then per limitations around - // __builtin_(add|sub)_overflow in safe_math_clang_gcc_impl.h : - // https://chromium-review.googlesource.com/c/chromium/src/+/873352#message-59594ab70827795a67e0780404adf37b4b6c2f14 - TimeDelta operator+(TimeDelta other) const { - return TimeDelta(time_internal::SaturatedAdd(*this, other.delta_)); - } - TimeDelta operator-(TimeDelta other) const { - return TimeDelta(time_internal::SaturatedSub(*this, other.delta_)); - } - - TimeDelta& operator+=(TimeDelta other) { return *this = (*this + other); } - TimeDelta& operator-=(TimeDelta other) { return *this = (*this - other); } - constexpr TimeDelta operator-() const { return TimeDelta(-delta_); } - - // Computations with numeric types. operator*() isn't constexpr because of a - // limitation around __builtin_mul_overflow (but operator/(1.0/a) works for - // |a|'s of "reasonable" size -- i.e. that don't risk overflow). - template <typename T> - TimeDelta operator*(T a) const { - CheckedNumeric<int64_t> rv(delta_); - rv *= a; - if (rv.IsValid()) - return TimeDelta(rv.ValueOrDie()); - // Matched sign overflows. Mismatched sign underflows. - if ((delta_ < 0) ^ (a < 0)) - return TimeDelta(std::numeric_limits<int64_t>::min()); - return TimeDelta(std::numeric_limits<int64_t>::max()); - } - template <typename T> - constexpr TimeDelta operator/(T a) const { - CheckedNumeric<int64_t> rv(delta_); - rv /= a; - if (rv.IsValid()) - return TimeDelta(rv.ValueOrDie()); - // Matched sign overflows. Mismatched sign underflows. - // Special case to catch divide by zero. - if ((delta_ < 0) ^ (a <= 0)) - return TimeDelta(std::numeric_limits<int64_t>::min()); - return TimeDelta(std::numeric_limits<int64_t>::max()); - } - template <typename T> - TimeDelta& operator*=(T a) { - return *this = (*this * a); - } - template <typename T> - constexpr TimeDelta& operator/=(T a) { - return *this = (*this / a); - } - - constexpr int64_t operator/(TimeDelta a) const { return delta_ / a.delta_; } - constexpr TimeDelta operator%(TimeDelta a) const { - return TimeDelta(delta_ % a.delta_); - } - - // Comparison operators. - constexpr bool operator==(TimeDelta other) const { - return delta_ == other.delta_; - } - constexpr bool operator!=(TimeDelta other) const { - return delta_ != other.delta_; - } - constexpr bool operator<(TimeDelta other) const { - return delta_ < other.delta_; - } - constexpr bool operator<=(TimeDelta other) const { - return delta_ <= other.delta_; - } - constexpr bool operator>(TimeDelta other) const { - return delta_ > other.delta_; - } - constexpr bool operator>=(TimeDelta other) const { - return delta_ >= other.delta_; - } - -#if defined(OS_WIN) - // This works around crbug.com/635974 - constexpr TimeDelta(const TimeDelta& other) : delta_(other.delta_) {} -#endif - - private: - friend int64_t time_internal::SaturatedAdd(TimeDelta delta, int64_t value); - friend int64_t time_internal::SaturatedSub(TimeDelta delta, int64_t value); - - // Constructs a delta given the duration in microseconds. This is private - // to avoid confusion by callers with an integer constructor. Use - // FromSeconds, FromMilliseconds, etc. instead. - constexpr explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} - - // Private method to build a delta from a double. - static constexpr TimeDelta FromDouble(double value); - - // Private method to build a delta from the product of a user-provided value - // and a known-positive value. - static constexpr TimeDelta FromProduct(int64_t value, int64_t positive_value); - - // Delta in microseconds. - int64_t delta_; -}; - -template <typename T> -TimeDelta operator*(T a, TimeDelta td) { - return td * a; -} - -// For logging use only. -std::ostream& operator<<(std::ostream& os, TimeDelta time_delta); - -// Do not reference the time_internal::TimeBase template class directly. Please -// use one of the time subclasses instead, and only reference the public -// TimeBase members via those classes. -namespace time_internal { - -// TimeBase-------------------------------------------------------------------- - -// Provides value storage and comparison/math operations common to all time -// classes. Each subclass provides for strong type-checking to ensure -// semantically meaningful comparison/math of time values from the same clock -// source or timeline. -template <class TimeClass> -class TimeBase { - public: - static const int64_t kHoursPerDay = 24; - static const int64_t kMillisecondsPerSecond = 1000; - static const int64_t kMillisecondsPerDay = - kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; - static const int64_t kMicrosecondsPerMillisecond = 1000; - static const int64_t kMicrosecondsPerSecond = - kMicrosecondsPerMillisecond * kMillisecondsPerSecond; - static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; - static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; - static const int64_t kMicrosecondsPerDay = - kMicrosecondsPerHour * kHoursPerDay; - static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; - static const int64_t kNanosecondsPerMicrosecond = 1000; - static const int64_t kNanosecondsPerSecond = - kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; - - // Returns true if this object has not been initialized. - // - // Warning: Be careful when writing code that performs math on time values, - // since it's possible to produce a valid "zero" result that should not be - // interpreted as a "null" value. - bool is_null() const { return us_ == 0; } - - // Returns true if this object represents the maximum/minimum time. - bool is_max() const { return us_ == std::numeric_limits<int64_t>::max(); } - bool is_min() const { return us_ == std::numeric_limits<int64_t>::min(); } - - // Returns the maximum/minimum times, which should be greater/less than than - // any reasonable time with which we might compare it. - static TimeClass Max() { - return TimeClass(std::numeric_limits<int64_t>::max()); - } - - static TimeClass Min() { - return TimeClass(std::numeric_limits<int64_t>::min()); - } - - // For serializing only. Use FromInternalValue() to reconstitute. Please don't - // use this and do arithmetic on it, as it is more error prone than using the - // provided operators. - // - // DEPRECATED - Do not use in new code. For serializing Time values, prefer - // Time::ToDeltaSinceWindowsEpoch().InMicroseconds(). http://crbug.com/634507 - int64_t ToInternalValue() const { return us_; } - - // The amount of time since the origin (or "zero") point. This is a syntactic - // convenience to aid in code readability, mainly for debugging/testing use - // cases. - // - // Warning: While the Time subclass has a fixed origin point, the origin for - // the other subclasses can vary each time the application is restarted. - TimeDelta since_origin() const { return TimeDelta::FromMicroseconds(us_); } - - TimeClass& operator=(TimeClass other) { - us_ = other.us_; - return *(static_cast<TimeClass*>(this)); - } - - // Compute the difference between two times. - TimeDelta operator-(TimeClass other) const { - return TimeDelta::FromMicroseconds(us_ - other.us_); - } - - // Return a new time modified by some delta. - TimeClass operator+(TimeDelta delta) const { - return TimeClass(time_internal::SaturatedAdd(delta, us_)); - } - TimeClass operator-(TimeDelta delta) const { - return TimeClass(-time_internal::SaturatedSub(delta, us_)); - } - - // Modify by some time delta. - TimeClass& operator+=(TimeDelta delta) { - return static_cast<TimeClass&>(*this = (*this + delta)); - } - TimeClass& operator-=(TimeDelta delta) { - return static_cast<TimeClass&>(*this = (*this - delta)); - } - - // Comparison operators - bool operator==(TimeClass other) const { return us_ == other.us_; } - bool operator!=(TimeClass other) const { return us_ != other.us_; } - bool operator<(TimeClass other) const { return us_ < other.us_; } - bool operator<=(TimeClass other) const { return us_ <= other.us_; } - bool operator>(TimeClass other) const { return us_ > other.us_; } - bool operator>=(TimeClass other) const { return us_ >= other.us_; } - - protected: - constexpr explicit TimeBase(int64_t us) : us_(us) {} - - // Time value in a microsecond timebase. - int64_t us_; -}; - -} // namespace time_internal - -template <class TimeClass> -inline TimeClass operator+(TimeDelta delta, TimeClass t) { - return t + delta; -} - -// Time ----------------------------------------------------------------------- - -// Represents a wall clock time in UTC. Values are not guaranteed to be -// monotonically non-decreasing and are subject to large amounts of skew. -class Time : public time_internal::TimeBase<Time> { - public: - // Offset of UNIX epoch (1970-01-01 00:00:00 UTC) from Windows FILETIME epoch - // (1601-01-01 00:00:00 UTC), in microseconds. This value is derived from the - // following: ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the number - // of leap year days between 1601 and 1970: (1970-1601)/4 excluding 1700, - // 1800, and 1900. - static constexpr int64_t kTimeTToMicrosecondsOffset = - INT64_C(11644473600000000); - -#if defined(OS_WIN) - // To avoid overflow in QPC to Microseconds calculations, since we multiply - // by kMicrosecondsPerSecond, then the QPC value should not exceed - // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. - static constexpr int64_t kQPCOverflowThreshold = INT64_C(0x8637BD05AF7); -#endif - -// kExplodedMinYear and kExplodedMaxYear define the platform-specific limits -// for values passed to FromUTCExploded() and FromLocalExploded(). Those -// functions will return false if passed values outside these limits. The limits -// are inclusive, meaning that the API should support all dates within a given -// limit year. -#if defined(OS_WIN) - static constexpr int kExplodedMinYear = 1601; - static constexpr int kExplodedMaxYear = 30827; -#elif defined(OS_MACOSX) - static constexpr int kExplodedMinYear = 1902; - static constexpr int kExplodedMaxYear = std::numeric_limits<int>::max(); -#else - static constexpr int kExplodedMinYear = - (sizeof(time_t) == 4 ? 1902 : std::numeric_limits<int>::min()); - static constexpr int kExplodedMaxYear = - (sizeof(time_t) == 4 ? 2037 : std::numeric_limits<int>::max()); -#endif - - // Represents an exploded time that can be formatted nicely. This is kind of - // like the Win32 SYSTEMTIME structure or the Unix "struct tm" with a few - // additions and changes to prevent errors. - struct Exploded { - int year; // Four digit year "2007" - int month; // 1-based month (values 1 = January, etc.) - int day_of_week; // 0-based day of week (0 = Sunday, etc.) - int day_of_month; // 1-based day of month (1-31) - int hour; // Hour within the current day (0-23) - int minute; // Minute within the current hour (0-59) - int second; // Second within the current minute (0-59 plus leap - // seconds which may take it up to 60). - int millisecond; // Milliseconds within the current second (0-999) - - // A cursory test for whether the data members are within their - // respective ranges. A 'true' return value does not guarantee the - // Exploded value can be successfully converted to a Time value. - bool HasValidValues() const; - }; - - // Contains the NULL time. Use Time::Now() to get the current time. - constexpr Time() : TimeBase(0) {} - - // Returns the time for epoch in Unix-like system (Jan 1, 1970). - static Time UnixEpoch(); - - // Returns the current time. Watch out, the system might adjust its clock - // in which case time will actually go backwards. We don't guarantee that - // times are increasing, or that two calls to Now() won't be the same. - static Time Now(); - - // Returns the current time. Same as Now() except that this function always - // uses system time so that there are no discrepancies between the returned - // time and system time even on virtual environments including our test bot. - // For timing sensitive unittests, this function should be used. - static Time NowFromSystemTime(); - - // Converts to/from TimeDeltas relative to the Windows epoch (1601-01-01 - // 00:00:00 UTC). Prefer these methods for opaque serialization and - // deserialization of time values, e.g. - // - // // Serialization: - // base::Time last_updated = ...; - // SaveToDatabase(last_updated.ToDeltaSinceWindowsEpoch().InMicroseconds()); - // - // // Deserialization: - // base::Time last_updated = base::Time::FromDeltaSinceWindowsEpoch( - // base::TimeDelta::FromMicroseconds(LoadFromDatabase())); - static Time FromDeltaSinceWindowsEpoch(TimeDelta delta); - TimeDelta ToDeltaSinceWindowsEpoch() const; - - // Converts to/from time_t in UTC and a Time class. - static Time FromTimeT(time_t tt); - time_t ToTimeT() const; - - // Converts time to/from a double which is the number of seconds since epoch - // (Jan 1, 1970). Webkit uses this format to represent time. - // Because WebKit initializes double time value to 0 to indicate "not - // initialized", we map it to empty Time object that also means "not - // initialized". - static Time FromDoubleT(double dt); - double ToDoubleT() const; - -#if defined(OS_POSIX) || defined(OS_FUCHSIA) - // Converts the timespec structure to time. MacOS X 10.8.3 (and tentatively, - // earlier versions) will have the |ts|'s tv_nsec component zeroed out, - // having a 1 second resolution, which agrees with - // https://developer.apple.com/legacy/library/#technotes/tn/tn1150.html#HFSPlusDates. - static Time FromTimeSpec(const timespec& ts); -#endif - - // Converts to/from the Javascript convention for times, a number of - // milliseconds since the epoch: - // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime. - static Time FromJsTime(double ms_since_epoch); - double ToJsTime() const; - - // Converts to/from Java convention for times, a number of milliseconds since - // the epoch. Because the Java format has less resolution, converting to Java - // time is a lossy operation. - static Time FromJavaTime(int64_t ms_since_epoch); - int64_t ToJavaTime() const; - -#if defined(OS_POSIX) || defined(OS_FUCHSIA) - static Time FromTimeVal(struct timeval t); - struct timeval ToTimeVal() const; -#endif - -#if defined(OS_MACOSX) - static Time FromCFAbsoluteTime(CFAbsoluteTime t); - CFAbsoluteTime ToCFAbsoluteTime() const; -#endif - -#if defined(OS_WIN) - static Time FromFileTime(FILETIME ft); - FILETIME ToFileTime() const; - - // The minimum time of a low resolution timer. This is basically a windows - // constant of ~15.6ms. While it does vary on some older OS versions, we'll - // treat it as static across all windows versions. - static const int kMinLowResolutionThresholdMs = 16; - - // Enable or disable Windows high resolution timer. - static void EnableHighResolutionTimer(bool enable); - - // Activates or deactivates the high resolution timer based on the |activate| - // flag. If the HighResolutionTimer is not Enabled (see - // EnableHighResolutionTimer), this function will return false. Otherwise - // returns true. Each successful activate call must be paired with a - // subsequent deactivate call. - // All callers to activate the high resolution timer must eventually call - // this function to deactivate the high resolution timer. - static bool ActivateHighResolutionTimer(bool activate); - - // Returns true if the high resolution timer is both enabled and activated. - // This is provided for testing only, and is not tracked in a thread-safe - // way. - static bool IsHighResolutionTimerInUse(); - - // The following two functions are used to report the fraction of elapsed time - // that the high resolution timer is activated. - // ResetHighResolutionTimerUsage() resets the cumulative usage and starts the - // measurement interval and GetHighResolutionTimerUsage() returns the - // percentage of time since the reset that the high resolution timer was - // activated. - // ResetHighResolutionTimerUsage() must be called at least once before calling - // GetHighResolutionTimerUsage(); otherwise the usage result would be - // undefined. - static void ResetHighResolutionTimerUsage(); - static double GetHighResolutionTimerUsage(); -#endif // defined(OS_WIN) - - // Converts an integer value representing Time to a class. This may be used - // when deserializing a |Time| structure, using a value known to be - // compatible. It is not provided as a constructor because the integer type - // may be unclear from the perspective of a caller. - // - // DEPRECATED - Do not use in new code. For deserializing Time values, prefer - // Time::FromDeltaSinceWindowsEpoch(). http://crbug.com/634507 - static constexpr Time FromInternalValue(int64_t us) { return Time(us); } - - private: - friend class time_internal::TimeBase<Time>; - - constexpr explicit Time(int64_t us) : TimeBase(us) {} -}; - -// static -constexpr TimeDelta TimeDelta::FromDays(int days) { - return days == std::numeric_limits<int>::max() - ? Max() - : TimeDelta(days * Time::kMicrosecondsPerDay); -} - -// static -constexpr TimeDelta TimeDelta::FromHours(int hours) { - return hours == std::numeric_limits<int>::max() - ? Max() - : TimeDelta(hours * Time::kMicrosecondsPerHour); -} - -// static -constexpr TimeDelta TimeDelta::FromMinutes(int minutes) { - return minutes == std::numeric_limits<int>::max() - ? Max() - : TimeDelta(minutes * Time::kMicrosecondsPerMinute); -} - -// static -constexpr TimeDelta TimeDelta::FromSeconds(int64_t secs) { - return FromProduct(secs, Time::kMicrosecondsPerSecond); -} - -// static -constexpr TimeDelta TimeDelta::FromMilliseconds(int64_t ms) { - return FromProduct(ms, Time::kMicrosecondsPerMillisecond); -} - -// static -constexpr TimeDelta TimeDelta::FromMicroseconds(int64_t us) { - return TimeDelta(us); -} - -// static -constexpr TimeDelta TimeDelta::FromNanoseconds(int64_t ns) { - return TimeDelta(ns / Time::kNanosecondsPerMicrosecond); -} - -// static -constexpr TimeDelta TimeDelta::FromSecondsD(double secs) { - return FromDouble(secs * Time::kMicrosecondsPerSecond); -} - -// static -constexpr TimeDelta TimeDelta::FromMillisecondsD(double ms) { - return FromDouble(ms * Time::kMicrosecondsPerMillisecond); -} - -// static -constexpr TimeDelta TimeDelta::FromMicrosecondsD(double us) { - return FromDouble(us); -} - -// static -constexpr TimeDelta TimeDelta::FromNanosecondsD(double ns) { - return FromDouble(ns / Time::kNanosecondsPerMicrosecond); -} - -// static -constexpr TimeDelta TimeDelta::Max() { - return TimeDelta(std::numeric_limits<int64_t>::max()); -} - -// static -constexpr TimeDelta TimeDelta::Min() { - return TimeDelta(std::numeric_limits<int64_t>::min()); -} - -// static -constexpr TimeDelta TimeDelta::FromDouble(double value) { - // TODO(crbug.com/612601): Use saturated_cast<int64_t>(value) once we sort out - // the Min() behavior. - return value > std::numeric_limits<int64_t>::max() - ? Max() - : value < std::numeric_limits<int64_t>::min() - ? Min() - : TimeDelta(static_cast<int64_t>(value)); -} - -// static -constexpr TimeDelta TimeDelta::FromProduct(int64_t value, - int64_t positive_value) { - DCHECK(positive_value > 0); - return value > std::numeric_limits<int64_t>::max() / positive_value - ? Max() - : value < std::numeric_limits<int64_t>::min() / positive_value - ? Min() - : TimeDelta(value * positive_value); -} - -// For logging use only. -std::ostream& operator<<(std::ostream& os, Time time); - -// TimeTicks ------------------------------------------------------------------ - -// Represents monotonically non-decreasing clock time. -class TimeTicks : public time_internal::TimeBase<TimeTicks> { - public: - // The underlying clock used to generate new TimeTicks. - enum class Clock { - FUCHSIA_ZX_CLOCK_MONOTONIC, - LINUX_CLOCK_MONOTONIC, - IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME, - MAC_MACH_ABSOLUTE_TIME, - WIN_QPC, - WIN_ROLLOVER_PROTECTED_TIME_GET_TIME - }; - - constexpr TimeTicks() : TimeBase(0) {} - - // Platform-dependent tick count representing "right now." When - // IsHighResolution() returns false, the resolution of the clock could be - // as coarse as ~15.6ms. Otherwise, the resolution should be no worse than one - // microsecond. - static TimeTicks Now(); - - // Returns true if the high resolution clock is working on this system and - // Now() will return high resolution values. Note that, on systems where the - // high resolution clock works but is deemed inefficient, the low resolution - // clock will be used instead. - static bool IsHighResolution() WARN_UNUSED_RESULT; - - // Returns true if TimeTicks is consistent across processes, meaning that - // timestamps taken on different processes can be safely compared with one - // another. (Note that, even on platforms where this returns true, time values - // from different threads that are within one tick of each other must be - // considered to have an ambiguous ordering.) - static bool IsConsistentAcrossProcesses() WARN_UNUSED_RESULT; - -#if defined(OS_WIN) - // Translates an absolute QPC timestamp into a TimeTicks value. The returned - // value has the same origin as Now(). Do NOT attempt to use this if - // IsHighResolution() returns false. - static TimeTicks FromQPCValue(LONGLONG qpc_value); -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) - static TimeTicks FromMachAbsoluteTime(uint64_t mach_absolute_time); -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - - // Get an estimate of the TimeTick value at the time of the UnixEpoch. Because - // Time and TimeTicks respond differently to user-set time and NTP - // adjustments, this number is only an estimate. Nevertheless, this can be - // useful when you need to relate the value of TimeTicks to a real time and - // date. Note: Upon first invocation, this function takes a snapshot of the - // realtime clock to establish a reference point. This function will return - // the same value for the duration of the application, but will be different - // in future application runs. - static TimeTicks UnixEpoch(); - - // Returns |this| snapped to the next tick, given a |tick_phase| and - // repeating |tick_interval| in both directions. |this| may be before, - // after, or equal to the |tick_phase|. - TimeTicks SnappedToNextTick(TimeTicks tick_phase, - TimeDelta tick_interval) const; - - // Returns an enum indicating the underlying clock being used to generate - // TimeTicks timestamps. This function should only be used for debugging and - // logging purposes. - static Clock GetClock(); - - // Converts an integer value representing TimeTicks to a class. This may be - // used when deserializing a |TimeTicks| structure, using a value known to be - // compatible. It is not provided as a constructor because the integer type - // may be unclear from the perspective of a caller. - // - // DEPRECATED - Do not use in new code. For deserializing TimeTicks values, - // prefer TimeTicks + TimeDelta(). http://crbug.com/634507 - static constexpr TimeTicks FromInternalValue(int64_t us) { - return TimeTicks(us); - } - - private: - friend class time_internal::TimeBase<TimeTicks>; - - // Please use Now() to create a new object. This is for internal use - // and testing. - constexpr explicit TimeTicks(int64_t us) : TimeBase(us) {} -}; - -// For logging use only. -std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks); - -// ThreadTicks ---------------------------------------------------------------- - -// Represents a clock, specific to a particular thread, than runs only while the -// thread is running. -class ThreadTicks : public time_internal::TimeBase<ThreadTicks> { - public: - ThreadTicks() : TimeBase(0) {} - - // Returns true if ThreadTicks::Now() is supported on this system. - static bool IsSupported() WARN_UNUSED_RESULT { -#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ - (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_ANDROID) || \ - defined(OS_FUCHSIA) || defined(OS_WIN) - return true; -#else - return false; -#endif - } - - // Waits until the initialization is completed. Needs to be guarded with a - // call to IsSupported(). - static void WaitUntilInitialized() { -#if defined(OS_WIN) - WaitUntilInitializedWin(); -#endif - } - - // Returns thread-specific CPU-time on systems that support this feature. - // Needs to be guarded with a call to IsSupported(). Use this timer - // to (approximately) measure how much time the calling thread spent doing - // actual work vs. being de-scheduled. May return bogus results if the thread - // migrates to another CPU between two calls. Returns an empty ThreadTicks - // object until the initialization is completed. If a clock reading is - // absolutely needed, call WaitUntilInitialized() before this method. - static ThreadTicks Now(); - -#if defined(OS_WIN) - // Similar to Now() above except this returns thread-specific CPU time for an - // arbitrary thread. All comments for Now() method above apply apply to this - // method as well. - static ThreadTicks GetForThread(const PlatformThreadHandle& thread_handle); -#endif - - // Converts an integer value representing ThreadTicks to a class. This may be - // used when deserializing a |ThreadTicks| structure, using a value known to - // be compatible. It is not provided as a constructor because the integer type - // may be unclear from the perspective of a caller. - // - // DEPRECATED - Do not use in new code. For deserializing ThreadTicks values, - // prefer ThreadTicks + TimeDelta(). http://crbug.com/634507 - static constexpr ThreadTicks FromInternalValue(int64_t us) { - return ThreadTicks(us); - } - - private: - friend class time_internal::TimeBase<ThreadTicks>; - - // Please use Now() or GetForThread() to create a new object. This is for - // internal use and testing. - constexpr explicit ThreadTicks(int64_t us) : TimeBase(us) {} - -#if defined(OS_WIN) - FRIEND_TEST_ALL_PREFIXES(TimeTicks, TSCTicksPerSecond); - - // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't - // been measured yet. Needs to be guarded with a call to IsSupported(). - // This method is declared here rather than in the anonymous namespace to - // allow testing. - static double TSCTicksPerSecond(); - - static void WaitUntilInitializedWin(); -#endif -}; - -// For logging use only. -std::ostream& operator<<(std::ostream& os, ThreadTicks time_ticks); - -} // namespace base - -#endif // BASE_TIME_TIME_H_
diff --git a/base/time/time_conversion_posix.cc b/base/time/time_conversion_posix.cc deleted file mode 100644 index ba0a2b2..0000000 --- a/base/time/time_conversion_posix.cc +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time.h" - -#include <stdint.h> -#include <sys/time.h> -#include <time.h> - -#include <limits> - -#include "base/logging.h" - -namespace base { - -// static -TimeDelta TimeDelta::FromTimeSpec(const timespec& ts) { - return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond + - ts.tv_nsec / Time::kNanosecondsPerMicrosecond); -} - -struct timespec TimeDelta::ToTimeSpec() const { - int64_t microseconds = InMicroseconds(); - time_t seconds = 0; - if (microseconds >= Time::kMicrosecondsPerSecond) { - seconds = InSeconds(); - microseconds -= seconds * Time::kMicrosecondsPerSecond; - } - struct timespec result = { - seconds, - static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)}; - return result; -} - -// static -Time Time::FromTimeVal(struct timeval t) { - DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond)); - DCHECK_GE(t.tv_usec, 0); - if (t.tv_usec == 0 && t.tv_sec == 0) - return Time(); - if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 && - t.tv_sec == std::numeric_limits<time_t>::max()) - return Max(); - return Time((static_cast<int64_t>(t.tv_sec) * Time::kMicrosecondsPerSecond) + - t.tv_usec + kTimeTToMicrosecondsOffset); -} - -struct timeval Time::ToTimeVal() const { - struct timeval result; - if (is_null()) { - result.tv_sec = 0; - result.tv_usec = 0; - return result; - } - if (is_max()) { - result.tv_sec = std::numeric_limits<time_t>::max(); - result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; - return result; - } - int64_t us = us_ - kTimeTToMicrosecondsOffset; - result.tv_sec = us / Time::kMicrosecondsPerSecond; - result.tv_usec = us % Time::kMicrosecondsPerSecond; - return result; -} - -} // namespace base
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc deleted file mode 100644 index 2d024e9..0000000 --- a/base/time/time_mac.cc +++ /dev/null
@@ -1,312 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time.h" - -#include <CoreFoundation/CFDate.h> -#include <CoreFoundation/CFTimeZone.h> -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <stddef.h> -#include <stdint.h> -#include <sys/sysctl.h> -#include <sys/time.h> -#include <sys/types.h> -#include <time.h> - -#include "base/logging.h" -#include "base/mac/mach_logging.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_mach_port.h" -#include "base/macros.h" -#include "base/numerics/safe_conversions.h" -#include "base/time/time_override.h" -#include "util/build_config.h" - -#if defined(OS_IOS) -#include <time.h> -#include "base/ios/ios_util.h" -#endif - -namespace { - -#if defined(OS_MACOSX) && !defined(OS_IOS) -int64_t MachAbsoluteTimeToTicks(uint64_t mach_absolute_time) { - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - // Zero-initialization of statics guarantees that denom will be 0 before - // calling mach_timebase_info. mach_timebase_info will never set denom to - // 0 as that would be invalid, so the zero-check can be used to determine - // whether mach_timebase_info has already been called. This is - // recommended by Apple's QA1398. - kern_return_t kr = mach_timebase_info(&timebase_info); - MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info"; - } - - // timebase_info converts absolute time tick units into nanoseconds. Convert - // to microseconds up front to stave off overflows. - base::CheckedNumeric<uint64_t> result(mach_absolute_time / - base::Time::kNanosecondsPerMicrosecond); - result *= timebase_info.numer; - result /= timebase_info.denom; - - // Don't bother with the rollover handling that the Windows version does. - // With numer and denom = 1 (the expected case), the 64-bit absolute time - // reported in nanoseconds is enough to last nearly 585 years. - return base::checked_cast<int64_t>(result.ValueOrDie()); -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -// Returns monotonically growing number of ticks in microseconds since some -// unspecified starting point. -int64_t ComputeCurrentTicks() { -#if defined(OS_IOS) - // iOS 10 supports clock_gettime(CLOCK_MONOTONIC, ...), which is - // around 15 times faster than sysctl() call. Use it if possible; - // otherwise, fall back to sysctl(). - if (__builtin_available(iOS 10, *)) { - struct timespec tp; - if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { - return (int64_t)tp.tv_sec * 1000000 + tp.tv_nsec / 1000; - } - } - - // On iOS mach_absolute_time stops while the device is sleeping. Instead use - // now - KERN_BOOTTIME to get a time difference that is not impacted by clock - // changes. KERN_BOOTTIME will be updated by the system whenever the system - // clock change. - struct timeval boottime; - int mib[2] = {CTL_KERN, KERN_BOOTTIME}; - size_t size = sizeof(boottime); - int kr = sysctl(mib, arraysize(mib), &boottime, &size, nullptr, 0); - DCHECK_EQ(KERN_SUCCESS, kr); - base::TimeDelta time_difference = - base::subtle::TimeNowIgnoringOverride() - - (base::Time::FromTimeT(boottime.tv_sec) + - base::TimeDelta::FromMicroseconds(boottime.tv_usec)); - return time_difference.InMicroseconds(); -#else - // mach_absolute_time is it when it comes to ticks on the Mac. Other calls - // with less precision (such as TickCount) just call through to - // mach_absolute_time. - return MachAbsoluteTimeToTicks(mach_absolute_time()); -#endif // defined(OS_IOS) -} - -int64_t ComputeThreadTicks() { -#if defined(OS_IOS) - NOTREACHED(); - return 0; -#else - base::mac::ScopedMachSendRight thread(mach_thread_self()); - mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT; - thread_basic_info_data_t thread_info_data; - - if (thread.get() == MACH_PORT_NULL) { - DLOG(ERROR) << "Failed to get mach_thread_self()"; - return 0; - } - - kern_return_t kr = thread_info( - thread.get(), THREAD_BASIC_INFO, - reinterpret_cast<thread_info_t>(&thread_info_data), &thread_info_count); - MACH_DCHECK(kr == KERN_SUCCESS, kr) << "thread_info"; - - base::CheckedNumeric<int64_t> absolute_micros( - thread_info_data.user_time.seconds + - thread_info_data.system_time.seconds); - absolute_micros *= base::Time::kMicrosecondsPerSecond; - absolute_micros += (thread_info_data.user_time.microseconds + - thread_info_data.system_time.microseconds); - return absolute_micros.ValueOrDie(); -#endif // defined(OS_IOS) -} - -} // namespace - -namespace base { - -// The Time routines in this file use Mach and CoreFoundation APIs, since the -// POSIX definition of time_t in Mac OS X wraps around after 2038--and -// there are already cookie expiration dates, etc., past that time out in -// the field. Using CFDate prevents that problem, and using mach_absolute_time -// for TimeTicks gives us nice high-resolution interval timing. - -// Time ----------------------------------------------------------------------- - -namespace subtle { -Time TimeNowIgnoringOverride() { - return Time::FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent()); -} - -Time TimeNowFromSystemTimeIgnoringOverride() { - // Just use TimeNowIgnoringOverride() because it returns the system time. - return TimeNowIgnoringOverride(); -} -} // namespace subtle - -// static -Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) { - static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, - "CFAbsoluteTime must have an infinity value"); - if (t == 0) - return Time(); // Consider 0 as a null Time. - if (t == std::numeric_limits<CFAbsoluteTime>::infinity()) - return Max(); - return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) * - kMicrosecondsPerSecond) + - kTimeTToMicrosecondsOffset); -} - -CFAbsoluteTime Time::ToCFAbsoluteTime() const { - static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, - "CFAbsoluteTime must have an infinity value"); - if (is_null()) - return 0; // Consider 0 as a null Time. - if (is_max()) - return std::numeric_limits<CFAbsoluteTime>::infinity(); - return (static_cast<CFAbsoluteTime>(us_ - kTimeTToMicrosecondsOffset) / - kMicrosecondsPerSecond) - - kCFAbsoluteTimeIntervalSince1970; -} - -// Note: These implementations of Time::FromExploded() and Time::Explode() are -// only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX -// versions of these functions as time_t is not capped at year 2038 on 64-bit -// builds. The POSIX functions are preferred since they don't suffer from some -// performance problems that are present in these implementations. -// See crbug.com/781601 for more details. -#if defined(OS_IOS) -// static -bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { - base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( - is_local - ? CFTimeZoneCopySystem() - : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); - base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( - kCFAllocatorDefault, kCFGregorianCalendar)); - CFCalendarSetTimeZone(gregorian, time_zone); - CFAbsoluteTime absolute_time; - // 'S' is not defined in componentDesc in Apple documentation, but can be - // found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c - CFCalendarComposeAbsoluteTime( - gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month, - exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, - exploded.millisecond); - CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970; - - // CFAbsolutTime is typedef of double. Convert seconds to - // microseconds and then cast to int64. If - // it cannot be suited to int64, then fail to avoid overflows. - double microseconds = - (seconds * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset; - if (microseconds > std::numeric_limits<int64_t>::max() || - microseconds < std::numeric_limits<int64_t>::min()) { - *time = Time(0); - return false; - } - - base::Time converted_time = Time(static_cast<int64_t>(microseconds)); - - // If |exploded.day_of_month| is set to 31 - // on a 28-30 day month, it will return the first day of the next month. - // Thus round-trip the time and compare the initial |exploded| with - // |utc_to_exploded| time. - base::Time::Exploded to_exploded; - if (!is_local) - converted_time.UTCExplode(&to_exploded); - else - converted_time.LocalExplode(&to_exploded); - - if (ExplodedMostlyEquals(to_exploded, exploded)) { - *time = converted_time; - return true; - } - - *time = Time(0); - return false; -} - -void Time::Explode(bool is_local, Exploded* exploded) const { - // Avoid rounding issues, by only putting the integral number of seconds - // (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|). - int64_t microsecond = us_ % kMicrosecondsPerSecond; - if (microsecond < 0) - microsecond += kMicrosecondsPerSecond; - CFAbsoluteTime seconds = ((us_ - microsecond - kTimeTToMicrosecondsOffset) / - kMicrosecondsPerSecond) - - kCFAbsoluteTimeIntervalSince1970; - - base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( - is_local - ? CFTimeZoneCopySystem() - : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); - base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( - kCFAllocatorDefault, kCFGregorianCalendar)); - CFCalendarSetTimeZone(gregorian, time_zone); - int second, day_of_week; - // 'E' sets the day of week, but is not defined in componentDesc in Apple - // documentation. It can be found in open source code here: - // http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c - CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE", - &exploded->year, &exploded->month, - &exploded->day_of_month, &exploded->hour, - &exploded->minute, &second, &day_of_week); - // Make sure seconds are rounded down towards -infinity. - exploded->second = floor(second); - // |Exploded|'s convention for day of week is 0 = Sunday, i.e. different - // from CF's 1 = Sunday. - exploded->day_of_week = (day_of_week - 1) % 7; - // Calculate milliseconds ourselves, since we rounded the |seconds|, making - // sure to round towards -infinity. - exploded->millisecond = - (microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond - : (microsecond - kMicrosecondsPerMillisecond + 1) / - kMicrosecondsPerMillisecond; -} -#endif // OS_IOS - -// TimeTicks ------------------------------------------------------------------ - -namespace subtle { -TimeTicks TimeTicksNowIgnoringOverride() { - return TimeTicks() + TimeDelta::FromMicroseconds(ComputeCurrentTicks()); -} -} // namespace subtle - -// static -bool TimeTicks::IsHighResolution() { - return true; -} - -// static -bool TimeTicks::IsConsistentAcrossProcesses() { - return true; -} - -#if defined(OS_MACOSX) && !defined(OS_IOS) -// static -TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) { - return TimeTicks(MachAbsoluteTimeToTicks(mach_absolute_time)); -} -#endif // defined(OS_MACOSX) && !defined(OS_IOS) - -// static -TimeTicks::Clock TimeTicks::GetClock() { -#if defined(OS_IOS) - return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME; -#else - return Clock::MAC_MACH_ABSOLUTE_TIME; -#endif // defined(OS_IOS) -} - -// ThreadTicks ---------------------------------------------------------------- - -namespace subtle { -ThreadTicks ThreadTicksNowIgnoringOverride() { - return ThreadTicks() + TimeDelta::FromMicroseconds(ComputeThreadTicks()); -} -} // namespace subtle - -} // namespace base
diff --git a/base/time/time_now_posix.cc b/base/time/time_now_posix.cc deleted file mode 100644 index a3f4602..0000000 --- a/base/time/time_now_posix.cc +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time.h" - -#include <stdint.h> -#include <sys/time.h> -#include <time.h> -#if defined(OS_ANDROID) && !defined(__LP64__) -#include <time64.h> -#endif -#include <unistd.h> - -#include "base/logging.h" -#include "base/numerics/safe_math.h" -#include "base/time/time_override.h" -#include "util/build_config.h" - -// Ensure the Fuchsia and Mac builds do not include this module. Instead, -// non-POSIX implementation is used for sampling the system clocks. -#if defined(OS_FUCHSIA) || defined(OS_MACOSX) -#error "This implementation is for POSIX platforms other than Fuchsia or Mac." -#endif - -namespace { - -int64_t ConvertTimespecToMicros(const struct timespec& ts) { - // On 32-bit systems, the calculation cannot overflow int64_t. - // 2**32 * 1000000 + 2**64 / 1000 < 2**63 - if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) { - int64_t result = ts.tv_sec; - result *= base::Time::kMicrosecondsPerSecond; - result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); - return result; - } else { - base::CheckedNumeric<int64_t> result(ts.tv_sec); - result *= base::Time::kMicrosecondsPerSecond; - result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond); - return result.ValueOrDie(); - } -} - -// Helper function to get results from clock_gettime() and convert to a -// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported -// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines -// _POSIX_MONOTONIC_CLOCK to -1. -#if (defined(OS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \ - _POSIX_MONOTONIC_CLOCK >= 0) || \ - defined(OS_BSD) || defined(OS_ANDROID) -int64_t ClockNow(clockid_t clk_id) { - struct timespec ts; - CHECK(clock_gettime(clk_id, &ts) == 0); - return ConvertTimespecToMicros(ts); -} -#else // _POSIX_MONOTONIC_CLOCK -#error No usable tick clock function on this platform. -#endif // _POSIX_MONOTONIC_CLOCK - -} // namespace - -namespace base { - -// Time ----------------------------------------------------------------------- - -namespace subtle { -Time TimeNowIgnoringOverride() { - struct timeval tv; - struct timezone tz = {0, 0}; // UTC - CHECK(gettimeofday(&tv, &tz) == 0); - // Combine seconds and microseconds in a 64-bit field containing microseconds - // since the epoch. That's enough for nearly 600 centuries. Adjust from - // Unix (1970) to Windows (1601) epoch. - return Time() + TimeDelta::FromMicroseconds( - (tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) + - Time::kTimeTToMicrosecondsOffset); -} - -Time TimeNowFromSystemTimeIgnoringOverride() { - // Just use TimeNowIgnoringOverride() because it returns the system time. - return TimeNowIgnoringOverride(); -} -} // namespace subtle - -// TimeTicks ------------------------------------------------------------------ - -namespace subtle { -TimeTicks TimeTicksNowIgnoringOverride() { - return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC)); -} -} // namespace subtle - -// static -TimeTicks::Clock TimeTicks::GetClock() { - return Clock::LINUX_CLOCK_MONOTONIC; -} - -// static -bool TimeTicks::IsHighResolution() { - return true; -} - -// static -bool TimeTicks::IsConsistentAcrossProcesses() { - return true; -} - -// ThreadTicks ---------------------------------------------------------------- - -namespace subtle { -ThreadTicks ThreadTicksNowIgnoringOverride() { -#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ - defined(OS_ANDROID) - return ThreadTicks() + - TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID)); -#else - NOTREACHED(); - return ThreadTicks(); -#endif -} -} // namespace subtle - -} // namespace base
diff --git a/base/time/time_override.cc b/base/time/time_override.cc deleted file mode 100644 index 09692b5..0000000 --- a/base/time/time_override.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/time/time_override.h" - -namespace base { -namespace subtle { - -#if DCHECK_IS_ON() -// static -bool ScopedTimeClockOverrides::overrides_active_ = false; -#endif - -ScopedTimeClockOverrides::ScopedTimeClockOverrides( - TimeNowFunction time_override, - TimeTicksNowFunction time_ticks_override, - ThreadTicksNowFunction thread_ticks_override) { -#if DCHECK_IS_ON() - DCHECK(!overrides_active_); - overrides_active_ = true; -#endif - if (time_override) { - internal::g_time_now_function = time_override; - internal::g_time_now_from_system_time_function = time_override; - } - if (time_ticks_override) - internal::g_time_ticks_now_function = time_ticks_override; - if (thread_ticks_override) - internal::g_thread_ticks_now_function = thread_ticks_override; -} - -ScopedTimeClockOverrides::~ScopedTimeClockOverrides() { - internal::g_time_now_function = &TimeNowIgnoringOverride; - internal::g_time_now_from_system_time_function = - &TimeNowFromSystemTimeIgnoringOverride; - internal::g_time_ticks_now_function = &TimeTicksNowIgnoringOverride; - internal::g_thread_ticks_now_function = &ThreadTicksNowIgnoringOverride; -#if DCHECK_IS_ON() - overrides_active_ = false; -#endif -} - -} // namespace subtle -} // namespace base
diff --git a/base/time/time_override.h b/base/time/time_override.h deleted file mode 100644 index 4e068f7..0000000 --- a/base/time/time_override.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TIME_TIME_OVERRIDE_H_ -#define BASE_TIME_TIME_OVERRIDE_H_ - -#include "base/time/time.h" - -namespace base { - -using TimeNowFunction = decltype(&Time::Now); -using TimeTicksNowFunction = decltype(&TimeTicks::Now); -using ThreadTicksNowFunction = decltype(&ThreadTicks::Now); - -// Time overrides should be used with extreme caution. Discuss with //base/time -// OWNERS before adding a new one. -namespace subtle { - -// Override the return value of Time::Now and Time::NowFromSystemTime / -// TimeTicks::Now / ThreadTicks::Now to emulate time, e.g. for tests or to -// modify progression of time. Note that the override should be set while -// single-threaded and before the first call to Now() to avoid threading issues -// and inconsistencies in returned values. Nested overrides are not allowed. -class ScopedTimeClockOverrides { - public: - // Pass |nullptr| for any override if it shouldn't be overriden. - ScopedTimeClockOverrides(TimeNowFunction time_override, - TimeTicksNowFunction time_ticks_override, - ThreadTicksNowFunction thread_ticks_override); - - // Restores the platform default Now() functions. - ~ScopedTimeClockOverrides(); - - private: -#if DCHECK_IS_ON() - static bool overrides_active_; -#endif - - DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTimeClockOverrides); -}; - -// These methods return the platform default Time::Now / TimeTicks::Now / -// ThreadTicks::Now values even while an override is in place. These methods -// should only be used in places where emulated time should be disregarded. For -// example, they can be used to implement test timeouts for tests that may -// override time. -Time TimeNowIgnoringOverride(); -Time TimeNowFromSystemTimeIgnoringOverride(); -TimeTicks TimeTicksNowIgnoringOverride(); -ThreadTicks ThreadTicksNowIgnoringOverride(); - -} // namespace subtle - -namespace internal { - -// These function pointers are used by platform-independent implementations of -// the Now() methods and ScopedTimeClockOverrides. They are set to point to the -// respective NowIgnoringOverride functions by default, but can also be set by -// platform-specific code to select a default implementation at runtime, thereby -// avoiding the indirection via the NowIgnoringOverride functions. Note that the -// pointers can be overridden and later reset to the NowIgnoringOverride -// functions by ScopedTimeClockOverrides. -extern TimeNowFunction g_time_now_function; -extern TimeNowFunction g_time_now_from_system_time_function; -extern TimeTicksNowFunction g_time_ticks_now_function; -extern ThreadTicksNowFunction g_thread_ticks_now_function; - -} // namespace internal - -} // namespace base - -#endif // BASE_TIME_TIME_OVERRIDE_H_
diff --git a/base/time/time_win.cc b/base/time/time_win.cc deleted file mode 100644 index 8632369..0000000 --- a/base/time/time_win.cc +++ /dev/null
@@ -1,542 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Windows Timer Primer -// -// A good article: http://www.ddj.com/windows/184416651 -// A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 -// -// The default windows timer, GetSystemTimeAsFileTime is not very precise. -// It is only good to ~15.5ms. -// -// QueryPerformanceCounter is the logical choice for a high-precision timer. -// However, it is known to be buggy on some hardware. Specifically, it can -// sometimes "jump". On laptops, QPC can also be very expensive to call. -// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower -// on laptops. A unittest exists which will show the relative cost of various -// timers on any system. -// -// The next logical choice is timeGetTime(). timeGetTime has a precision of -// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other -// applications on the system. By default, precision is only 15.5ms. -// Unfortunately, we don't want to call timeBeginPeriod because we don't -// want to affect other applications. Further, on mobile platforms, use of -// faster multimedia timers can hurt battery life. See the intel -// article about this here: -// http://softwarecommunity.intel.com/articles/eng/1086.htm -// -// To work around all this, we're going to generally use timeGetTime(). We -// will only increase the system-wide timer if we're not running on battery -// power. - -#include "base/time/time.h" - -#include <windows.h> - -#include <mmsystem.h> -#include <stdint.h> - -#include <mutex> - -#include "base/bit_cast.h" -#include "base/logging.h" -#include "base/threading/platform_thread.h" -#include "base/time/time_override.h" - -namespace base { - -namespace { - -// From MSDN, FILETIME "Contains a 64-bit value representing the number of -// 100-nanosecond intervals since January 1, 1601 (UTC)." -int64_t FileTimeToMicroseconds(const FILETIME& ft) { - // Need to bit_cast to fix alignment, then divide by 10 to convert - // 100-nanoseconds to microseconds. This only works on little-endian - // machines. - return bit_cast<int64_t, FILETIME>(ft) / 10; -} - -void MicrosecondsToFileTime(int64_t us, FILETIME* ft) { - DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not " - "representable in FILETIME"; - - // Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will - // handle alignment problems. This only works on little-endian machines. - *ft = bit_cast<FILETIME, int64_t>(us * 10); -} - -int64_t CurrentWallclockMicroseconds() { - FILETIME ft; - ::GetSystemTimeAsFileTime(&ft); - return FileTimeToMicroseconds(ft); -} - -// Time between resampling the un-granular clock for this API. -constexpr TimeDelta kMaxTimeToAvoidDrift = TimeDelta::FromSeconds(60); - -int64_t g_initial_time = 0; -TimeTicks g_initial_ticks; - -void InitializeClock() { - g_initial_ticks = subtle::TimeTicksNowIgnoringOverride(); - g_initial_time = CurrentWallclockMicroseconds(); -} - -// The two values that ActivateHighResolutionTimer uses to set the systemwide -// timer interrupt frequency on Windows. It controls how precise timers are -// but also has a big impact on battery life. -const int kMinTimerIntervalHighResMs = 1; -const int kMinTimerIntervalLowResMs = 4; -// Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active. -bool g_high_res_timer_enabled = false; -// How many times the high resolution timer has been called. -uint32_t g_high_res_timer_count = 0; -// Start time of the high resolution timer usage monitoring. This is needed -// to calculate the usage as percentage of the total elapsed time. -TimeTicks g_high_res_timer_usage_start; -// The cumulative time the high resolution timer has been in use since -// |g_high_res_timer_usage_start| moment. -TimeDelta g_high_res_timer_usage; -// Timestamp of the last activation change of the high resolution timer. This -// is used to calculate the cumulative usage. -TimeTicks g_high_res_timer_last_activation; -// The lock to control access to the above two variables. -std::mutex* GetHighResLock() { - static auto* lock = new std::mutex(); - return lock; -} - -// Returns the current value of the performance counter. -uint64_t QPCNowRaw() { - LARGE_INTEGER perf_counter_now = {}; - // According to the MSDN documentation for QueryPerformanceCounter(), this - // will never fail on systems that run XP or later. - // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx - ::QueryPerformanceCounter(&perf_counter_now); - return perf_counter_now.QuadPart; -} - -bool SafeConvertToWord(int in, WORD* out) { - CheckedNumeric<WORD> result = in; - *out = result.ValueOrDefault(std::numeric_limits<WORD>::max()); - return result.IsValid(); -} - -} // namespace - -// Time ----------------------------------------------------------------------- - -namespace subtle { -Time TimeNowIgnoringOverride() { - if (g_initial_time == 0) - InitializeClock(); - - // We implement time using the high-resolution timers so that we can get - // timeouts which are smaller than 10-15ms. If we just used - // CurrentWallclockMicroseconds(), we'd have the less-granular timer. - // - // To make this work, we initialize the clock (g_initial_time) and the - // counter (initial_ctr). To compute the initial time, we can check - // the number of ticks that have elapsed, and compute the delta. - // - // To avoid any drift, we periodically resync the counters to the system - // clock. - while (true) { - TimeTicks ticks = TimeTicksNowIgnoringOverride(); - - // Calculate the time elapsed since we started our timer - TimeDelta elapsed = ticks - g_initial_ticks; - - // Check if enough time has elapsed that we need to resync the clock. - if (elapsed > kMaxTimeToAvoidDrift) { - InitializeClock(); - continue; - } - - return Time() + elapsed + TimeDelta::FromMicroseconds(g_initial_time); - } -} - -Time TimeNowFromSystemTimeIgnoringOverride() { - // Force resync. - InitializeClock(); - return Time() + TimeDelta::FromMicroseconds(g_initial_time); -} -} // namespace subtle - -// static -Time Time::FromFileTime(FILETIME ft) { - if (bit_cast<int64_t, FILETIME>(ft) == 0) - return Time(); - if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() && - ft.dwLowDateTime == std::numeric_limits<DWORD>::max()) - return Max(); - return Time(FileTimeToMicroseconds(ft)); -} - -FILETIME Time::ToFileTime() const { - if (is_null()) - return bit_cast<FILETIME, int64_t>(0); - if (is_max()) { - FILETIME result; - result.dwHighDateTime = std::numeric_limits<DWORD>::max(); - result.dwLowDateTime = std::numeric_limits<DWORD>::max(); - return result; - } - FILETIME utc_ft; - MicrosecondsToFileTime(us_, &utc_ft); - return utc_ft; -} - -// static -void Time::EnableHighResolutionTimer(bool enable) { - std::lock_guard<std::mutex> lock(*GetHighResLock()); - if (g_high_res_timer_enabled == enable) - return; - g_high_res_timer_enabled = enable; - if (!g_high_res_timer_count) - return; - // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true) - // was called which called timeBeginPeriod with g_high_res_timer_enabled - // with a value which is the opposite of |enable|. With that information we - // call timeEndPeriod with the same value used in timeBeginPeriod and - // therefore undo the period effect. - if (enable) { - timeEndPeriod(kMinTimerIntervalLowResMs); - timeBeginPeriod(kMinTimerIntervalHighResMs); - } else { - timeEndPeriod(kMinTimerIntervalHighResMs); - timeBeginPeriod(kMinTimerIntervalLowResMs); - } -} - -// static -bool Time::ActivateHighResolutionTimer(bool activating) { - // We only do work on the transition from zero to one or one to zero so we - // can easily undo the effect (if necessary) when EnableHighResolutionTimer is - // called. - const uint32_t max = std::numeric_limits<uint32_t>::max(); - - std::lock_guard<std::mutex> lock(*GetHighResLock()); - UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs - : kMinTimerIntervalLowResMs; - if (activating) { - DCHECK_NE(g_high_res_timer_count, max); - ++g_high_res_timer_count; - if (g_high_res_timer_count == 1) { - g_high_res_timer_last_activation = subtle::TimeTicksNowIgnoringOverride(); - timeBeginPeriod(period); - } - } else { - DCHECK_NE(g_high_res_timer_count, 0u); - --g_high_res_timer_count; - if (g_high_res_timer_count == 0) { - g_high_res_timer_usage += subtle::TimeTicksNowIgnoringOverride() - - g_high_res_timer_last_activation; - timeEndPeriod(period); - } - } - return (period == kMinTimerIntervalHighResMs); -} - -// static -bool Time::IsHighResolutionTimerInUse() { - std::lock_guard<std::mutex> lock(*GetHighResLock()); - return g_high_res_timer_enabled && g_high_res_timer_count > 0; -} - -// static -void Time::ResetHighResolutionTimerUsage() { - std::lock_guard<std::mutex> lock(*GetHighResLock()); - g_high_res_timer_usage = TimeDelta(); - g_high_res_timer_usage_start = subtle::TimeTicksNowIgnoringOverride(); - if (g_high_res_timer_count > 0) - g_high_res_timer_last_activation = g_high_res_timer_usage_start; -} - -// static -double Time::GetHighResolutionTimerUsage() { - std::lock_guard<std::mutex> lock(*GetHighResLock()); - TimeTicks now = subtle::TimeTicksNowIgnoringOverride(); - TimeDelta elapsed_time = now - g_high_res_timer_usage_start; - if (elapsed_time.is_zero()) { - // This is unexpected but possible if TimeTicks resolution is low and - // GetHighResolutionTimerUsage() is called promptly after - // ResetHighResolutionTimerUsage(). - return 0.0; - } - TimeDelta used_time = g_high_res_timer_usage; - if (g_high_res_timer_count > 0) { - // If currently activated add the remainder of time since the last - // activation. - used_time += now - g_high_res_timer_last_activation; - } - return used_time.InMillisecondsF() / elapsed_time.InMillisecondsF() * 100; -} - -// TimeTicks ------------------------------------------------------------------ - -namespace { - -// Discussion of tick counter options on Windows: -// -// (1) CPU cycle counter. (Retrieved via RDTSC) -// The CPU counter provides the highest resolution time stamp and is the least -// expensive to retrieve. However, on older CPUs, two issues can affect its -// reliability: First it is maintained per processor and not synchronized -// between processors. Also, the counters will change frequency due to thermal -// and power changes, and stop in some states. -// -// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- -// resolution (<1 microsecond) time stamp. On most hardware running today, it -// auto-detects and uses the constant-rate RDTSC counter to provide extremely -// efficient and reliable time stamps. -// -// On older CPUs where RDTSC is unreliable, it falls back to using more -// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI -// PM timer, and can involve system calls; and all this is up to the HAL (with -// some help from ACPI). According to -// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the -// worst case, it gets the counter from the rollover interrupt on the -// programmable interrupt timer. In best cases, the HAL may conclude that the -// RDTSC counter runs at a constant frequency, then it uses that instead. On -// multiprocessor machines, it will try to verify the values returned from -// RDTSC on each processor are consistent with each other, and apply a handful -// of workarounds for known buggy hardware. In other words, QPC is supposed to -// give consistent results on a multiprocessor computer, but for older CPUs it -// can be unreliable due bugs in BIOS or HAL. -// -// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6 -// milliseconds) time stamp but is comparatively less expensive to retrieve and -// more reliable. Time::EnableHighResolutionTimer() and -// Time::ActivateHighResolutionTimer() can be called to alter the resolution of -// this timer; and also other Windows applications can alter it, affecting this -// one. - -TimeTicks InitialNowFunction(); - -// See "threading notes" in InitializeNowFunctionPointer() for details on how -// concurrent reads/writes to these globals has been made safe. -TimeTicksNowFunction g_time_ticks_now_ignoring_override_function = - &InitialNowFunction; -int64_t g_qpc_ticks_per_second = 0; - -// As of January 2015, use of <atomic> is forbidden in Chromium code. This is -// what std::atomic_thread_fence does on Windows on all Intel architectures when -// the memory_order argument is anything but std::memory_order_seq_cst: -#define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier(); - -TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) { - // Ensure that the assignment to |g_qpc_ticks_per_second|, made in - // InitializeNowFunctionPointer(), has happened by this point. - ATOMIC_THREAD_FENCE(memory_order_acquire); - - DCHECK_GT(g_qpc_ticks_per_second, 0); - - // If the QPC Value is below the overflow threshold, we proceed with - // simple multiply and divide. - if (qpc_value < Time::kQPCOverflowThreshold) { - return TimeDelta::FromMicroseconds( - qpc_value * Time::kMicrosecondsPerSecond / g_qpc_ticks_per_second); - } - // Otherwise, calculate microseconds in a round about manner to avoid - // overflow and precision issues. - int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second; - int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second); - return TimeDelta::FromMicroseconds( - (whole_seconds * Time::kMicrosecondsPerSecond) + - ((leftover_ticks * Time::kMicrosecondsPerSecond) / - g_qpc_ticks_per_second)); -} - -TimeTicks QPCNow() { - return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw()); -} - -void InitializeNowFunctionPointer() { - LARGE_INTEGER ticks_per_sec = {}; - if (!QueryPerformanceFrequency(&ticks_per_sec)) - ticks_per_sec.QuadPart = 0; - - TimeTicksNowFunction now_function = &QPCNow; - - // Threading note 1: In an unlikely race condition, it's possible for two or - // more threads to enter InitializeNowFunctionPointer() in parallel. This is - // not a problem since all threads should end up writing out the same values - // to the global variables. - // - // Threading note 2: A release fence is placed here to ensure, from the - // perspective of other threads using the function pointers, that the - // assignment to |g_qpc_ticks_per_second| happens before the function pointers - // are changed. - g_qpc_ticks_per_second = ticks_per_sec.QuadPart; - ATOMIC_THREAD_FENCE(memory_order_release); - // Also set g_time_ticks_now_function to avoid the additional indirection via - // TimeTicksNowIgnoringOverride() for future calls to TimeTicks::Now(). But - // g_time_ticks_now_function may have already be overridden. - if (internal::g_time_ticks_now_function == - &subtle::TimeTicksNowIgnoringOverride) { - internal::g_time_ticks_now_function = now_function; - } - g_time_ticks_now_ignoring_override_function = now_function; -} - -TimeTicks InitialNowFunction() { - InitializeNowFunctionPointer(); - return g_time_ticks_now_ignoring_override_function(); -} - -} // namespace - -namespace subtle { -TimeTicks TimeTicksNowIgnoringOverride() { - return g_time_ticks_now_ignoring_override_function(); -} -} // namespace subtle - -// static -bool TimeTicks::IsHighResolution() { - if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction) - InitializeNowFunctionPointer(); - return g_time_ticks_now_ignoring_override_function == &QPCNow; -} - -// static -bool TimeTicks::IsConsistentAcrossProcesses() { - // According to Windows documentation [1] QPC is consistent post-Windows - // Vista. So if we are using QPC then we are consistent which is the same as - // being high resolution. - // - // [1] - // https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx - // - // "In general, the performance counter results are consistent across all - // processors in multi-core and multi-processor systems, even when measured on - // different threads or processes. Here are some exceptions to this rule: - // - Pre-Windows Vista operating systems that run on certain processors might - // violate this consistency because of one of these reasons: - // 1. The hardware processors have a non-invariant TSC and the BIOS - // doesn't indicate this condition correctly. - // 2. The TSC synchronization algorithm that was used wasn't suitable for - // systems with large numbers of processors." - return IsHighResolution(); -} - -// static -TimeTicks::Clock TimeTicks::GetClock() { - return IsHighResolution() ? Clock::WIN_QPC - : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME; -} - -// ThreadTicks ---------------------------------------------------------------- - -namespace subtle { -ThreadTicks ThreadTicksNowIgnoringOverride() { - return ThreadTicks::GetForThread(PlatformThread::CurrentHandle()); -} -} // namespace subtle - -// static -ThreadTicks ThreadTicks::GetForThread( - const PlatformThreadHandle& thread_handle) { - DCHECK(IsSupported()); - - // Get the number of TSC ticks used by the current thread. - ULONG64 thread_cycle_time = 0; - ::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time); - - // Get the frequency of the TSC. - double tsc_ticks_per_second = TSCTicksPerSecond(); - if (tsc_ticks_per_second == 0) - return ThreadTicks(); - - // Return the CPU time of the current thread. - double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second; - return ThreadTicks( - static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond)); -} - -// static -void ThreadTicks::WaitUntilInitializedWin() { - while (TSCTicksPerSecond() == 0) - ::Sleep(10); -} - -double ThreadTicks::TSCTicksPerSecond() { - DCHECK(IsSupported()); - - // The value returned by QueryPerformanceFrequency() cannot be used as the TSC - // frequency, because there is no guarantee that the TSC frequency is equal to - // the performance counter frequency. - - // The TSC frequency is cached in a static variable because it takes some time - // to compute it. - static double tsc_ticks_per_second = 0; - if (tsc_ticks_per_second != 0) - return tsc_ticks_per_second; - - // Increase the thread priority to reduces the chances of having a context - // switch during a reading of the TSC and the performance counter. - int previous_priority = ::GetThreadPriority(::GetCurrentThread()); - ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST); - - // The first time that this function is called, make an initial reading of the - // TSC and the performance counter. - static const uint64_t tsc_initial = __rdtsc(); - static const uint64_t perf_counter_initial = QPCNowRaw(); - - // Make a another reading of the TSC and the performance counter every time - // that this function is called. - uint64_t tsc_now = __rdtsc(); - uint64_t perf_counter_now = QPCNowRaw(); - - // Reset the thread priority. - ::SetThreadPriority(::GetCurrentThread(), previous_priority); - - // Make sure that at least 50 ms elapsed between the 2 readings. The first - // time that this function is called, we don't expect this to be the case. - // Note: The longer the elapsed time between the 2 readings is, the more - // accurate the computed TSC frequency will be. The 50 ms value was - // chosen because local benchmarks show that it allows us to get a - // stddev of less than 1 tick/us between multiple runs. - // Note: According to the MSDN documentation for QueryPerformanceFrequency(), - // this will never fail on systems that run XP or later. - // https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx - LARGE_INTEGER perf_counter_frequency = {}; - ::QueryPerformanceFrequency(&perf_counter_frequency); - DCHECK_GE(perf_counter_now, perf_counter_initial); - uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial; - double elapsed_time_seconds = - perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart); - - static constexpr double kMinimumEvaluationPeriodSeconds = 0.05; - if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds) - return 0; - - // Compute the frequency of the TSC. - DCHECK_GE(tsc_now, tsc_initial); - uint64_t tsc_ticks = tsc_now - tsc_initial; - tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds; - - return tsc_ticks_per_second; -} - -// static -TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) { - return TimeTicks() + QPCValueToTimeDelta(qpc_value); -} - -// TimeDelta ------------------------------------------------------------------ - -// static -TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) { - return QPCValueToTimeDelta(qpc_value); -} - -// static -TimeDelta TimeDelta::FromFileTime(FILETIME ft) { - return TimeDelta::FromMicroseconds(FileTimeToMicroseconds(ft)); -} - -} // namespace base
diff --git a/base/timer/elapsed_timer.cc b/base/timer/elapsed_timer.cc index ca86ccd..68992f4 100644 --- a/base/timer/elapsed_timer.cc +++ b/base/timer/elapsed_timer.cc
@@ -7,7 +7,7 @@ namespace base { ElapsedTimer::ElapsedTimer() { - begin_ = TimeTicks::Now(); + begin_ = TicksNow(); } ElapsedTimer::ElapsedTimer(ElapsedTimer&& other) { @@ -18,8 +18,8 @@ begin_ = other.begin_; } -TimeDelta ElapsedTimer::Elapsed() const { - return TimeTicks::Now() - begin_; +TickDelta ElapsedTimer::Elapsed() const { + return TicksDelta(TicksNow(), begin_); } } // namespace base
diff --git a/base/timer/elapsed_timer.h b/base/timer/elapsed_timer.h index c9d254b..fbbc83d 100644 --- a/base/timer/elapsed_timer.h +++ b/base/timer/elapsed_timer.h
@@ -6,11 +6,11 @@ #define BASE_TIMER_ELAPSED_TIMER_H_ #include "base/macros.h" -#include "base/time/time.h" +#include "util/ticks.h" namespace base { -// A simple wrapper around TimeTicks::Now(). +// A simple wrapper around TicksNow(). class ElapsedTimer { public: ElapsedTimer(); @@ -19,10 +19,10 @@ void operator=(ElapsedTimer&& other); // Returns the time elapsed since object construction. - TimeDelta Elapsed() const; + TickDelta Elapsed() const; private: - TimeTicks begin_; + Ticks begin_; DISALLOW_COPY_AND_ASSIGN(ElapsedTimer); };
diff --git a/build/gen.py b/build/gen.py index f253bc3..44435f6 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -254,8 +254,6 @@ 'base/strings/utf_string_conversion_utils.cc', 'base/strings/utf_string_conversions.cc', 'base/third_party/icu/icu_utf.cc', - 'base/time/clock.cc', - 'base/time/time.cc', 'base/timer/elapsed_timer.cc', 'base/value_iterators.cc', 'base/values.cc', @@ -385,6 +383,7 @@ 'util/msg_loop.cc', 'util/semaphore.cc', 'util/sys_info.cc', + 'util/ticks.cc', 'util/worker_pool.cc', ], 'tool': 'cxx', 'include_dirs': []}, } @@ -469,15 +468,11 @@ 'base/posix/file_descriptor_shuffle.cc', 'base/posix/safe_strerror.cc', 'base/strings/string16.cc', - 'base/threading/platform_thread_posix.cc', - 'base/time/time_conversion_posix.cc', ]) if is_linux: static_libraries['base']['sources'].extend([ 'base/strings/sys_string_conversions_posix.cc', - 'base/time/time_now_posix.cc', - 'base/threading/platform_thread_linux.cc', ]) libs.extend([ '-lc', @@ -498,8 +493,6 @@ 'base/mac/scoped_mach_port.cc', 'base/mac/scoped_nsautorelease_pool.mm', 'base/strings/sys_string_conversions_mac.mm', - 'base/time/time_mac.cc', - 'base/threading/platform_thread_mac.mm', ]) libs.extend([ @@ -515,8 +508,6 @@ 'base/files/file_util_win.cc', 'base/files/file_win.cc', 'base/strings/sys_string_conversions_win.cc', - 'base/threading/platform_thread_win.cc', - 'base/time/time_win.cc', 'base/win/registry.cc', 'base/win/scoped_handle.cc', 'base/win/scoped_process_information.cc',
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc index af5dd1f..eb1b4d2 100644 --- a/tools/gn/command_gen.cc +++ b/tools/gn/command_gen.cc
@@ -455,7 +455,7 @@ return 1; } - base::TimeDelta elapsed_time = timer.Elapsed(); + TickDelta elapsed_time = timer.Elapsed(); if (!command_line->HasSwitch(switches::kQuiet)) { OutputString("Done. ", DECORATION_GREEN);
diff --git a/tools/gn/filesystem_utils_unittest.cc b/tools/gn/filesystem_utils_unittest.cc index 8bfd52c..87e37f8 100644 --- a/tools/gn/filesystem_utils_unittest.cc +++ b/tools/gn/filesystem_utils_unittest.cc
@@ -3,12 +3,14 @@ // found in the LICENSE file. #include "tools/gn/filesystem_utils.h" + +#include <thread> + #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/threading/platform_thread.h" #include "tools/gn/target.h" #include "util/build_config.h" #include "util/test/test.h" @@ -645,15 +647,17 @@ base::File::Info file_info; ASSERT_TRUE(base::GetFileInfo(file_path, &file_info)); - base::Time last_modified = file_info.last_modified; + Ticks last_modified = file_info.last_modified; + { + using namespace std::chrono_literals; #if defined(OS_MACOSX) - // Modification times are in seconds in HFS on Mac. - base::TimeDelta sleep_time = base::TimeDelta::FromSeconds(1); + // Modification times are in seconds in HFS on Mac. + std::this_thread::sleep_for(1s); #else - base::TimeDelta sleep_time = base::TimeDelta::FromMilliseconds(1); + std::this_thread::sleep_for(1ms); #endif - base::PlatformThread::Sleep(sleep_time); + } // Don't write if contents is the same. EXPECT_TRUE(WriteFileIfChanged(file_path, data, nullptr));
diff --git a/tools/gn/function_exec_script.cc b/tools/gn/function_exec_script.cc index e1ada23..e0b6265 100644 --- a/tools/gn/function_exec_script.cc +++ b/tools/gn/function_exec_script.cc
@@ -7,7 +7,6 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" #include "tools/gn/err.h" #include "tools/gn/exec_process.h" #include "tools/gn/filesystem_utils.h" @@ -19,6 +18,7 @@ #include "tools/gn/trace.h" #include "tools/gn/value.h" #include "util/build_config.h" +#include "util/ticks.h" namespace functions { @@ -198,7 +198,7 @@ // Log command line for debugging help. trace.SetCommandLine(cmdline); - base::TimeTicks begin_exec; + Ticks begin_exec = 0; if (g_scheduler->verbose_logging()) { #if defined(OS_WIN) g_scheduler->Log("Pythoning", @@ -206,7 +206,7 @@ #else g_scheduler->Log("Pythoning", cmdline.GetCommandLineString()); #endif - begin_exec = base::TimeTicks::Now(); + begin_exec = TicksNow(); } base::FilePath startup_dir = @@ -239,7 +239,7 @@ "Pythoning", script_source_path + " took " + base::Int64ToString( - (base::TimeTicks::Now() - begin_exec).InMilliseconds()) + + TicksDelta(TicksNow(), begin_exec).InMilliseconds()) + "ms"); }
diff --git a/tools/gn/function_write_file_unittest.cc b/tools/gn/function_write_file_unittest.cc index b12f037..95414ce 100644 --- a/tools/gn/function_write_file_unittest.cc +++ b/tools/gn/function_write_file_unittest.cc
@@ -70,13 +70,21 @@ EXPECT_EQ("line 1\n2\n", result_contents); // Test that the file is not rewritten if the contents are not changed. - // Start by setting the modified time to something old to avoid clock - // resolution issues. - base::Time old_time = base::Time::Now() - base::TimeDelta::FromDays(1); base::File foo_file(foo_name, base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE); ASSERT_TRUE(foo_file.IsValid()); - foo_file.SetTimes(old_time, old_time); + + // Start by setting the modified time to something old to avoid clock + // resolution issues. +#if defined(OS_WIN) + FILETIME last_access_filetime = {}; + FILETIME last_modified_filetime = {}; + ASSERT_TRUE(::SetFileTime(foo_file.GetPlatformFile(), nullptr, + &last_access_filetime, &last_modified_filetime)); +#else + timespec ts_times[2] = {}; + ASSERT_EQ(futimens(foo_file.GetPlatformFile(), ts_times), 0); +#endif // Read the current time to avoid timer resolution issues when comparing // below.
diff --git a/tools/gn/import_manager.cc b/tools/gn/import_manager.cc index f4aa32a..36c7088 100644 --- a/tools/gn/import_manager.cc +++ b/tools/gn/import_manager.cc
@@ -11,6 +11,7 @@ #include "tools/gn/scheduler.h" #include "tools/gn/scope_per_file_provider.h" #include "tools/gn/trace.h" +#include "util/ticks.h" namespace { @@ -75,8 +76,9 @@ Scope* scope, Err* err) { // Key for the current import on the current thread in imports_in_progress_. - std::string key = - std::to_string(base::PlatformThread::CurrentId()) + file.value(); + std::stringstream ss; + ss << std::this_thread::get_id() << file.value(); + std::string key = ss.str(); // See if we have a cached import, but be careful to actually do the scope // copying outside of the lock. @@ -101,7 +103,7 @@ // is already processing the import. const Scope* import_scope = nullptr; { - base::TimeTicks import_block_begin = base::TimeTicks::Now(); + Ticks import_block_begin = TicksNow(); std::lock_guard<std::mutex> lock(import_info->load_lock); if (!import_info->scope) { @@ -117,14 +119,14 @@ } else { // Add trace if this thread was blocked for a long period of time and did // not load the import itself. - base::TimeTicks import_block_end = base::TimeTicks::Now(); - constexpr auto kImportBlockTraceThreshold = - base::TimeDelta::FromMilliseconds(20); + Ticks import_block_end = TicksNow(); + constexpr auto kImportBlockTraceThresholdMS = 20; if (TracingEnabled() && - import_block_end - import_block_begin > kImportBlockTraceThreshold) { + TicksDelta(import_block_end, import_block_begin).InMilliseconds() > + kImportBlockTraceThresholdMS) { auto* import_block_trace = new TraceItem(TraceItem::TRACE_IMPORT_BLOCK, file.value(), - base::PlatformThread::CurrentId()); + std::this_thread::get_id()); import_block_trace->set_begin(import_block_begin); import_block_trace->set_end(import_block_end); AddTrace(import_block_trace);
diff --git a/tools/gn/trace.cc b/tools/gn/trace.cc index 76fc00d..184c450 100644 --- a/tools/gn/trace.cc +++ b/tools/gn/trace.cc
@@ -56,7 +56,7 @@ }; bool DurationGreater(const TraceItem* a, const TraceItem* b) { - return a->delta() > b->delta(); + return a->delta().raw() > b->delta().raw(); } bool CoalescedDurationGreater(const Coalesced& a, const Coalesced& b) { @@ -112,7 +112,7 @@ TraceItem::TraceItem(Type type, const std::string& name, - base::PlatformThreadId thread_id) + std::thread::id thread_id) : type_(type), name_(name), thread_id_(thread_id) {} TraceItem::~TraceItem() = default; @@ -120,8 +120,8 @@ ScopedTrace::ScopedTrace(TraceItem::Type t, const std::string& name) : item_(nullptr), done_(false) { if (trace_log) { - item_ = new TraceItem(t, name, base::PlatformThread::CurrentId()); - item_->set_begin(base::TimeTicks::Now()); + item_ = new TraceItem(t, name, std::this_thread::get_id()); + item_->set_begin(TicksNow()); } } @@ -129,8 +129,8 @@ : item_(nullptr), done_(false) { if (trace_log) { item_ = new TraceItem(t, label.GetUserVisibleName(false), - base::PlatformThread::CurrentId()); - item_->set_begin(base::TimeTicks::Now()); + std::this_thread::get_id()); + item_->set_begin(TicksNow()); } } @@ -152,7 +152,7 @@ if (!done_) { done_ = true; if (trace_log) { - item_->set_end(base::TimeTicks::Now()); + item_->set_end(TicksNow()); AddTrace(item_); } } @@ -244,7 +244,7 @@ // Write main thread metadata (assume this is being written on the main // thread). - out << "{\"pid\":0,\"tid\":" << base::PlatformThread::CurrentId(); + out << "{\"pid\":0,\"tid\":" << std::this_thread::get_id(); out << ",\"ts\":0,\"ph\":\"M\","; out << "\"name\":\"thread_name\",\"args\":{\"name\":\"Main thread\"}},"; @@ -255,7 +255,7 @@ if (i != 0) out << ","; out << "{\"pid\":0,\"tid\":" << item.thread_id(); - out << ",\"ts\":" << item.begin().ToInternalValue(); + out << ",\"ts\":" << item.begin(); out << ",\"ph\":\"X\""; // "X" = complete event with begin & duration. out << ",\"dur\":" << item.delta().InMicroseconds();
diff --git a/tools/gn/trace.h b/tools/gn/trace.h index 3b91aaa..f4f06df 100644 --- a/tools/gn/trace.h +++ b/tools/gn/trace.h
@@ -6,10 +6,10 @@ #define TOOLS_GN_TRACE_H_ #include <string> +#include <thread> #include "base/macros.h" -#include "base/threading/platform_thread.h" -#include "base/time/time.h" +#include "util/ticks.h" class Label; @@ -35,21 +35,19 @@ TRACE_CHECK_HEADERS, // All files. }; - TraceItem(Type type, - const std::string& name, - base::PlatformThreadId thread_id); + TraceItem(Type type, const std::string& name, std::thread::id thread_id); ~TraceItem(); Type type() const { return type_; } const std::string& name() const { return name_; } - base::PlatformThreadId thread_id() const { return thread_id_; } + std::thread::id thread_id() const { return thread_id_; } - base::TimeTicks begin() const { return begin_; } - void set_begin(base::TimeTicks b) { begin_ = b; } - base::TimeTicks end() const { return end_; } - void set_end(base::TimeTicks e) { end_ = e; } + Ticks begin() const { return begin_; } + void set_begin(Ticks b) { begin_ = b; } + Ticks end() const { return end_; } + void set_end(Ticks e) { end_ = e; } - base::TimeDelta delta() const { return end_ - begin_; } + TickDelta delta() const { return TicksDelta(end_, begin_); } // Optional toolchain label. const std::string& toolchain() const { return toolchain_; } @@ -62,10 +60,10 @@ private: Type type_; std::string name_; - base::PlatformThreadId thread_id_; + std::thread::id thread_id_; - base::TimeTicks begin_; - base::TimeTicks end_; + Ticks begin_; + Ticks end_; std::string toolchain_; std::string cmdline_;
diff --git a/tools/gn/unique_vector.h b/tools/gn/unique_vector.h index 25b4f5b..732b663 100644 --- a/tools/gn/unique_vector.h +++ b/tools/gn/unique_vector.h
@@ -9,6 +9,7 @@ #include <algorithm> #include <unordered_set> +#include <vector> namespace internal {
diff --git a/tools/gn/unique_vector_unittest.cc b/tools/gn/unique_vector_unittest.cc index 87430ea..afea1e2 100644 --- a/tools/gn/unique_vector_unittest.cc +++ b/tools/gn/unique_vector_unittest.cc
@@ -6,7 +6,6 @@ #include <algorithm> -#include "base/time/time.h" #include "tools/gn/unique_vector.h" #include "util/test/test.h"
diff --git a/util/ticks.cc b/util/ticks.cc new file mode 100644 index 0000000..df35375 --- /dev/null +++ b/util/ticks.cc
@@ -0,0 +1,93 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ticks.h" + +#include "base/logging.h" +#include "build_config.h" + +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_MACOSX) +#include <mach/mach_time.h> +#elif defined(OS_LINUX) +#include <time.h> +#else +#error Port. +#endif + +namespace { + +bool g_initialized; + +#if defined(OS_WIN) +LARGE_INTEGER g_frequency; +LARGE_INTEGER g_start; +#elif defined(OS_MACOSX) +mach_timebase_info_data_t g_timebase; +uint64_t g_start; +#elif defined(OS_LINUX) +uint64_t g_start; +#else +#error Port. +#endif + +constexpr uint64_t kNano = 1'000'000'000; + +void Init() { + DCHECK(!g_initialized); + +#if defined(OS_WIN) + QueryPerformanceFrequency(&g_frequency); + QueryPerformanceCounter(&g_start); +#elif defined(OS_MACOSX) + mach_timebase_info(&g_timebase); + g_start = (mach_absolute_time() * g_timebase.numer) / g_timebase.denom; +#elif defined(OS_LINUX) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + g_start = static_cast<uint64_t>(ts.tv_sec) * kNano + + static_cast<uint64_t>(ts.tv_nsec); +#else +#error Port. +#endif + + g_initialized = true; +} + +} // namespace + +Ticks TicksNow() { + static bool initialized = []() { + Init(); + return true; + }(); + DCHECK(initialized); + + Ticks now; + +#if defined(OS_WIN) + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + now = ((t.QuadPart - g_start.QuadPart) * kNano) / g_frequency.QuadPart; +#elif defined(OS_MACOSX) + now = + ((mach_absolute_time() * g_timebase.numer) / g_timebase.denom) - g_start; +#elif defined(OS_LINUX) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + now = (static_cast<uint64_t>(ts.tv_sec) * kNano + + static_cast<uint64_t>(ts.tv_nsec)) - + g_start; +#else +#error Port. +#endif + + return now; +} + +TickDelta TicksDelta(Ticks new_ticks, Ticks old_ticks) { + DCHECK(new_ticks >= old_ticks); + return TickDelta(new_ticks - old_ticks); +}
diff --git a/util/ticks.h b/util/ticks.h new file mode 100644 index 0000000..fcbde05 --- /dev/null +++ b/util/ticks.h
@@ -0,0 +1,45 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UTIL_TICKS_H_ +#define UTIL_TICKS_H_ + +#include <stdint.h> + +using Ticks = uint64_t; + +class TickDelta { + public: + explicit TickDelta(uint64_t delta) : delta_(delta) {} + + double InSecondsF() const { return delta_ / 1000000000.0; } + double InMillisecondsF() const { return delta_ / 1000000.0; } + double InMicrosecondsF() const { return delta_ / 1000.0; } + double InNanosecondsF() const { return delta_; } + + uint64_t InSeconds() const { return delta_ / 1000000000; } + uint64_t InMilliseconds() const { return delta_ / 1000000; } + uint64_t InMicroseconds() const { return delta_ / 1000; } + uint64_t InNanoseconds() const { return delta_; } + + uint64_t raw() const { return delta_; } + + private: + uint64_t delta_; +}; + +Ticks TicksNow(); + +TickDelta TicksDelta(Ticks new_ticks, Ticks old_ticks); + +class ElapsedTimer { + public: + ElapsedTimer() : start_(TicksNow()) {} + TickDelta Elapsed() { return TicksDelta(TicksNow(), start_); } + + private: + Ticks start_; +}; + +#endif // UTIL_TICKS_H_