64 lines
1.6 KiB
C++
64 lines
1.6 KiB
C++
/* This file is part of the dynarmic project.
|
|
* Copyright (c) 2018 MerryMage
|
|
* SPDX-License-Identifier: 0BSD
|
|
*/
|
|
|
|
#include <algorithm>
|
|
|
|
#include <dynarmic/A64/exclusive_monitor.h>
|
|
#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
|