[A64] Add thread-safe atomics to A64Function
Also adds some bounds check to LookupFunction. Co-Authored-By: Reality <reality@xenios.jp>
This commit is contained in:
@@ -26,18 +26,19 @@ A64Function::~A64Function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void A64Function::Setup(uint8_t* machine_code, size_t machine_code_length) {
|
void A64Function::Setup(uint8_t* machine_code, size_t machine_code_length) {
|
||||||
machine_code_ = machine_code;
|
machine_code_length_.store(machine_code_length, std::memory_order_relaxed);
|
||||||
machine_code_length_ = machine_code_length;
|
machine_code_.store(machine_code, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool A64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
|
bool A64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
|
||||||
auto backend =
|
auto backend =
|
||||||
reinterpret_cast<A64Backend*>(thread_state->processor()->backend());
|
reinterpret_cast<A64Backend*>(thread_state->processor()->backend());
|
||||||
auto thunk = backend->host_to_guest_thunk();
|
auto thunk = backend->host_to_guest_thunk();
|
||||||
if (!thunk || !machine_code_) {
|
auto* code = machine_code_.load(std::memory_order_acquire);
|
||||||
|
if (!thunk || !code) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
thunk(machine_code_, thread_state->context(),
|
thunk(code, thread_state->context(),
|
||||||
reinterpret_cast<void*>(uintptr_t(return_address)));
|
reinterpret_cast<void*>(uintptr_t(return_address)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#ifndef XENIA_CPU_BACKEND_A64_A64_FUNCTION_H_
|
#ifndef XENIA_CPU_BACKEND_A64_A64_FUNCTION_H_
|
||||||
#define XENIA_CPU_BACKEND_A64_A64_FUNCTION_H_
|
#define XENIA_CPU_BACKEND_A64_A64_FUNCTION_H_
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "xenia/cpu/function.h"
|
#include "xenia/cpu/function.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
|
||||||
@@ -23,8 +25,12 @@ class A64Function : public GuestFunction {
|
|||||||
A64Function(Module* module, uint32_t address);
|
A64Function(Module* module, uint32_t address);
|
||||||
~A64Function() override;
|
~A64Function() override;
|
||||||
|
|
||||||
uint8_t* machine_code() const override { return machine_code_; }
|
uint8_t* machine_code() const override {
|
||||||
size_t machine_code_length() const override { return machine_code_length_; }
|
return machine_code_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
size_t machine_code_length() const override {
|
||||||
|
return machine_code_length_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
void Setup(uint8_t* machine_code, size_t machine_code_length);
|
void Setup(uint8_t* machine_code, size_t machine_code_length);
|
||||||
|
|
||||||
@@ -32,8 +38,8 @@ class A64Function : public GuestFunction {
|
|||||||
bool CallImpl(ThreadState* thread_state, uint32_t return_address) override;
|
bool CallImpl(ThreadState* thread_state, uint32_t return_address) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t* machine_code_ = nullptr;
|
std::atomic<uint8_t*> machine_code_{nullptr};
|
||||||
size_t machine_code_length_ = 0;
|
std::atomic<size_t> machine_code_length_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace a64
|
} // namespace a64
|
||||||
|
|||||||
@@ -234,7 +234,15 @@ class CodeCacheBase : public CodeCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GuestFunction* LookupFunction(uint64_t host_pc) override {
|
GuestFunction* LookupFunction(uint64_t host_pc) override {
|
||||||
uint32_t key = uint32_t(host_pc - kGeneratedCodeExecuteBase);
|
if (generated_code_map_.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const uint64_t code_base = execute_base_address();
|
||||||
|
const uint64_t code_end = code_base + total_size();
|
||||||
|
if (host_pc < code_base || host_pc >= code_end) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
uint32_t key = uint32_t(host_pc - code_base);
|
||||||
void* fn_entry = std::bsearch(
|
void* fn_entry = std::bsearch(
|
||||||
&key, generated_code_map_.data(), generated_code_map_.size(),
|
&key, generated_code_map_.data(), generated_code_map_.size(),
|
||||||
sizeof(std::pair<uint32_t, Function*>),
|
sizeof(std::pair<uint32_t, Function*>),
|
||||||
|
|||||||
Reference in New Issue
Block a user