From 9f3277540ad85a25d8b796d271155bf59c0484a8 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 17 Jun 2020 10:28:24 +0100 Subject: [PATCH] Merge A32 and A64 exclusive monitors --- include/dynarmic/A32/config.h | 5 +- include/dynarmic/A32/exclusive_monitor.h | 81 ------------------- include/dynarmic/A64/config.h | 6 +- .../dynarmic/{A64 => }/exclusive_monitor.h | 2 - src/CMakeLists.txt | 5 +- src/backend/x64/a32_emit_x64.cpp | 2 +- src/backend/x64/a32_exclusive_monitor.cpp | 62 -------------- src/backend/x64/a64_emit_x64.cpp | 2 +- ...sive_monitor.cpp => exclusive_monitor.cpp} | 5 +- tests/A64/a64.cpp | 4 +- 10 files changed, 15 insertions(+), 159 deletions(-) delete mode 100644 include/dynarmic/A32/exclusive_monitor.h rename include/dynarmic/{A64 => }/exclusive_monitor.h (98%) delete mode 100644 src/backend/x64/a32_exclusive_monitor.cpp rename src/backend/x64/{a64_exclusive_monitor.cpp => exclusive_monitor.cpp} (94%) diff --git a/include/dynarmic/A32/config.h b/include/dynarmic/A32/config.h index 6d96c5a4..1f2e0314 100644 --- a/include/dynarmic/A32/config.h +++ b/include/dynarmic/A32/config.h @@ -10,13 +10,16 @@ #include #include +namespace Dynarmic { +class ExclusiveMonitor; +} // namespace Dynarmic + namespace Dynarmic { namespace A32 { using VAddr = std::uint32_t; class Coprocessor; -class ExclusiveMonitor; enum class Exception { /// An UndefinedFault occured due to executing instruction with an unallocated encoding diff --git a/include/dynarmic/A32/exclusive_monitor.h b/include/dynarmic/A32/exclusive_monitor.h deleted file mode 100644 index 65464550..00000000 --- a/include/dynarmic/A32/exclusive_monitor.h +++ /dev/null @@ -1,81 +0,0 @@ -/* This file is part of the dynarmic project. - * Copyright (c) 2018 MerryMage - * SPDX-License-Identifier: 0BSD - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace Dynarmic { -namespace A32 { - -using VAddr = std::uint32_t; - -class ExclusiveMonitor { -public: - /// @param processor_count Maximum number of processors using this global - /// exclusive monitor. Each processor must have a - /// unique id. - explicit ExclusiveMonitor(size_t processor_count); - - size_t GetProcessorCount() const; - - /// Marks a region containing [address, address+size) to be exclusive to - /// processor processor_id. - template - T ReadAndMark(size_t processor_id, VAddr address, Function op) { - static_assert(std::is_trivially_copyable_v); - const VAddr masked_address = address; - - Lock(); - exclusive_addresses[processor_id] = masked_address; - const T value = op(); - std::memcpy(&exclusive_values[processor_id], &value, sizeof(T)); - Unlock(); - return value; - } - - /// Checks to see if processor processor_id has exclusive access to the - /// specified region. If it does, executes the operation then clears - /// the exclusive state for processors if their exclusive region(s) - /// contain [address, address+size). - template - bool DoExclusiveOperation(size_t processor_id, VAddr address, Function op) { - static_assert(std::is_trivially_copyable_v); - if (!CheckAndClear(processor_id, address)) { - return false; - } - - T saved_value; - std::memcpy(&saved_value, &exclusive_values[processor_id], sizeof(T)); - const bool result = op(saved_value); - - Unlock(); - return result; - } - - /// Unmark everything. - void Clear(); - /// Unmark processor id - void ClearProcessor(size_t processor_id); - -private: - bool CheckAndClear(size_t processor_id, VAddr address); - - void Lock(); - void Unlock(); - - static constexpr VAddr INVALID_EXCLUSIVE_ADDRESS = 0xDEADDEAD; - std::atomic_flag is_locked; - std::vector exclusive_addresses; - std::vector exclusive_values; -}; - -} // namespace A32 -} // namespace Dynarmic diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index e3c3de26..3bfdb2f0 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -10,6 +10,10 @@ #include #include +namespace Dynarmic { +class ExclusiveMonitor; +} // namespace Dynarmic + namespace Dynarmic { namespace A64 { @@ -114,8 +118,6 @@ struct UserCallbacks { virtual std::uint64_t GetCNTPCT() = 0; }; -class ExclusiveMonitor; - struct UserConfig { UserCallbacks* callbacks; diff --git a/include/dynarmic/A64/exclusive_monitor.h b/include/dynarmic/exclusive_monitor.h similarity index 98% rename from include/dynarmic/A64/exclusive_monitor.h rename to include/dynarmic/exclusive_monitor.h index 3033d541..9314cccb 100644 --- a/include/dynarmic/A64/exclusive_monitor.h +++ b/include/dynarmic/exclusive_monitor.h @@ -13,7 +13,6 @@ #include namespace Dynarmic { -namespace A64 { using VAddr = std::uint64_t; using Vector = std::array; @@ -79,5 +78,4 @@ private: std::vector exclusive_values; }; -} // namespace A64 } // namespace Dynarmic diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3e87e5b9..49837ea9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ add_library(dynarmic ../include/dynarmic/A32/disassembler.h ../include/dynarmic/A64/a64.h ../include/dynarmic/A64/config.h - ../include/dynarmic/A64/exclusive_monitor.h + ../include/dynarmic/exclusive_monitor.h common/assert.cpp common/assert.h common/bit_util.h @@ -259,6 +259,7 @@ if (ARCHITECTURE_x86_64) backend/x64/emit_x64_vector_floating_point.cpp backend/x64/emit_x64_vector_saturation.cpp backend/x64/exception_handler.h + backend/x64/exclusive_monitor.cpp backend/x64/hostloc.cpp backend/x64/hostloc.h backend/x64/jitstate_info.h @@ -273,7 +274,6 @@ if (ARCHITECTURE_x86_64) target_sources(dynarmic PRIVATE backend/x64/a32_emit_x64.cpp backend/x64/a32_emit_x64.h - backend/x64/a32_exclusive_monitor.cpp backend/x64/a32_interface.cpp backend/x64/a32_jitstate.cpp backend/x64/a32_jitstate.h @@ -284,7 +284,6 @@ if (ARCHITECTURE_x86_64) target_sources(dynarmic PRIVATE backend/x64/a64_emit_x64.cpp backend/x64/a64_emit_x64.h - backend/x64/a64_exclusive_monitor.cpp backend/x64/a64_interface.cpp backend/x64/a64_jitstate.cpp backend/x64/a64_jitstate.h diff --git a/src/backend/x64/a32_emit_x64.cpp b/src/backend/x64/a32_emit_x64.cpp index f4bcc3a4..febed8c5 100644 --- a/src/backend/x64/a32_emit_x64.cpp +++ b/src/backend/x64/a32_emit_x64.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include "backend/x64/a32_emit_x64.h" #include "backend/x64/a32_jitstate.h" diff --git a/src/backend/x64/a32_exclusive_monitor.cpp b/src/backend/x64/a32_exclusive_monitor.cpp deleted file mode 100644 index ada26a9c..00000000 --- a/src/backend/x64/a32_exclusive_monitor.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* This file is part of the dynarmic project. - * Copyright (c) 2018 MerryMage - * SPDX-License-Identifier: 0BSD - */ - -#include - -#include -#include "common/assert.h" - -namespace Dynarmic { -namespace A32 { - -ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) : - exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) { - Unlock(); -} - -size_t ExclusiveMonitor::GetProcessorCount() const { - return exclusive_addresses.size(); -} - -void ExclusiveMonitor::Lock() { - while (is_locked.test_and_set(std::memory_order_acquire)) {} -} - -void ExclusiveMonitor::Unlock() { - is_locked.clear(std::memory_order_release); -} - -bool ExclusiveMonitor::CheckAndClear(size_t processor_id, VAddr address) { - const VAddr masked_address = address; - - Lock(); - if (exclusive_addresses[processor_id] != masked_address) { - Unlock(); - return false; - } - - for (VAddr& other_address : exclusive_addresses) { - if (other_address == masked_address) { - other_address = INVALID_EXCLUSIVE_ADDRESS; - } - } - return true; -} - -void ExclusiveMonitor::Clear() { - Lock(); - std::fill(exclusive_addresses.begin(), exclusive_addresses.end(), INVALID_EXCLUSIVE_ADDRESS); - Unlock(); -} - -void ExclusiveMonitor::ClearProcessor(size_t processor_id) { - Lock(); - exclusive_addresses[processor_id] = INVALID_EXCLUSIVE_ADDRESS; - Unlock(); -} - - -} // namespace A32 -} // namespace Dynarmic diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index 8950d3b4..9586254d 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include "backend/x64/a64_emit_x64.h" #include "backend/x64/a64_jitstate.h" diff --git a/src/backend/x64/a64_exclusive_monitor.cpp b/src/backend/x64/exclusive_monitor.cpp similarity index 94% rename from src/backend/x64/a64_exclusive_monitor.cpp rename to src/backend/x64/exclusive_monitor.cpp index a1a2d22f..c5c3ba39 100644 --- a/src/backend/x64/a64_exclusive_monitor.cpp +++ b/src/backend/x64/exclusive_monitor.cpp @@ -5,11 +5,10 @@ #include -#include +#include #include "common/assert.h" namespace Dynarmic { -namespace A64 { ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) { @@ -57,6 +56,4 @@ void ExclusiveMonitor::ClearProcessor(size_t processor_id) { Unlock(); } - -} // namespace A64 } // namespace Dynarmic diff --git a/tests/A64/a64.cpp b/tests/A64/a64.cpp index d7fef1fa..d7e40c53 100644 --- a/tests/A64/a64.cpp +++ b/tests/A64/a64.cpp @@ -5,7 +5,7 @@ #include -#include +#include #include "common/fp/fpsr.h" #include "testenv.h" @@ -281,7 +281,7 @@ TEST_CASE("A64: FABD", "[a64]") { TEST_CASE("A64: 128-bit exclusive read/write", "[a64]") { A64TestEnv env; - Dynarmic::A64::ExclusiveMonitor monitor{1}; + Dynarmic::ExclusiveMonitor monitor{1}; Dynarmic::A64::UserConfig conf; conf.callbacks = &env;