From 1c97fe3340fe806ca3e506cb430c2c6d76f439dd Mon Sep 17 00:00:00 2001 From: crueter Date: Sat, 27 Sep 2025 07:59:24 +0200 Subject: [PATCH] [common] revert "replace Common::BitSet with std::bitset" this commit appears to cause some games to not boot on certain platforms (Linux is unaffected)--needs testing since this may be a linker issue --- src/common/CMakeLists.txt | 1 + src/common/bit_set.h | 86 ++++++++++++++++++++++++++ src/core/hle/kernel/k_priority_queue.h | 29 ++++----- 3 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 src/common/bit_set.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 96ea429e5a..7759ea6a21 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -32,6 +32,7 @@ add_library( atomic_ops.h bit_cast.h bit_field.h + bit_set.h bit_util.h bounded_threadsafe_queue.h cityhash.cpp diff --git a/src/common/bit_set.h b/src/common/bit_set.h new file mode 100644 index 0000000000..74754504be --- /dev/null +++ b/src/common/bit_set.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/alignment.h" +#include "common/bit_util.h" +#include "common/common_types.h" + +namespace Common { + +namespace impl { + +template +class BitSet { + +public: + constexpr BitSet() = default; + + constexpr void SetBit(size_t i) { + this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord); + } + + constexpr void ClearBit(size_t i) { + this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord); + } + + constexpr size_t CountLeadingZero() const { + for (size_t i = 0; i < NumWords; i++) { + if (this->words[i]) { + return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]); + } + } + return FlagsPerWord * NumWords; + } + + constexpr size_t GetNextSet(size_t n) const { + for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) { + Storage word = this->words[i]; + if (!IsAligned(n + 1, FlagsPerWord)) { + word &= GetBitMask(n % FlagsPerWord) - 1; + } + if (word) { + return FlagsPerWord * i + CountLeadingZeroImpl(word); + } + } + return FlagsPerWord * NumWords; + } + +private: + static_assert(std::is_unsigned_v); + static_assert(sizeof(Storage) <= sizeof(u64)); + + static constexpr size_t FlagsPerWord = BitSize(); + static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord; + + static constexpr auto CountLeadingZeroImpl(Storage word) { + return std::countl_zero(static_cast(word)) - + (BitSize() - FlagsPerWord); + } + + static constexpr Storage GetBitMask(size_t bit) { + return Storage(1) << (FlagsPerWord - 1 - bit); + } + + std::array words{}; +}; + +} // namespace impl + +template +using BitSet8 = impl::BitSet; + +template +using BitSet16 = impl::BitSet; + +template +using BitSet32 = impl::BitSet; + +template +using BitSet64 = impl::BitSet; + +} // namespace Common diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index 0ef6bcc32c..26677ec65c 100644 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,11 +5,10 @@ #include #include -#include #include -#include #include "common/assert.h" +#include "common/bit_set.h" #include "common/common_types.h" #include "common/concepts.h" @@ -163,7 +159,7 @@ public: } if (m_queues[priority].PushBack(core, member)) { - m_available_priorities[core].set(std::size_t(priority)); + m_available_priorities[core].SetBit(priority); } } @@ -176,7 +172,7 @@ public: } if (m_queues[priority].PushFront(core, member)) { - m_available_priorities[core].set(std::size_t(priority)); + m_available_priorities[core].SetBit(priority); } } @@ -189,14 +185,14 @@ public: } if (m_queues[priority].Remove(core, member)) { - m_available_priorities[core].reset(std::size_t(priority)); + m_available_priorities[core].ClearBit(priority); } } constexpr Member* GetFront(s32 core) const { ASSERT(IsValidCore(core)); - const s32 priority = s32((~m_available_priorities[core]).count()); + const s32 priority = static_cast(m_available_priorities[core].CountLeadingZero()); if (priority <= LowestPriority) { return m_queues[priority].GetFront(core); } else { @@ -220,14 +216,11 @@ public: Member* next = member->GetPriorityQueueEntry(core).GetNext(); if (next == nullptr) { - s32 priority = member->GetPriority() + 1; - do { - if (m_available_priorities[core][priority]) { - next = m_queues[priority].GetFront(core); - break; - } - ++priority; - } while (priority <= LowestPriority && priority < s32(m_available_priorities[core].size())); + const s32 priority = static_cast( + m_available_priorities[core].GetNextSet(member->GetPriority())); + if (priority <= LowestPriority) { + next = m_queues[priority].GetFront(core); + } } return next; } @@ -257,7 +250,7 @@ public: private: std::array m_queues{}; - std::array, NumCores> m_available_priorities{}; + std::array, NumCores> m_available_priorities{}; }; private: