Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atomic_ref (#2, p0019r8) #843

Merged
merged 145 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from 141 commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
1cf7cad
atomic_ref (#2, p0019r8)
AlexGuteniev May 17, 2020
001e340
clang format, volatile overload
AlexGuteniev May 17, 2020
75a155d
no really `volatile` overload for atomic_ref
AlexGuteniev May 17, 2020
85ba6a2
no really `volatile` overload for atomic_ref
AlexGuteniev May 17, 2020
9d610cc
required_alignment
AlexGuteniev May 17, 2020
857c620
Don't use _Spinlock
AlexGuteniev May 17, 2020
1ca420a
Do use spinlock
AlexGuteniev May 17, 2020
a522d3b
fix build
AlexGuteniev May 17, 2020
25f603b
direction
AlexGuteniev May 17, 2020
85c044e
Pointer to object for atomic ref mutex init
AlexGuteniev May 17, 2020
2cb4d3e
clang format
AlexGuteniev May 17, 2020
c938bf2
Correct base for specializations
AlexGuteniev May 17, 2020
012bf46
basic operations test
AlexGuteniev May 17, 2020
da247a6
Fix spinlock initialization
AlexGuteniev May 17, 2020
0c38cdc
elaborate test
AlexGuteniev May 17, 2020
3e3cd47
better naming
AlexGuteniev May 17, 2020
6fdcf4d
better naming
AlexGuteniev May 17, 2020
f385fa1
warnings fix
AlexGuteniev May 17, 2020
dac5c6a
get back mutable
AlexGuteniev May 17, 2020
c8d38df
clang format
AlexGuteniev May 17, 2020
3cf38d6
satellite
AlexGuteniev May 17, 2020
dd33205
feature
AlexGuteniev May 17, 2020
fc29559
Use SRWLOCK and abandon _Spinlock for atomic_ref
AlexGuteniev May 17, 2020
e219b71
ref
AlexGuteniev May 17, 2020
9229c12
ARM spinlock
AlexGuteniev May 17, 2020
a266baa
clang format
AlexGuteniev May 17, 2020
2f992db
clang format
AlexGuteniev May 17, 2020
24f1f01
found a way to use spinlock pointer for atomic_ref
AlexGuteniev May 17, 2020
b166dd1
clang format
AlexGuteniev May 17, 2020
e3c2331
missing strong CAS
AlexGuteniev May 17, 2020
b4973b3
Consistently use value type
AlexGuteniev May 17, 2020
15bbdbe
Consistently use value type
AlexGuteniev May 17, 2020
4d07c1c
Remove volatile overloads for atomic_ref
AlexGuteniev May 23, 2020
ef2adde
try to define vNext as well
AlexGuteniev May 23, 2020
3b90ac0
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev May 23, 2020
49b7f95
Zero pad for potential future redefinition
AlexGuteniev May 23, 2020
1be9a85
Warn about misuse
AlexGuteniev May 25, 2020
91f3819
clang-format
AlexGuteniev May 25, 2020
f3e9c76
might
AlexGuteniev May 25, 2020
fe2e25f
formatting
AlexGuteniev May 25, 2020
17297a9
drop static check, keep only runtime
AlexGuteniev May 25, 2020
45191a0
drop static check, keep only runtime
AlexGuteniev May 25, 2020
8f18bbe
fix tests pass
AlexGuteniev May 25, 2020
35388d9
Correct _Init_spinlock_for_ref for current ABI
AlexGuteniev May 25, 2020
0ff9148
constexpr
AlexGuteniev May 25, 2020
549a856
clang format, const, noexcept
AlexGuteniev May 25, 2020
cec012a
whitespace
AlexGuteniev May 25, 2020
f9f876c
fix incorrect test, satisfy required alignment
AlexGuteniev May 26, 2020
fed136c
clang format
AlexGuteniev May 26, 2020
a1a34aa
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev May 30, 2020
f59ed29
fail libcxx test for correct reason
AlexGuteniev Jun 9, 2020
7849930
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Jun 30, 2020
a7dd4bb
Merge branch 'master' into atomic_ref
AlexGuteniev Jul 8, 2020
bf1af3f
line ending fix after merge via GitHub web face
AlexGuteniev Jul 8, 2020
a4eb73c
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Jul 9, 2020
5421ee9
Fix merge error
AlexGuteniev Jul 10, 2020
5992ce5
Update stl/inc/atomic
AlexGuteniev Jul 15, 2020
a08ebbf
revive atomic_ref<16 bytes>
AlexGuteniev Jul 17, 2020
db63179
Merge branch 'atomic_ref' of https://github.com/AlexGuteniev/STL into…
AlexGuteniev Jul 17, 2020
5bf9c93
good mutex
AlexGuteniev Jul 17, 2020
8868246
clang format
AlexGuteniev Jul 17, 2020
f35df6b
fix build
AlexGuteniev Jul 17, 2020
64d364e
clang format
AlexGuteniev Jul 17, 2020
2b7bc84
fix build
AlexGuteniev Jul 17, 2020
5829541
implement fallback
AlexGuteniev Jul 17, 2020
68b134f
try to fix tests
AlexGuteniev Jul 17, 2020
c9a3baa
go home clang format you're drunk
AlexGuteniev Jul 17, 2020
94b0990
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Jul 25, 2020
081890d
merge typo fix
AlexGuteniev Jul 25, 2020
a9130fe
merge: fix _Ty with _TVal in padding bits part
AlexGuteniev Jul 25, 2020
48262ad
Implement padding bits for 16 byte type
AlexGuteniev Jul 25, 2020
547e775
test coverage for 16 byte type
AlexGuteniev Jul 25, 2020
297a97e
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 1, 2020
8a81301
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 2, 2020
516a09c
post merge fixes
AlexGuteniev Aug 2, 2020
456ff02
more post merge fixes
AlexGuteniev Aug 2, 2020
0a3b79e
Apply suggestions from code review
AlexGuteniev Aug 2, 2020
74d925b
clang format
AlexGuteniev Aug 2, 2020
6ec6912
typename
AlexGuteniev Aug 2, 2020
a3b1d45
atomic ref wait
AlexGuteniev Aug 3, 2020
7645384
fix cmp 16
AlexGuteniev Aug 3, 2020
e24bc24
better fix cmp 16
AlexGuteniev Aug 3, 2020
4d74aeb
empty change to restart build
AlexGuteniev Aug 3, 2020
abc9673
Don't use _nf for now
AlexGuteniev Aug 3, 2020
fe47a46
copy stuff from <intrin.h>
AlexGuteniev Aug 3, 2020
3ec5506
I don't know how to build on ARM64
AlexGuteniev Aug 3, 2020
a1e3c02
I don't know how to build on ARM64
AlexGuteniev Aug 3, 2020
b477b45
align
AlexGuteniev Aug 3, 2020
5593227
format
AlexGuteniev Aug 3, 2020
4d44049
Billy's review comment
AlexGuteniev Aug 4, 2020
a3b729a
Billy's review comment
AlexGuteniev Aug 4, 2020
9608a3e
arm build
AlexGuteniev Aug 4, 2020
bf59db6
"detection" of cmpxchg16b sililar to woa
AlexGuteniev Aug 4, 2020
8c46780
Ban _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 when _M_ARM64.
BillyONeal Aug 5, 2020
4abebdb
_Spinlock_guard nitpicks.
BillyONeal Aug 5, 2020
690fd0b
Sort msvcp_atomic_wait.src.
BillyONeal Aug 5, 2020
6666848
Fix _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B enforcement on ARM32.
BillyONeal Aug 5, 2020
67b3fb5
Suppress 4324 and ensure entire structure is zeroed.
BillyONeal Aug 5, 2020
318d9c0
Don't define _STD_COMPARE_EXCHANGE_128 for non 64 bit.
BillyONeal Aug 5, 2020
42ea87f
;
AlexGuteniev Aug 5, 2020
db0b368
Apply suggestions from code review
AlexGuteniev Aug 7, 2020
d6cff23
Apply suggestions from code review
AlexGuteniev Aug 7, 2020
3f0fd34
fix atomic_ref interface
AlexGuteniev Aug 7, 2020
da36cb0
Merge branch 'atomic_ref' of https://github.com/AlexGuteniev/STL into…
AlexGuteniev Aug 7, 2020
3fee7e8
clang format
AlexGuteniev Aug 7, 2020
333e585
+store
AlexGuteniev Aug 7, 2020
cc99367
more @STL comments
AlexGuteniev Aug 7, 2020
c583519
Update stl/src/atomic_wait.cpp
AlexGuteniev Aug 7, 2020
ff8a7b4
grammer
AlexGuteniev Aug 7, 2020
909332c
Merge branch 'atomic_ref' of https://github.com/AlexGuteniev/STL into…
AlexGuteniev Aug 7, 2020
508cfd1
more @STL comments
AlexGuteniev Aug 7, 2020
a9e165a
no reinterpret cast to bool
AlexGuteniev Aug 7, 2020
f925380
this is now superfluous
AlexGuteniev Aug 7, 2020
10c1e9e
_MSC_FULL_VER
AlexGuteniev Aug 8, 2020
69f1d82
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 10, 2020
2f8e7d3
exclude shared_ptr from atomic_ref test
AlexGuteniev Aug 10, 2020
3c52354
+pad bits
AlexGuteniev Aug 10, 2020
3653311
correctly align atomic_ref
AlexGuteniev Aug 10, 2020
8ef2426
try to fix intrinsic problem
AlexGuteniev Aug 10, 2020
86e887f
cleanup
AlexGuteniev Aug 10, 2020
b09b8cc
skip _TVal for facade types
AlexGuteniev Aug 10, 2020
600e5ab
consistent cast syntax
AlexGuteniev Aug 10, 2020
05f1f84
correct is_lock_free
AlexGuteniev Aug 10, 2020
73c026a
correct is_lock_free
AlexGuteniev Aug 10, 2020
52700e2
correct is_lock_free
AlexGuteniev Aug 10, 2020
2aab7ba
clang format
AlexGuteniev Aug 10, 2020
69fc773
build fix
AlexGuteniev Aug 10, 2020
1370b5d
reduce transition
AlexGuteniev Aug 10, 2020
0f9978c
Who said it must be CRITICAL_SECTION?
AlexGuteniev Aug 10, 2020
3702d7b
ARM64
AlexGuteniev Aug 10, 2020
8ae82a5
Windows
AlexGuteniev Aug 10, 2020
ca9b076
_STL
AlexGuteniev Aug 10, 2020
2e8638d
clang format
AlexGuteniev Aug 10, 2020
19f596d
space
AlexGuteniev Aug 10, 2020
fc26176
missing space
AlexGuteniev Aug 11, 2020
be20faa
actually no _TVal here already
AlexGuteniev Aug 11, 2020
e6e9ba0
Update stl/inc/yvals_core.h
AlexGuteniev Aug 12, 2020
0def107
STL comments
AlexGuteniev Aug 12, 2020
18d9e8e
nonstatic constexpr
AlexGuteniev Aug 12, 2020
c0d809b
never a reference here
AlexGuteniev Aug 12, 2020
6ccb054
clang format
AlexGuteniev Aug 12, 2020
d3dcda4
fix atomic ref<16 bytes>
AlexGuteniev Aug 12, 2020
ac2ebe7
clang format
AlexGuteniev Aug 12, 2020
60bc35e
update TRANSITION comment
AlexGuteniev Aug 12, 2020
a270733
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 12, 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
937 changes: 683 additions & 254 deletions stl/inc/atomic

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions stl/inc/xatomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

#include <intrin0.h>
#include <type_traits>
#if defined(_WIN64) && (_MSC_FULL_VER < 192829203) // TRANSITION
#include <intrin.h> // Visual Studio 2019 to define 128-bit CAS in <intrin0.h>
#endif // defined(_WIN64) && (_MSC_FULL_VER < 192829203), TRANSITION

#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
Expand Down
31 changes: 31 additions & 0 deletions stl/inc/yvals.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,21 @@ _STL_DISABLE_CLANG_WARNINGS
#define _STL_INTERNAL_STATIC_ASSERT(...)
#endif // _ENABLE_STL_INTERNAL_CHECK

#ifndef _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a use case for this being different than _DEBUG ? OK to leave as is, just curious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinpoint tearing in release, that never happens in debug due to timings and debug allocations

#ifdef _DEBUG
#define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 1
#else // ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv
#define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 0
#endif // _DEBUG
#endif // _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK

#if _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK
#define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _STL_VERIFY(cond, mesg)
#else
#define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _Analysis_assume_(cond)
#endif


#include <use_ansi.h>

#define _WARNING_MESSAGE(NUMBER, MESSAGE) __FILE__ "(" _CRT_STRINGIZE(__LINE__) "): warning " NUMBER ": " MESSAGE
Expand Down Expand Up @@ -314,6 +329,22 @@ _STL_DISABLE_CLANG_WARNINGS
#endif // ^^^ _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 ^^^
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE

#ifndef _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B
#if _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WINBLUE && defined(_WIN64)
#define _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B 1
#else // ^^^ modern 64-bit // less modern or 32-bit vvv
#define _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B 0
#endif // _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WINBLUE && defined(_WIN64)
#endif // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B

#if _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 && defined(_M_ARM64)
#error ARM64 requires _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B to be 1.
#endif // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 && defined(_M_ARM64)

#if _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 && !defined(_WIN64)
#error _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 requires 64-bit.
#endif // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 && !defined(_WIN64)

#ifndef _ALLOW_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE_MISMATCH
#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
#pragma detect_mismatch("_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE", "1")
Expand Down
20 changes: 16 additions & 4 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
// Other C++17 deprecation warnings

// _HAS_CXX20 directly controls:
// P0019R8 atomic_ref
// P0020R6 atomic<float>, atomic<double>, atomic<long double>
// P0122R7 <span>
// P0202R3 constexpr For <algorithm> And exchange()
Expand All @@ -147,6 +148,7 @@
// P0482R6 Library Support For char8_t
// (mbrtoc8 and c8rtomb not yet implemented)
// P0487R1 Fixing operator>>(basic_istream&, CharT*)
// P0528R3 Atomic Compare-And-Exchange With Padding Bits
// P0550R2 remove_cvref
// P0553R4 <bit> Rotating And Counting Functions
// P0556R3 <bit> Integral Power-Of-2 Operations (renamed by P1956R1)
Expand Down Expand Up @@ -182,6 +184,9 @@
// (except the std::invoke function which is implemented in C++17)
// P1085R2 Removing span Comparisons
// P1115R3 erase()/erase_if() Return size_type
// P1123R0 Atomic Compare-And-Exchange With Padding Bits For atomic_ref
// P1135R6 The C++20 Synchronization Library
// (partially implemented)
// P1207R4 Movability Of Single-Pass Iterators
// (partially implemented)
// P1209R0 erase_if(), erase()
Expand All @@ -207,6 +212,7 @@
// P1907R2 ranges::ssize
// P1956R1 <bit> has_single_bit(), bit_ceil(), bit_floor(), bit_width()
// P1959R0 Removing weak_equality And strong_equality
// P1960R0 atomic_ref Cleanup
// P1964R2 Replacing boolean With boolean-testable
// P1976R2 Explicit Constructors For Fixed-Extent span From Dynamic-Extent Ranges
// P2091R0 Fixing Issues With Range Access CPOs
Expand Down Expand Up @@ -1137,6 +1143,7 @@
#define __cpp_lib_atomic_flag_test 201907L
#define __cpp_lib_atomic_float 201711L
#define __cpp_lib_atomic_lock_free_type_aliases 201907L
#define __cpp_lib_atomic_ref 201806L
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
#define __cpp_lib_atomic_shared_ptr 201711L
#define __cpp_lib_atomic_wait 201907L
#define __cpp_lib_bind_front 201907L
Expand Down Expand Up @@ -1262,13 +1269,18 @@ compiler option, or define _ALLOW_RTCc_IN_STL to acknowledge that you have recei
#error In yvals_core.h, defined(MRTDLL) implies defined(_M_CEE_PURE); !defined(_M_CEE_PURE) implies !defined(MRTDLL)
#endif // defined(MRTDLL) && !defined(_M_CEE_PURE)

#define _STL_WIN32_WINNT_WINXP 0x0501 // _WIN32_WINNT_WINXP from sdkddkver.h
#define _STL_WIN32_WINNT_VISTA 0x0600 // _WIN32_WINNT_VISTA from sdkddkver.h
#define _STL_WIN32_WINNT_WIN8 0x0602 // _WIN32_WINNT_WIN8 from sdkddkver.h
#define _STL_WIN32_WINNT_WINXP 0x0501 // _WIN32_WINNT_WINXP from sdkddkver.h
#define _STL_WIN32_WINNT_VISTA 0x0600 // _WIN32_WINNT_VISTA from sdkddkver.h
#define _STL_WIN32_WINNT_WIN8 0x0602 // _WIN32_WINNT_WIN8 from sdkddkver.h
#define _STL_WIN32_WINNT_WINBLUE 0x0603 // _WIN32_WINNT_WINBLUE from sdkddkver.h
#define _STL_WIN32_WINNT_WIN10 0x0A00 // _WIN32_WINNT_WIN10 from sdkddkver.h

// Note that the STL DLL builds will set this to XP for ABI compatibility with VS2015 which supported XP.
#ifndef _STL_WIN32_WINNT
#if defined(_M_ARM) || defined(_M_ARM64) || defined(_ONECORE) || defined(_CRT_APP)
#if defined(_M_ARM64)
// The first ARM64 Windows was Windows 10
#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN10
#elif defined(_M_ARM) || defined(_ONECORE) || defined(_CRT_APP)
// The first ARM or OneCore or App Windows was Windows 8
#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN8
#else // ^^^ default to Win8 // default to Vista vvv
Expand Down
76 changes: 76 additions & 0 deletions stl/src/atomic_wait.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,24 @@ namespace {
}
}
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE

_NODISCARD unsigned char __std_atomic_compare_exchange_128_fallback(_Inout_bytecount_(16) long long* _Destination,
_In_ long long _ExchangeHigh, _In_ long long _ExchangeLow,
_Inout_bytecount_(16) long long* _ComparandResult) noexcept {
static SRWLOCK _Mtx = SRWLOCK_INIT;
_SrwLock_guard _Guard{_Mtx};
if (_Destination[0] == _ComparandResult[0] && _Destination[1] == _ComparandResult[1]) {
_ComparandResult[0] = _Destination[0];
_ComparandResult[1] = _Destination[1];
_Destination[0] = _ExchangeLow;
_Destination[1] = _ExchangeHigh;
return static_cast<unsigned char>(true);
} else {
_ComparandResult[0] = _Destination[0];
_ComparandResult[1] = _Destination[1];
return static_cast<unsigned char>(false);
}
}
} // unnamed namespace


