@@ -62,8 +62,12 @@ namespace {
62
62
#pragma warning(push)
63
63
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
64
64
struct alignas (_STD hardware_destructive_interference_size) _Wait_table_entry {
65
- SRWLOCK _Lock = SRWLOCK_INIT;
66
- _Wait_context _Wait_list_head = {nullptr , &_Wait_list_head, &_Wait_list_head, CONDITION_VARIABLE_INIT};
65
+ SRWLOCK _Lock = SRWLOCK_INIT;
66
+ // Initialize to all zeros, self-link lazily to optimize for space.
67
+ // Since _Wait_table_entry is initialized to all zero bytes,
68
+ // _Atomic_wait_table_entry::wait_table will also be all zero bytes.
69
+ // It can thus can be stored in the .bss section, and not in the actual binary.
70
+ _Wait_context _Wait_list_head = {nullptr , nullptr , nullptr , CONDITION_VARIABLE_INIT};
67
71
68
72
constexpr _Wait_table_entry () noexcept = default ;
69
73
};
@@ -263,6 +267,11 @@ void __stdcall __std_atomic_notify_one_indirect(const void* const _Storage) noex
263
267
auto & _Entry = _Atomic_wait_table_entry (_Storage);
264
268
_SrwLock_guard _Guard (_Entry._Lock );
265
269
_Wait_context* _Context = _Entry._Wait_list_head ._Next ;
270
+
271
+ if (_Context == nullptr ) {
272
+ return ;
273
+ }
274
+
266
275
for (; _Context != &_Entry._Wait_list_head ; _Context = _Context->_Next ) {
267
276
if (_Context->_Storage == _Storage) {
268
277
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the _Context itself
@@ -276,6 +285,11 @@ void __stdcall __std_atomic_notify_all_indirect(const void* const _Storage) noex
276
285
auto & _Entry = _Atomic_wait_table_entry (_Storage);
277
286
_SrwLock_guard _Guard (_Entry._Lock );
278
287
_Wait_context* _Context = _Entry._Wait_list_head ._Next ;
288
+
289
+ if (_Context == nullptr ) {
290
+ return ;
291
+ }
292
+
279
293
for (; _Context != &_Entry._Wait_list_head ; _Context = _Context->_Next ) {
280
294
if (_Context->_Storage == _Storage) {
281
295
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the _Context itself
@@ -289,6 +303,12 @@ int __stdcall __std_atomic_wait_indirect(const void* _Storage, void* _Comparand,
289
303
auto & _Entry = _Atomic_wait_table_entry (_Storage);
290
304
291
305
_SrwLock_guard _Guard (_Entry._Lock );
306
+
307
+ if (_Entry._Wait_list_head ._Next == nullptr ) {
308
+ _Entry._Wait_list_head ._Next = &_Entry._Wait_list_head ;
309
+ _Entry._Wait_list_head ._Prev = &_Entry._Wait_list_head ;
310
+ }
311
+
292
312
_Guarded_wait_context _Context{_Storage, &_Entry._Wait_list_head };
293
313
for (;;) {
294
314
if (!_Are_equal (_Storage, _Comparand, _Size, _Param)) { // note: under lock to prevent lost wakes
0 commit comments