Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
42c42bd
More aggressive on #448
AlexGuteniev Mar 29, 2020
baf428c
clang format
AlexGuteniev Mar 29, 2020
315299c
Group variables to reduce branching
AlexGuteniev Mar 29, 2020
404a6fe
unsigned divides faster
AlexGuteniev Mar 29, 2020
004426d
Revert "unsigned divides faster"
AlexGuteniev Mar 29, 2020
444c82f
Clear comparison against uninitialized
AlexGuteniev Mar 29, 2020
d7c8a4c
Rebase counter and do one division
AlexGuteniev Apr 2, 2020
aeecbcd
Undo test, it is not correct test
AlexGuteniev Apr 2, 2020
7e57c05
cland format
AlexGuteniev Apr 2, 2020
a255604
avoid loop
AlexGuteniev Apr 2, 2020
fc19466
trim whitespace
AlexGuteniev Apr 2, 2020
36262a6
Merge remote-tracking branch 'upstream/master' into chrono_cache_qpf_2
AlexGuteniev Apr 7, 2020
6c8b439
Merge remote-tracking branch 'upstream/master' into chrono_cache_qpf_2
AlexGuteniev Apr 11, 2020
27db1ba
After merging with #658 , avoid explanation repetition
AlexGuteniev Apr 11, 2020
bf63ab6
clang format
AlexGuteniev Apr 11, 2020
e85274a
more const
AlexGuteniev Apr 11, 2020
e2b00cf
Merge branch 'master' into chrono_cache_qpf_2
StephanTLavavej May 12, 2020
178b9bf
Code review feedback, part 1.
StephanTLavavej May 12, 2020
9d686ec
Code review feedback, part 2: access control.
StephanTLavavej May 12, 2020
2347e10
Code review feedback, part 3: avoid magic static
AlexGuteniev May 12, 2020
156783f
Relocate two _Atomic_meow function templates to <xatomic.h>
CaseyCarter May 12, 2020
f72c96c
Remove now-unused include <intrin0.h> in <chrono>
CaseyCarter May 12, 2020
4583b84
Use _Ugly_snake_case.
StephanTLavavej May 12, 2020
c83771b
Merge remote-tracking branch 'upstream/master' into chrono_cache_qpf_2
AlexGuteniev May 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion stl/inc/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <ratio>
#include <time.h>
#include <utility>
#include <xatomic.h>
#include <xtimec.h>

#pragma pack(push, _CRT_PACKING)
Expand Down Expand Up @@ -609,8 +610,40 @@ namespace chrono {
static constexpr bool is_steady = true;

_NODISCARD static time_point now() noexcept { // get current time
#if (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)) && !defined(_M_CEE_PURE)
// Implement atomics avoiding <atomic> header dependency
static volatile long long _Cached_freq = LLONG_MAX;
static volatile long long _Cached_ctr_base = LLONG_MAX;
static volatile long long _Cached_result_base = LLONG_MAX;

const long long _Freq_from_cache = _Atomic_load_ll_relaxed(&_Cached_freq);
const long long _Ctr_base = _Atomic_load_ll_relaxed(&_Cached_ctr_base);
const long long _Result_base = _Atomic_load_ll_relaxed(&_Cached_result_base);
if (_Freq_from_cache != LLONG_MAX && _Ctr_base != LLONG_MAX && _Result_base != LLONG_MAX) {
// Fast path
const long long _Ctr = _Query_perf_counter();
return time_point(duration(_Result_base + (_Ctr - _Ctr_base) * period::den / _Freq_from_cache));
}
// Calculate with two divisions to prevent overflow
const long long _Freq = _Query_perf_frequency();
const long long _Ctr = _Query_perf_counter();
const long long _Result = _Scale_large_counter(_Ctr, _Freq);
if (_Atomic_compare_exchange_strong_ll_seq_cst(&_Cached_freq, _Freq, LLONG_MAX)) {
// This is the first result, save current result as base for fast path
_Atomic_compare_exchange_strong_ll_seq_cst(&_Cached_ctr_base, _Ctr, LLONG_MAX);
_Atomic_compare_exchange_strong_ll_seq_cst(&_Cached_result_base, _Result, LLONG_MAX);
}
// if _Result is not saved as first, it is still compatible with fast result
return time_point(duration(_Result));
#else // ^^^ known hardware && !defined(_M_CEE_PURE) / unknown hardware || defined(_M_CEE_PURE) vvv
const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot
const long long _Ctr = _Query_perf_counter();
return time_point(duration(_Scale_large_counter(_Ctr, _Freq)));
#endif // (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)) && !defined(_M_CEE_PURE)
}

private:
_NODISCARD static long long _Scale_large_counter(const long long _Ctr, const long long _Freq) noexcept {
static_assert(period::num == 1, "This assumes period::num == 1.");
// Instead of just having "(_Ctr * period::den) / _Freq",
// the algorithm below prevents overflow when _Ctr is sufficiently large.
Expand All @@ -619,7 +652,7 @@ namespace chrono {
// but the initial value of _Ctr could be large.
const long long _Whole = (_Ctr / _Freq) * period::den;
const long long _Part = (_Ctr % _Freq) * period::den / _Freq;
return time_point(duration(_Whole + _Part));
return _Whole + _Part;
}
};

Expand Down
21 changes: 21 additions & 0 deletions stl/inc/xatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,27 @@ _NODISCARD volatile _Integral* _Atomic_address_as(_Ty& _Source) noexcept {
return &reinterpret_cast<volatile _Integral&>(_Source);
}

// FUNCTION TEMPLATE _Atomic_load_ll_relaxed
#if (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)) && !defined(_M_CEE_PURE)
_NODISCARD inline long long _Atomic_load_ll_relaxed(volatile long long* _Mem) noexcept {
// Copy from _Atomic_storage<_Ty, 8>::load
#if defined(_M_IX86) || defined(_M_ARM64)
return __iso_volatile_load64(_Mem);
#elif defined(_M_X64)
return *_Mem;
#else // _M_ARM
return __ldrexd(_Mem);
#endif // hardware
}

// FUNCTION TEMPLATE _Atomic_compare_exchange_strong_ll_seq_cst
inline bool _Atomic_compare_exchange_strong_ll_seq_cst(
volatile long long* _Mem, long long _Value, long long _Comparand) noexcept {
// Copy from _Atomic_storage<_Ty, 8>::store
return _InterlockedCompareExchange64(_Mem, _Value, _Comparand) == _Comparand;
}
#endif // (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64)) && !defined(_M_CEE_PURE)

_STD_END

#pragma pop_macro("new")
Expand Down