atomic.hpp: fix signal saturation logic

Make sure to notify_all at max signal count.
This commit is contained in:
Nekotekina 2019-09-09 05:28:02 +03:00
parent 92a75cfa80
commit 67f31c17d1

View file

@ -284,6 +284,8 @@ void atomic_storage_futex::notify_one(const void* data)
atomic_t<u64>& entry = s_hashtable[iptr % s_hashtable_size]; atomic_t<u64>& entry = s_hashtable[iptr % s_hashtable_size];
bool fallback = false;
const auto [prev, ok] = entry.fetch_op([&](u64& value) const auto [prev, ok] = entry.fetch_op([&](u64& value)
{ {
if (value & s_waiter_mask && (value & s_pointer_mask) == (iptr & s_pointer_mask)) if (value & s_waiter_mask && (value & s_pointer_mask) == (iptr & s_pointer_mask))
@ -305,30 +307,41 @@ void atomic_storage_futex::notify_one(const void* data)
} }
value += s_signal_mask & -s_signal_mask; value += s_signal_mask & -s_signal_mask;
if ((value & s_signal_mask) == s_signal_mask)
{
// Signal will overflow, fallback
fallback = true;
return false;
}
#endif #endif
return true; return true;
} }
if (value & s_waiter_mask && (value & s_pointer_mask) == s_pointer_mask)
{
// Collision, notify everything
fallback = true;
}
return false; return false;
}); });
if (fallback)
{
notify_all(data);
return;
}
if (ok) if (ok)
{ {
#ifdef _WIN32 #ifdef _WIN32
NtReleaseKeyedEvent(nullptr, &entry, false, nullptr); NtReleaseKeyedEvent(nullptr, &entry, false, nullptr);
return;
#else #else
futex(reinterpret_cast<char*>(&entry) + 4 * IS_BE_MACHINE, FUTEX_WAKE_PRIVATE, 1); futex(reinterpret_cast<char*>(&entry) + 4 * IS_BE_MACHINE, FUTEX_WAKE_PRIVATE, 1);
return;
#endif #endif
} }
if ((prev & s_pointer_mask) == s_pointer_mask)
{
// Collision, notify everything
notify_all(data);
}
} }
void atomic_storage_futex::notify_all(const void* data) void atomic_storage_futex::notify_all(const void* data)