Expand Down Expand Up @@ -331,4 +349,62 @@ __std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_lev
return _Acquire_wait_functions();
#endif // !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
}

#pragma warning(push)
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
_Smtx_t* __stdcall __std_atomic_get_mutex(const void* const _Key) noexcept {
constexpr size_t _Table_size_power = 8;
constexpr size_t _Table_size = 1 << _Table_size_power;
constexpr size_t _Table_index_mask = _Table_size - 1;

struct alignas(std::hardware_destructive_interference_size) _Table_entry {
_Smtx_t _Mutex;
};

static _Table_entry _Table[_Table_size]{};

auto _Index = reinterpret_cast<std::uintptr_t>(_Key);
_Index ^= _Index >> (_Table_size_power * 2);
_Index ^= _Index >> _Table_size_power;
return &_Table[_Index & _Table_index_mask]._Mutex;
}
#pragma warning(pop)

_NODISCARD unsigned char __stdcall __std_atomic_compare_exchange_128(_Inout_bytecount_(16) long long* _Destination,
_In_ long long _ExchangeHigh, _In_ long long _ExchangeLow,
_Inout_bytecount_(16) long long* _ComparandResult) noexcept {
#if !defined(_WIN64)
return __std_atomic_compare_exchange_128_fallback(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
#elif _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1
return _InterlockedCompareExchange128(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
#else // ^^^ _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 vvv
if (__std_atomic_has_cmpxchg16b()) {
return _InterlockedCompareExchange128(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
}

return __std_atomic_compare_exchange_128_fallback(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
#endif // ^^^ _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0
}

_NODISCARD char __stdcall __std_atomic_has_cmpxchg16b() noexcept {
#if !defined(_WIN64)
return false;
#elif _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1
return true;
#else // ^^^ _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 1 // _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 vvv
constexpr char _Cmpxchg_Absent = 0;
constexpr char _Cmpxchg_Present = 1;
constexpr char _Cmpxchg_Unknown = 2;

static std::atomic<char> _Cached_value{_Cmpxchg_Unknown};

char _Value = _Cached_value.load(std::memory_order_relaxed);
if (_Value == _Cmpxchg_Unknown) {
_Value = IsProcessorFeaturePresent(PF_COMPARE_EXCHANGE128) ? _Cmpxchg_Present : _Cmpxchg_Absent;
_Cached_value.store(_Value, std::memory_order_relaxed);
}

return _Value;
#endif // ^^^ _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0
}
_END_EXTERN_C
7 changes: 5 additions & 2 deletions stl/src/msvcp_atomic_wait.src
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
LIBRARY LIBRARYNAME

EXPORTS
__std_atomic_wait_get_deadline
__std_atomic_wait_get_remaining_timeout
__std_atomic_compare_exchange_128
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BillyONeal Is there a list of exports that we need to update for the "have the exports changed" build-time test? (I think that might still be MSVC-internal.) Are we running such a check against the atomic_wait satellite yet?

__std_atomic_get_mutex
__std_atomic_has_cmpxchg16b
__std_atomic_notify_all_direct
__std_atomic_notify_all_indirect
__std_atomic_notify_one_direct
__std_atomic_notify_one_indirect
__std_atomic_set_api_level
__std_atomic_wait_direct
__std_atomic_wait_get_deadline
__std_atomic_wait_get_remaining_timeout
__std_atomic_wait_indirect
__std_bulk_submit_threadpool_work
__std_close_threadpool_work
Expand Down
4 changes: 1 addition & 3 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ std/containers/unord/unord.map/unord.map.modifiers/insert_and_emplace_allocator_
std/containers/unord/unord.set/insert_and_emplace_allocator_requirements.pass.cpp FAIL

# libc++ doesn't yet implement P1423R3, so it expects an old value for `__cpp_lib_char8_t`
std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/istream.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/limits.version.pass.cpp FAIL
Expand Down Expand Up @@ -252,9 +253,6 @@ std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKI


# *** MISSING STL FEATURES ***
# C++20 P0019R8 "atomic_ref"
std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp FAIL

# C++20 P0355R7 "<chrono> Calendars And Time Zones"
std/utilities/time/days.pass.cpp FAIL
std/utilities/time/months.pass.cpp FAIL
Expand Down
4 changes: 1 addition & 3 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ containers\unord\unord.map\unord.map.modifiers\insert_and_emplace_allocator_requ
containers\unord\unord.set\insert_and_emplace_allocator_requirements.pass.cpp

# libc++ doesn't yet implement P1423R3, so it expects an old value for `__cpp_lib_char8_t`
language.support\support.limits\support.limits.general\atomic.version.pass.cpp
language.support\support.limits\support.limits.general\filesystem.version.pass.cpp
language.support\support.limits\support.limits.general\istream.version.pass.cpp
language.support\support.limits\support.limits.general\limits.version.pass.cpp
Expand Down Expand Up @@ -252,9 +253,6 @@ utilities\memory\default.allocator\allocator.members\allocate.verify.cpp


# *** MISSING STL FEATURES ***
# C++20 P0019R8 "atomic_ref"
language.support\support.limits\support.limits.general\atomic.version.pass.cpp

# C++20 P0355R7 "<chrono> Calendars And Time Zones"
utilities\time\days.pass.cpp
utilities\time\months.pass.cpp
Expand Down
58 changes: 47 additions & 11 deletions tests/std/include/test_atomic_wait.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include <string.h>
#include <thread>

template <class UnderlyingType>
void test_atomic_wait_func(const UnderlyingType old_value, const UnderlyingType new_value,
template <template <class> class Template, class UnderlyingType>
void test_atomic_wait_func_impl(UnderlyingType& old_value, const UnderlyingType new_value,
const std::chrono::steady_clock::duration waiting_duration) {
constexpr int seq_max_size = 10;
char seq[seq_max_size + 1];
Expand All @@ -22,7 +22,7 @@ void test_atomic_wait_func(const UnderlyingType old_value, const UnderlyingType
*p = ch;
};

std::atomic<UnderlyingType> a{old_value};
Template<UnderlyingType> a(old_value);
a.wait(new_value);

add_seq('1');
Expand Down Expand Up @@ -64,9 +64,24 @@ void test_atomic_wait_func(const UnderlyingType old_value, const UnderlyingType
}

template <class UnderlyingType>
void test_notify_all_notifies_all(const UnderlyingType old_value, const UnderlyingType new_value,
void test_atomic_wait_func(UnderlyingType old_value, const UnderlyingType new_value,
const std::chrono::steady_clock::duration waiting_duration) {
test_atomic_wait_func_impl<std::atomic, UnderlyingType>(old_value, new_value, waiting_duration);
alignas(std::atomic_ref<UnderlyingType>::required_alignment) UnderlyingType old_value_for_ref = old_value;
test_atomic_wait_func_impl<std::atomic_ref, UnderlyingType>(old_value_for_ref, new_value, waiting_duration);
}

template <class UnderlyingType>
void test_atomic_wait_func_ptr(UnderlyingType old_value, const UnderlyingType new_value,
const std::chrono::steady_clock::duration waiting_duration) {
std::atomic<UnderlyingType> c{old_value};
test_atomic_wait_func_impl<std::atomic, UnderlyingType>(old_value, new_value, waiting_duration);
}


template <template <class> class Template, class UnderlyingType>
void test_notify_all_notifies_all_impl(UnderlyingType& old_value, const UnderlyingType new_value,
const std::chrono::steady_clock::duration waiting_duration) {
Template<UnderlyingType> c(old_value);
const auto waitFn = [&c, old_value] { c.wait(old_value); };

std::thread w1{waitFn};
Expand All @@ -83,16 +98,31 @@ void test_notify_all_notifies_all(const UnderlyingType old_value, const Underlyi
}

template <class UnderlyingType>
void test_pad_bits(const std::chrono::steady_clock::duration waiting_duration) {
UnderlyingType old_value;
void test_notify_all_notifies_all(UnderlyingType old_value, const UnderlyingType new_value,
const std::chrono::steady_clock::duration waiting_duration) {
test_notify_all_notifies_all_impl<std::atomic, UnderlyingType>(old_value, new_value, waiting_duration);
alignas(std::atomic_ref<UnderlyingType>::required_alignment) UnderlyingType old_value_for_ref = old_value;
test_notify_all_notifies_all_impl<std::atomic_ref, UnderlyingType>(old_value_for_ref, new_value, waiting_duration);
}

template <class UnderlyingType>
void test_notify_all_notifies_all_ptr(UnderlyingType old_value, const UnderlyingType new_value,
const std::chrono::steady_clock::duration waiting_duration) {
test_notify_all_notifies_all_impl<std::atomic, UnderlyingType>(old_value, new_value, waiting_duration);
}


template <template <class> class Template, class UnderlyingType>
void test_pad_bits_impl(const std::chrono::steady_clock::duration waiting_duration) {
alignas(std::atomic_ref<UnderlyingType>::required_alignment) UnderlyingType old_value;
memset(&old_value, 0x66, sizeof(UnderlyingType));
old_value.set(1);

UnderlyingType same_old_value;
memset(&same_old_value, 0x99, sizeof(UnderlyingType));
same_old_value.set(1);

std::atomic<UnderlyingType> c(old_value);
Template<UnderlyingType> c(old_value);

bool trigger = false;
const auto waitFn = [&c, same_old_value, &trigger] {
Expand Down Expand Up @@ -123,6 +153,12 @@ void test_pad_bits(const std::chrono::steady_clock::duration waiting_duration) {
w1.join();
}

template <class UnderlyingType>
void test_pad_bits(const std::chrono::steady_clock::duration waiting_duration) {
test_pad_bits_impl<std::atomic, UnderlyingType>(waiting_duration);
test_pad_bits_impl<std::atomic_ref, UnderlyingType>(waiting_duration);
}

struct two_shorts {
short a;
short b;
Expand Down Expand Up @@ -182,9 +218,9 @@ inline void test_atomic_wait() {
test_atomic_wait_func(three_chars{1, 1, 3}, three_chars{1, 2, 3}, waiting_duration);
test_atomic_wait_func(big_char_like{'a'}, big_char_like{'b'}, waiting_duration);

test_atomic_wait_func(std::make_shared<int>('a'), std::make_shared<int>('b'), waiting_duration);
test_atomic_wait_func(
std::weak_ptr{std::make_shared<int>('a')}, std::weak_ptr{std::make_shared<int>('b')}, waiting_duration);
test_atomic_wait_func_ptr(std::make_shared<int>('a'), std::make_shared<int>('a'), waiting_duration);
test_atomic_wait_func_ptr(
std::weak_ptr{std::make_shared<int>('a')}, std::weak_ptr{std::make_shared<int>('a')}, waiting_duration);

test_notify_all_notifies_all<char>(1, 2, waiting_duration);
test_notify_all_notifies_all<signed char>(1, 2, waiting_duration);
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ tests\GH_001017_discrete_distribution_out_of_range
tests\GH_001086_partial_sort_copy
tests\LWG2597_complex_branch_cut
tests\LWG3018_shared_ptr_function
tests\P0019R8_atomic_ref
tests\P0024R2_parallel_algorithms_adjacent_difference
tests\P0024R2_parallel_algorithms_adjacent_find
tests\P0024R2_parallel_algorithms_all_of
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0019R8_atomic_ref/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
Loading