/* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * This software may be used and distributed according to the terms of the GNU * General Public License version 2 or any later version. */ #include #include #include "common/assert.h" namespace Dynarmic { namespace A64 { ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS) { Unlock(); } size_t ExclusiveMonitor::GetProcessorCount() const { return exclusive_addresses.size(); } void ExclusiveMonitor::Mark(size_t processor_id, VAddr address, size_t size) { ASSERT(size <= 16); const VAddr masked_address = address & RESERVATION_GRANULE_MASK; Lock(); exclusive_addresses[processor_id] = masked_address; Unlock(); } 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, size_t size) { ASSERT(size <= 16); const VAddr masked_address = address & RESERVATION_GRANULE_MASK; 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(); } } // namespace A64 } // namespace Dynarmic