2010-05-12 03:42:16 +08:00
|
|
|
//===------------------------- chrono.cpp ---------------------------------===//
|
|
|
|
//
|
2019-01-19 18:56:40 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-05-12 03:42:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2016-07-02 07:31:55 +08:00
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
#include "chrono"
|
2015-06-23 22:45:02 +08:00
|
|
|
#include "cerrno" // errno
|
|
|
|
#include "system_error" // __throw_system_error
|
2020-02-13 00:01:19 +08:00
|
|
|
#include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW}
|
[libc++] Use __int128_t to represent file_time_type.
Summary:
The ``file_time_type`` time point is used to represent the write times for files.
Its job is to act as part of a C++ wrapper for less ideal system interfaces. The
underlying filesystem uses the ``timespec`` struct for the same purpose.
However, the initial implementation of ``file_time_type`` could not represent
either the range or resolution of ``timespec``, making it unsuitable. Fixing
this requires an implementation which uses more than 64 bits to store the
time point.
I primarily considered two solutions: Using ``__int128_t`` and using a
arithmetic emulation of ``timespec``. Each has its pros and cons, and both
come with more than one complication.
However, after a lot of consideration, I decided on using `__int128_t`. This patch implements that change.
Please see the [FileTimeType Design Document](http://libcxx.llvm.org/docs/DesignDocs/FileTimeType.html) for more information.
Reviewers: mclow.lists, ldionne, joerg, arthur.j.odwyer, EricWF
Reviewed By: EricWF
Subscribers: christof, K-ballo, cfe-commits, BillyONeal
Differential Revision: https://reviews.llvm.org/D49774
llvm-svn: 337960
2018-07-26 04:51:49 +08:00
|
|
|
#include "include/apple_availability.h"
|
2015-05-15 04:54:18 +08:00
|
|
|
|
2020-05-14 18:51:13 +08:00
|
|
|
#if __has_include(<unistd.h>)
|
2020-10-06 05:28:25 +08:00
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if __has_include(<sys/time.h>)
|
|
|
|
# include <sys/time.h> // for gettimeofday and timeval
|
2020-05-08 00:10:33 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(__APPLE__) && _POSIX_TIMERS > 0
|
2020-10-06 05:28:25 +08:00
|
|
|
# define _LIBCPP_USE_CLOCK_GETTIME
|
2020-05-08 00:10:33 +08:00
|
|
|
#endif
|
2017-01-10 03:21:48 +08:00
|
|
|
|
2017-01-04 05:53:51 +08:00
|
|
|
#if defined(_LIBCPP_WIN32API)
|
2020-02-13 00:01:19 +08:00
|
|
|
# define WIN32_LEAN_AND_MEAN
|
|
|
|
# define VC_EXTRA_LEAN
|
|
|
|
# include <windows.h>
|
|
|
|
# if _WIN32_WINNT >= _WIN32_WINNT_WIN8
|
|
|
|
# include <winapifamily.h>
|
|
|
|
# endif
|
2017-01-04 05:53:51 +08:00
|
|
|
#endif // defined(_LIBCPP_WIN32API)
|
2015-05-15 04:54:18 +08:00
|
|
|
|
2019-12-02 18:49:20 +08:00
|
|
|
#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB)
|
2020-02-13 00:01:19 +08:00
|
|
|
# pragma comment(lib, "rt")
|
2019-05-30 09:34:41 +08:00
|
|
|
#endif
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
|
|
|
namespace chrono
|
|
|
|
{
|
|
|
|
|
2020-11-04 23:14:13 +08:00
|
|
|
//
|
2010-05-12 03:42:16 +08:00
|
|
|
// system_clock
|
2020-11-04 23:14:13 +08:00
|
|
|
//
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2017-01-04 05:53:51 +08:00
|
|
|
#if defined(_LIBCPP_WIN32API)
|
2020-11-04 23:14:13 +08:00
|
|
|
|
|
|
|
static system_clock::time_point __libcpp_system_clock_now() {
|
2017-01-02 06:04:38 +08:00
|
|
|
// FILETIME is in 100ns units
|
|
|
|
using filetime_duration =
|
|
|
|
_VSTD::chrono::duration<__int64,
|
|
|
|
_VSTD::ratio_multiply<_VSTD::ratio<100, 1>,
|
|
|
|
nanoseconds::period>>;
|
2017-01-02 04:20:41 +08:00
|
|
|
|
2017-01-02 06:04:38 +08:00
|
|
|
// The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
|
2017-01-03 02:41:50 +08:00
|
|
|
static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600};
|
2017-01-02 06:04:38 +08:00
|
|
|
|
|
|
|
FILETIME ft;
|
2020-11-04 23:14:13 +08:00
|
|
|
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
2017-01-02 06:04:38 +08:00
|
|
|
GetSystemTimePreciseAsFileTime(&ft);
|
2017-01-02 04:20:41 +08:00
|
|
|
#else
|
2017-01-02 06:04:38 +08:00
|
|
|
GetSystemTimeAsFileTime(&ft);
|
2017-01-02 04:20:41 +08:00
|
|
|
#endif
|
2017-01-02 06:04:38 +08:00
|
|
|
|
|
|
|
filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
|
|
|
|
static_cast<__int64>(ft.dwLowDateTime)};
|
2020-11-04 23:14:13 +08:00
|
|
|
return system_clock::time_point(duration_cast<system_clock::duration>(d - nt_to_unix_epoch));
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(CLOCK_REALTIME) && defined(_LIBCPP_USE_CLOCK_GETTIME)
|
|
|
|
|
|
|
|
static system_clock::time_point __libcpp_system_clock_now() {
|
[libc++] Use __int128_t to represent file_time_type.
Summary:
The ``file_time_type`` time point is used to represent the write times for files.
Its job is to act as part of a C++ wrapper for less ideal system interfaces. The
underlying filesystem uses the ``timespec`` struct for the same purpose.
However, the initial implementation of ``file_time_type`` could not represent
either the range or resolution of ``timespec``, making it unsuitable. Fixing
this requires an implementation which uses more than 64 bits to store the
time point.
I primarily considered two solutions: Using ``__int128_t`` and using a
arithmetic emulation of ``timespec``. Each has its pros and cons, and both
come with more than one complication.
However, after a lot of consideration, I decided on using `__int128_t`. This patch implements that change.
Please see the [FileTimeType Design Document](http://libcxx.llvm.org/docs/DesignDocs/FileTimeType.html) for more information.
Reviewers: mclow.lists, ldionne, joerg, arthur.j.odwyer, EricWF
Reviewed By: EricWF
Subscribers: christof, K-ballo, cfe-commits, BillyONeal
Differential Revision: https://reviews.llvm.org/D49774
llvm-svn: 337960
2018-07-26 04:51:49 +08:00
|
|
|
struct timespec tp;
|
|
|
|
if (0 != clock_gettime(CLOCK_REALTIME, &tp))
|
|
|
|
__throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
|
2020-11-04 23:14:13 +08:00
|
|
|
return system_clock::time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
|
|
|
|
}
|
|
|
|
|
2017-01-10 03:21:48 +08:00
|
|
|
#else
|
2020-11-04 23:14:13 +08:00
|
|
|
|
|
|
|
static system_clock::time_point __libcpp_system_clock_now() {
|
2010-05-12 03:42:16 +08:00
|
|
|
timeval tv;
|
|
|
|
gettimeofday(&tv, 0);
|
2020-11-04 23:14:13 +08:00
|
|
|
return system_clock::time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
|
|
|
|
}
|
|
|
|
|
2017-01-02 04:20:41 +08:00
|
|
|
#endif
|
2020-11-04 23:14:13 +08:00
|
|
|
|
|
|
|
const bool system_clock::is_steady;
|
|
|
|
|
|
|
|
system_clock::time_point
|
|
|
|
system_clock::now() _NOEXCEPT
|
|
|
|
{
|
|
|
|
return __libcpp_system_clock_now();
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
time_t
|
2011-05-29 02:34:36 +08:00
|
|
|
system_clock::to_time_t(const time_point& t) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
|
|
|
|
}
|
|
|
|
|
|
|
|
system_clock::time_point
|
2011-05-29 02:34:36 +08:00
|
|
|
system_clock::from_time_t(time_t t) _NOEXCEPT
|
2010-05-12 03:42:16 +08:00
|
|
|
{
|
|
|
|
return system_clock::time_point(seconds(t));
|
|
|
|
}
|
|
|
|
|
2020-11-04 23:14:13 +08:00
|
|
|
//
|
2010-11-21 03:16:30 +08:00
|
|
|
// steady_clock
|
2015-05-15 04:54:18 +08:00
|
|
|
//
|
|
|
|
// Warning: If this is not truly steady, then it is non-conforming. It is
|
|
|
|
// better for it to not exist and have the rest of libc++ use system_clock
|
|
|
|
// instead.
|
2020-11-04 23:14:13 +08:00
|
|
|
//
|
2010-05-12 03:42:16 +08:00
|
|
|
|
2020-11-04 23:14:13 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
|
2012-12-13 05:14:28 +08:00
|
|
|
|
2017-01-02 04:20:43 +08:00
|
|
|
#if defined(__APPLE__)
|
2015-05-15 04:54:18 +08:00
|
|
|
|
2020-02-13 00:01:19 +08:00
|
|
|
// On Apple platforms, only CLOCK_UPTIME_RAW, CLOCK_MONOTONIC_RAW or
|
|
|
|
// mach_absolute_time are able to time functions in the nanosecond range.
|
|
|
|
// Furthermore, only CLOCK_MONOTONIC_RAW is truly monotonic, because it
|
|
|
|
// also counts cycles when the system is asleep. Thus, it is the only
|
|
|
|
// acceptable implementation of steady_clock.
|
2020-11-04 23:14:13 +08:00
|
|
|
static steady_clock::time_point __libcpp_steady_clock_now() {
|
2017-01-10 03:21:48 +08:00
|
|
|
struct timespec tp;
|
[libc++][Apple] Use CLOCK_MONOTONIC_RAW instead of CLOCK_UPTIME_RAW for steady_clock
Summary:
In D27429, we switched the Apple implementation of steady_clock::now()
from clock_gettime(CLOCK_MONOTONIC) to clock_gettime(CLOCK_UPTIME_RAW).
The purpose was to get nanosecond precision, and also to improve the
performance of the implementation.
However, it appears that CLOCK_UPTIME_RAW does not satisfy the requirements
of the Standard, since it is not strictly speaking monotonic. Indeed, the
clock does not increment while the system is asleep, which had been
mentioned in D27429 but somehow not addressed.
This patch switches to CLOCK_MONOTONIC_RAW, which is monotonic, increased
during sleep, and also has nanosecond precision.
https://llvm.org/PR44773
Reviewers: bruno, howard.hinnant, EricWF
Subscribers: christof, jkorous, dexonsmith, libcxx-commits, mclow.lists, EricWF
Tags: #libc
Differential Revision: https://reviews.llvm.org/D74341
2020-02-11 01:30:43 +08:00
|
|
|
if (0 != clock_gettime(CLOCK_MONOTONIC_RAW, &tp))
|
|
|
|
__throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC_RAW) failed");
|
2020-11-04 23:14:13 +08:00
|
|
|
return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
|
2017-01-10 03:21:48 +08:00
|
|
|
}
|
|
|
|
|
2017-01-04 05:53:51 +08:00
|
|
|
#elif defined(_LIBCPP_WIN32API)
|
2017-01-02 04:20:43 +08:00
|
|
|
|
2019-04-02 01:23:30 +08:00
|
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says:
|
|
|
|
// If the function fails, the return value is zero. <snip>
|
2019-10-24 02:45:36 +08:00
|
|
|
// On systems that run Windows XP or later, the function will always succeed
|
2019-04-02 01:23:30 +08:00
|
|
|
// and will thus never return zero.
|
|
|
|
|
|
|
|
static LARGE_INTEGER
|
|
|
|
__QueryPerformanceFrequency()
|
|
|
|
{
|
2020-11-04 23:14:13 +08:00
|
|
|
LARGE_INTEGER val;
|
|
|
|
(void) QueryPerformanceFrequency(&val);
|
|
|
|
return val;
|
2019-04-02 01:23:30 +08:00
|
|
|
}
|
|
|
|
|
2020-11-04 23:14:13 +08:00
|
|
|
static steady_clock::time_point __libcpp_steady_clock_now() {
|
2019-04-02 01:23:30 +08:00
|
|
|
static const LARGE_INTEGER freq = __QueryPerformanceFrequency();
|
2017-01-02 06:04:36 +08:00
|
|
|
|
2019-04-02 22:00:36 +08:00
|
|
|
LARGE_INTEGER counter;
|
|
|
|
(void) QueryPerformanceCounter(&counter);
|
2020-12-17 21:40:06 +08:00
|
|
|
auto seconds = counter.QuadPart / freq.QuadPart;
|
|
|
|
auto fractions = counter.QuadPart % freq.QuadPart;
|
|
|
|
auto dur = seconds * nano::den + fractions * nano::den / freq.QuadPart;
|
|
|
|
return steady_clock::time_point(steady_clock::duration(dur));
|
2017-01-02 04:20:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(CLOCK_MONOTONIC)
|
|
|
|
|
2020-11-04 23:14:13 +08:00
|
|
|
static steady_clock::time_point __libcpp_steady_clock_now() {
|
2017-01-02 04:20:43 +08:00
|
|
|
struct timespec tp;
|
|
|
|
if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
|
|
|
|
__throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
|
2020-11-04 23:14:13 +08:00
|
|
|
return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
|
2017-01-02 04:20:43 +08:00
|
|
|
}
|
|
|
|
|
2015-05-15 04:54:18 +08:00
|
|
|
#else
|
2020-11-04 23:14:13 +08:00
|
|
|
# error "Monotonic clock not implemented on this platform"
|
2015-05-15 04:54:18 +08:00
|
|
|
#endif
|
2010-05-25 01:49:41 +08:00
|
|
|
|
2020-11-04 23:14:13 +08:00
|
|
|
const bool steady_clock::is_steady;
|
|
|
|
|
|
|
|
steady_clock::time_point
|
|
|
|
steady_clock::now() _NOEXCEPT
|
|
|
|
{
|
|
|
|
return __libcpp_steady_clock_now();
|
|
|
|
}
|
|
|
|
|
2014-09-03 05:14:38 +08:00
|
|
|
#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK
|
|
|
|
|
2010-05-12 03:42:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|