Browse Source

[dynarmic] reduce exclusive monitor overhead

Signed-off-by: lizzie <lizzie@eden-emu.dev>
pull/203/head
lizzie 7 months ago
committed by crueter
parent
commit
6735a15433
  1. 2
      src/core/hardware_properties.h
  2. 2
      src/dynarmic/src/dynarmic/backend/arm64/exclusive_monitor.cpp
  3. 12
      src/dynarmic/src/dynarmic/backend/x64/exclusive_monitor.cpp
  4. 5
      src/dynarmic/src/dynarmic/common/spin_lock.h
  5. 4
      src/dynarmic/src/dynarmic/common/spin_lock_arm64.cpp
  6. 4
      src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp
  7. 8
      src/dynarmic/src/dynarmic/interface/exclusive_monitor.h

2
src/core/hardware_properties.h

@ -15,7 +15,7 @@ namespace Hardware {
constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz
constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores - sync with dynarmic exclusive_monitor.h
// Virtual to Physical core map. // Virtual to Physical core map.
constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{ constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{

2
src/dynarmic/src/dynarmic/backend/arm64/exclusive_monitor.cpp

@ -14,7 +14,7 @@
namespace Dynarmic { namespace Dynarmic {
ExclusiveMonitor::ExclusiveMonitor(size_t processor_count)
ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count)
: exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {} : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {}
size_t ExclusiveMonitor::GetProcessorCount() const { size_t ExclusiveMonitor::GetProcessorCount() const {

12
src/dynarmic/src/dynarmic/backend/x64/exclusive_monitor.cpp

@ -14,7 +14,7 @@
namespace Dynarmic { namespace Dynarmic {
ExclusiveMonitor::ExclusiveMonitor(size_t processor_count)
ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count)
: exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {} : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {}
size_t ExclusiveMonitor::GetProcessorCount() const { size_t ExclusiveMonitor::GetProcessorCount() const {
@ -29,20 +29,16 @@ void ExclusiveMonitor::Unlock() {
lock.Unlock(); lock.Unlock();
} }
bool ExclusiveMonitor::CheckAndClear(size_t processor_id, VAddr address) {
bool ExclusiveMonitor::CheckAndClear(std::size_t processor_id, VAddr address) {
const VAddr masked_address = address & RESERVATION_GRANULE_MASK; const VAddr masked_address = address & RESERVATION_GRANULE_MASK;
Lock(); Lock();
if (exclusive_addresses[processor_id] != masked_address) { if (exclusive_addresses[processor_id] != masked_address) {
Unlock(); Unlock();
return false; return false;
} }
for (VAddr& other_address : exclusive_addresses) {
if (other_address == masked_address) {
for (VAddr& other_address : exclusive_addresses)
if (other_address == masked_address)
other_address = INVALID_EXCLUSIVE_ADDRESS; other_address = INVALID_EXCLUSIVE_ADDRESS;
}
}
return true; return true;
} }

5
src/dynarmic/src/dynarmic/common/spin_lock.h

@ -8,9 +8,8 @@
namespace Dynarmic { namespace Dynarmic {
struct SpinLock { struct SpinLock {
void Lock();
void Unlock();
void Lock() noexcept;
void Unlock() noexcept;
volatile int storage = 0; volatile int storage = 0;
}; };

4
src/dynarmic/src/dynarmic/common/spin_lock_arm64.cpp

@ -73,12 +73,12 @@ void SpinLockImpl::Initialize() {
} // namespace } // namespace
void SpinLock::Lock() {
void SpinLock::Lock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl); std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.lock(&storage); impl.lock(&storage);
} }
void SpinLock::Unlock() {
void SpinLock::Unlock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl); std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.unlock(&storage); impl.unlock(&storage);
} }

4
src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp

@ -62,12 +62,12 @@ void SpinLockImpl::Initialize() {
} // namespace } // namespace
void SpinLock::Lock() {
void SpinLock::Lock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl); std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.lock(&storage); impl.lock(&storage);
} }
void SpinLock::Unlock() {
void SpinLock::Unlock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl); std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.unlock(&storage); impl.unlock(&storage);
} }

8
src/dynarmic/src/dynarmic/interface/exclusive_monitor.h

@ -6,11 +6,10 @@
#pragma once #pragma once
#include <array> #include <array>
#include <atomic>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <vector>
#include <boost/container/static_vector.hpp>
#include <dynarmic/common/spin_lock.h> #include <dynarmic/common/spin_lock.h>
@ -80,9 +79,10 @@ private:
static constexpr VAddr RESERVATION_GRANULE_MASK = 0xFFFF'FFFF'FFFF'FFFFull; static constexpr VAddr RESERVATION_GRANULE_MASK = 0xFFFF'FFFF'FFFF'FFFFull;
static constexpr VAddr INVALID_EXCLUSIVE_ADDRESS = 0xDEAD'DEAD'DEAD'DEADull; static constexpr VAddr INVALID_EXCLUSIVE_ADDRESS = 0xDEAD'DEAD'DEAD'DEADull;
static constexpr size_t MAX_NUM_CPU_CORES = 4; // Sync with src/core/hardware_properties
boost::container::static_vector<VAddr, MAX_NUM_CPU_CORES> exclusive_addresses;
boost::container::static_vector<Vector, MAX_NUM_CPU_CORES> exclusive_values;
SpinLock lock; SpinLock lock;
std::vector<VAddr> exclusive_addresses;
std::vector<Vector> exclusive_values;
}; };
} // namespace Dynarmic } // namespace Dynarmic
Loading…
Cancel
Save