dynarmic/src/backend/x64/exclusive_monitor.cpp

60 lines
1.5 KiB
C++
Raw Normal View History

2018-06-05 12:27:37 +01:00
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
2020-04-23 15:25:11 +01:00
* SPDX-License-Identifier: 0BSD
2018-06-05 12:27:37 +01:00
*/
#include <algorithm>
2020-06-17 10:28:24 +01:00
#include <dynarmic/exclusive_monitor.h>
2018-06-05 12:27:37 +01:00
#include "common/assert.h"
namespace Dynarmic {
ExclusiveMonitor::ExclusiveMonitor(size_t processor_count) :
exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {
2018-06-05 12:27:37 +01:00
Unlock();
}
size_t ExclusiveMonitor::GetProcessorCount() const {
return exclusive_addresses.size();
}
void ExclusiveMonitor::Lock() {
while (is_locked.test_and_set(std::memory_order_acquire)) {}
2018-06-05 12:27:37 +01:00
}
void ExclusiveMonitor::Unlock() {
is_locked.clear(std::memory_order_release);
2018-06-05 12:27:37 +01:00
}
bool ExclusiveMonitor::CheckAndClear(size_t processor_id, VAddr address) {
2018-06-05 12:27:37 +01:00
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();
}
void ExclusiveMonitor::ClearProcessor(size_t processor_id) {
Lock();
exclusive_addresses[processor_id] = INVALID_EXCLUSIVE_ADDRESS;
Unlock();
}
2018-06-05 12:27:37 +01:00
} // namespace Dynarmic