From a456502938d2e1f0ffa07b7064fc10bdaff57a47 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 13:20:12 +0200 Subject: [PATCH 01/15] caching QueryPerformanceFrequency() #448 --- stl/inc/chrono | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 5941ccf9c63..9890c975ed1 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -8,6 +8,7 @@ #define _CHRONO_ #include #if _STL_COMPILER_PREPROCESSOR +#include #include #include #include @@ -609,8 +610,19 @@ namespace chrono { static constexpr bool is_steady = true; _NODISCARD static time_point now() noexcept { // get current time - const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot - const long long _Ctr = _Query_perf_counter(); +#if (defined(_M_ARM) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_X64)) && !defined(_M_CEE_PURE) + // ad-hoc load/store with std::memory_order_relaxed + // avoid dependency on real + volatile long long _Freq_cached = -1; // doesn't change after system boot + long long _Freq = __iso_volatile_load64(&_Freq_cached); + if (_Freq == -1) { + _Freq = _Query_perf_frequency(); + __iso_volatile_store64(&_Freq_cached, _Freq); + } +#else // ^^^ (defined(_M_ARM) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_X64)) && !defined(_M_CEE_PURE) / otherwise vvv + const long long _Freq = _Query_perf_frequency(); +#endif + const long long _Ctr = _Query_perf_counter(); static_assert(period::num == 1, "This assumes period::num == 1."); const long long _Whole = (_Ctr / _Freq) * period::den; const long long _Part = (_Ctr % _Freq) * period::den / _Freq; From 1cac8929cc38e9320277a11ae084d40318e85b26 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 13:30:51 +0200 Subject: [PATCH 02/15] missing static --- stl/inc/chrono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 9890c975ed1..b0c02be441a 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -613,7 +613,7 @@ namespace chrono { #if (defined(_M_ARM) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_X64)) && !defined(_M_CEE_PURE) // ad-hoc load/store with std::memory_order_relaxed // avoid dependency on real - volatile long long _Freq_cached = -1; // doesn't change after system boot + static volatile long long _Freq_cached = -1; // doesn't change after system boot long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); From 8ce02679dbe14899135aa9d76aacf13561096fa5 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 13:45:58 +0200 Subject: [PATCH 03/15] clang format --- stl/inc/chrono | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index b0c02be441a..3af8d1a216a 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -614,12 +614,12 @@ namespace chrono { // ad-hoc load/store with std::memory_order_relaxed // avoid dependency on real static volatile long long _Freq_cached = -1; // doesn't change after system boot - long long _Freq = __iso_volatile_load64(&_Freq_cached); + long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); __iso_volatile_store64(&_Freq_cached, _Freq); } -#else // ^^^ (defined(_M_ARM) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_X64)) && !defined(_M_CEE_PURE) / otherwise vvv +#else const long long _Freq = _Query_perf_frequency(); #endif const long long _Ctr = _Query_perf_counter(); From 244a15b75bc0d56cf632b87eb8029139696a76bd Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 18:06:32 +0200 Subject: [PATCH 04/15] avoid __iso_volatile_store64 --- stl/inc/chrono | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 3af8d1a216a..0e2cb3c3de8 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -611,13 +611,13 @@ namespace chrono { _NODISCARD static time_point now() noexcept { // get current time #if (defined(_M_ARM) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_X64)) && !defined(_M_CEE_PURE) - // ad-hoc load/store with std::memory_order_relaxed + // ad-hoc load/compare_exchange_strong with std::memory_order_relaxed // avoid dependency on real static volatile long long _Freq_cached = -1; // doesn't change after system boot long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); - __iso_volatile_store64(&_Freq_cached, _Freq); + _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); } #else const long long _Freq = _Query_perf_frequency(); From 8b1c5c32bec36524f18833f978172fd614f0d54d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 19:29:46 +0200 Subject: [PATCH 05/15] Suppress a warning that I'm thinking is false --- stl/inc/chrono | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/chrono b/stl/inc/chrono index 0e2cb3c3de8..ff8f3296f77 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -617,6 +617,7 @@ namespace chrono { long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); +#pragma warning (suppress: 28112) // _Freq_cached must always be accessed via an Interlocked function, but it is accessed via __iso_volatile_load64 _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); } #else From abbd3652201d14bcb8b4a1d36d77bbcd00ae03fe Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 19:33:42 +0200 Subject: [PATCH 06/15] clang format --- stl/inc/chrono | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index ff8f3296f77..4d55ad6eb80 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -617,7 +617,9 @@ namespace chrono { long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); -#pragma warning (suppress: 28112) // _Freq_cached must always be accessed via an Interlocked function, but it is accessed via __iso_volatile_load64 + // _Freq_cached must always be accessed via an Interlocked function, + // But it is accessed via __iso_volatile_load64, which is also proper way +#pragma warning (suppress: 28112) _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); } #else From 4250eeb005e757f158b298d3ae5e0a71cc700598 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 19:38:12 +0200 Subject: [PATCH 07/15] clang format --- stl/inc/chrono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index 4d55ad6eb80..a8fd36eab3e 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -619,7 +619,7 @@ namespace chrono { _Freq = _Query_perf_frequency(); // _Freq_cached must always be accessed via an Interlocked function, // But it is accessed via __iso_volatile_load64, which is also proper way -#pragma warning (suppress: 28112) +#pragma warning(suppress : 28112) _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); } #else From 8ae738cb77c9e00d4de173b7508e88d231939d7c Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 20:45:48 +0200 Subject: [PATCH 08/15] Proper place to suppress a warning I'm thinking false --- stl/inc/chrono | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index a8fd36eab3e..cdeb84af26f 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -614,12 +614,12 @@ namespace chrono { // ad-hoc load/compare_exchange_strong with std::memory_order_relaxed // avoid dependency on real static volatile long long _Freq_cached = -1; // doesn't change after system boot + // _Freq_cached must always be accessed via an Interlocked function, + // But it is accessed via __iso_volatile_load64, which is also proper way +#pragma warning(suppress : 28112) long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); - // _Freq_cached must always be accessed via an Interlocked function, - // But it is accessed via __iso_volatile_load64, which is also proper way -#pragma warning(suppress : 28112) _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); } #else From bb746ac674a0bf2bdaee9058921692c84b726d5d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 27 Mar 2020 20:48:47 +0200 Subject: [PATCH 09/15] clang format --- stl/inc/chrono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index cdeb84af26f..e55c5f73553 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -617,7 +617,7 @@ namespace chrono { // _Freq_cached must always be accessed via an Interlocked function, // But it is accessed via __iso_volatile_load64, which is also proper way #pragma warning(suppress : 28112) - long long _Freq = __iso_volatile_load64(&_Freq_cached); + long long _Freq = __iso_volatile_load64(&_Freq_cached); if (_Freq == -1) { _Freq = _Query_perf_frequency(); _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); From e1fb7755e6f84c13f9a225b891f4310013cbe204 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 28 Mar 2020 14:34:45 +0200 Subject: [PATCH 10/15] Move implementation to .cpp --- stl/inc/chrono | 19 ++----------------- stl/src/xtime.cpp | 13 ++++++++++++- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index e55c5f73553..5941ccf9c63 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -8,7 +8,6 @@ #define _CHRONO_ #include #if _STL_COMPILER_PREPROCESSOR -#include #include #include #include @@ -610,22 +609,8 @@ namespace chrono { static constexpr bool is_steady = true; _NODISCARD static time_point now() noexcept { // get current time -#if (defined(_M_ARM) || defined(_M_IX86) || defined(_M_ARM64) || defined(_M_X64)) && !defined(_M_CEE_PURE) - // ad-hoc load/compare_exchange_strong with std::memory_order_relaxed - // avoid dependency on real - static volatile long long _Freq_cached = -1; // doesn't change after system boot - // _Freq_cached must always be accessed via an Interlocked function, - // But it is accessed via __iso_volatile_load64, which is also proper way -#pragma warning(suppress : 28112) - long long _Freq = __iso_volatile_load64(&_Freq_cached); - if (_Freq == -1) { - _Freq = _Query_perf_frequency(); - _InterlockedCompareExchange64(&_Freq_cached, _Freq, -1); - } -#else - const long long _Freq = _Query_perf_frequency(); -#endif - const long long _Ctr = _Query_perf_counter(); + const long long _Freq = _Query_perf_frequency(); // doesn't change after system boot + const long long _Ctr = _Query_perf_counter(); static_assert(period::num == 1, "This assumes period::num == 1."); const long long _Whole = (_Ctr / _Freq) * period::den; const long long _Part = (_Ctr % _Freq) * period::den / _Freq; diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index f39d35031e0..b07ede91cc5 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -3,6 +3,7 @@ // xtime functions +#include #include "awint.h" #include #include @@ -86,12 +87,22 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_counter() { // get current value of return li.QuadPart; } -_CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter +static long long __cdecl _Query_perf_frequency_internal() { // get frequency of performance counter LARGE_INTEGER li; QueryPerformanceFrequency(&li); // always succeeds return li.QuadPart; } +_CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter + static std::atomic freq_cached = 0; + long long freq = freq_cached.load(std::memory_order_relaxed); + if (freq == 0) { + freq = _Query_perf_frequency_internal(); // doesn't change after system boot + freq_cached.store(freq, std::memory_order_relaxed); + } + return freq; +} + _END_EXTERN_C /* From 9312817610fd08070611c11fe289695e6c4aa5d7 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 28 Mar 2020 14:46:15 +0200 Subject: [PATCH 11/15] clang format --- stl/src/xtime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index b07ede91cc5..87a0059c06e 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -3,8 +3,8 @@ // xtime functions -#include #include "awint.h" +#include #include #include #include @@ -94,7 +94,7 @@ static long long __cdecl _Query_perf_frequency_internal() { // get frequency of } _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter - static std::atomic freq_cached = 0; + static std::atomic freq_cached = 0; long long freq = freq_cached.load(std::memory_order_relaxed); if (freq == 0) { freq = _Query_perf_frequency_internal(); // doesn't change after system boot From 44448ef957d23340e066efa56d557b831d3efce5 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 28 Mar 2020 14:48:23 +0200 Subject: [PATCH 12/15] remove unnecessary function --- stl/src/xtime.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index 87a0059c06e..518ff758a01 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -87,17 +87,13 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_counter() { // get current value of return li.QuadPart; } -static long long __cdecl _Query_perf_frequency_internal() { // get frequency of performance counter - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); // always succeeds - return li.QuadPart; -} - _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter static std::atomic freq_cached = 0; long long freq = freq_cached.load(std::memory_order_relaxed); if (freq == 0) { - freq = _Query_perf_frequency_internal(); // doesn't change after system boot + LARGE_INTEGER li; + QueryPerformanceFrequency(&li); // always succeeds + freq = li.QuadPart; // doesn't change after system boot freq_cached.store(freq, std::memory_order_relaxed); } return freq; From d6ea49b98ab834c89ca82f4c3dbc83492123bfe7 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 29 Mar 2020 07:09:59 +0300 Subject: [PATCH 13/15] Restore old code for _M_CEE_PURE --- stl/src/xtime.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index 518ff758a01..c0e27926e82 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -4,7 +4,9 @@ // xtime functions #include "awint.h" +#ifndef _M_CEE_PURE #include +#endif #include #include #include @@ -88,6 +90,7 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_counter() { // get current value of } _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter +#ifndef _M_CEE_PURE static std::atomic freq_cached = 0; long long freq = freq_cached.load(std::memory_order_relaxed); if (freq == 0) { @@ -97,6 +100,11 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of pe freq_cached.store(freq, std::memory_order_relaxed); } return freq; +#else // ^^^ !_M_CEE_PURE / _M_CEE_PURE vvv + LARGE_INTEGER li; + QueryPerformanceFrequency(&li); // always succeeds + return li.QuadPart; +#endif // _M_CEE_PURE } _END_EXTERN_C From f7234f4e8a077c69115c913dae1ebe6ea0e3bd1b Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 30 Mar 2020 21:44:41 -0700 Subject: [PATCH 14/15] Remove unnecessary _M_CEE_PURE guards; xtime.cpp is compiled as native only. --- stl/src/xtime.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index c0e27926e82..518ff758a01 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -4,9 +4,7 @@ // xtime functions #include "awint.h" -#ifndef _M_CEE_PURE #include -#endif #include #include #include @@ -90,7 +88,6 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_counter() { // get current value of } _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter -#ifndef _M_CEE_PURE static std::atomic freq_cached = 0; long long freq = freq_cached.load(std::memory_order_relaxed); if (freq == 0) { @@ -100,11 +97,6 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of pe freq_cached.store(freq, std::memory_order_relaxed); } return freq; -#else // ^^^ !_M_CEE_PURE / _M_CEE_PURE vvv - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); // always succeeds - return li.QuadPart; -#endif // _M_CEE_PURE } _END_EXTERN_C From f10ced4af6fb37ab48501ad644da515c43db3282 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 31 Mar 2020 15:11:53 -0700 Subject: [PATCH 15/15] Use direct-init. --- stl/src/xtime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index 518ff758a01..015e259c766 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -88,8 +88,8 @@ _CRTIMP2_PURE long long __cdecl _Query_perf_counter() { // get current value of } _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() { // get frequency of performance counter - static std::atomic freq_cached = 0; - long long freq = freq_cached.load(std::memory_order_relaxed); + static std::atomic freq_cached{0}; + long long freq = freq_cached.load(std::memory_order_relaxed); if (freq == 0) { LARGE_INTEGER li; QueryPerformanceFrequency(&li); // always succeeds