diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 81722a2ca..c3c7fda97 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -50,6 +50,7 @@ Processor::Processor(xe_memory_ref memory, shared_ptr backend) : interrupt_thread_lock_(NULL), interrupt_thread_state_(NULL) { memory_ = xe_memory_retain(memory); backend_ = backend; + sym_lock_ = xe_mutex_alloc(10000); InitializeIfNeeded(); } @@ -71,6 +72,7 @@ Processor::~Processor() { delete jit_; delete sym_table_; + xe_mutex_free(sym_lock_); graphics_system_.reset(); export_resolver_.reset(); @@ -158,7 +160,9 @@ int Processor::LoadRawBinary(const xechar_t* path, uint32_t start_address) { // Initialize the module and prepare it for execution. XEEXPECTZERO(jit_->InitModule(exec_module)); + xe_mutex_lock(sym_lock_); modules_.push_back(exec_module); + xe_mutex_unlock(sym_lock_); result_code = 0; XECLEANUP: @@ -183,7 +187,9 @@ int Processor::LoadXexModule(const char* name, const char* path, // Initialize the module and prepare it for execution. XEEXPECTZERO(jit_->InitModule(exec_module)); + xe_mutex_lock(sym_lock_); modules_.push_back(exec_module); + xe_mutex_unlock(sym_lock_); result_code = 0; XECLEANUP: @@ -264,6 +270,7 @@ uint64_t Processor::ExecuteInterrupt(uint32_t address, FunctionSymbol* Processor::GetFunction(uint32_t address) { // Attempt to grab the function symbol from the global lookup table. + // The symbol table takes a lock so it should be safe. FunctionSymbol* fn_symbol = sym_table_->GetFunction(address); if (fn_symbol) { return fn_symbol; @@ -274,13 +281,16 @@ FunctionSymbol* Processor::GetFunction(uint32_t address) { // symbol is not found (likely) it will do analysis on it. // TODO(benvanik): make this more efficient. Could use a binary search or // something more clever. + xe_mutex_lock(sym_lock_); for (std::vector::iterator it = modules_.begin(); it != modules_.end(); ++it) { fn_symbol = (*it)->FindFunctionSymbol(address); if (fn_symbol) { + xe_mutex_unlock(sym_lock_); return fn_symbol; } } + xe_mutex_unlock(sym_lock_); // Not found at all? That seems wrong... XEASSERTALWAYS(); diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 72f11eabb..53e49cb2d 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -76,6 +76,7 @@ private: sdb::SymbolTable* sym_table_; JIT* jit_; std::vector modules_; + xe_mutex_t* sym_lock_; xe_mutex_t* interrupt_thread_lock_; ThreadState* interrupt_thread_state_; diff --git a/src/xenia/cpu/x64/x64_jit.cc b/src/xenia/cpu/x64/x64_jit.cc index 719ce04d9..4007dd7dd 100644 --- a/src/xenia/cpu/x64/x64_jit.cc +++ b/src/xenia/cpu/x64/x64_jit.cc @@ -27,10 +27,12 @@ using namespace AsmJit; X64JIT::X64JIT(xe_memory_ref memory, SymbolTable* sym_table) : JIT(memory, sym_table), emitter_(NULL) { + jit_lock_ = xe_mutex_alloc(10000); } X64JIT::~X64JIT() { delete emitter_; + xe_mutex_free(jit_lock_); } int X64JIT::Setup() { @@ -160,17 +162,20 @@ int X64JIT::UninitModule(ExecModule* module) { void* X64JIT::GetFunctionPointer(sdb::FunctionSymbol* fn_symbol) { // Check function. + // TODO(benvanik): make this lock-free (or spin). + xe_mutex_lock(jit_lock_); x64_function_t fn_ptr = (x64_function_t)fn_symbol->impl_value; if (!fn_ptr) { // Function hasn't been prepped yet - make it now inline. // The emitter will lock and do other fancy things, if required. if (emitter_->PrepareFunction(fn_symbol)) { + xe_mutex_unlock(jit_lock_); return NULL; } fn_ptr = (x64_function_t)fn_symbol->impl_value; XEASSERTNOTNULL(fn_ptr); } - + xe_mutex_unlock(jit_lock_); return fn_ptr; } diff --git a/src/xenia/cpu/x64/x64_jit.h b/src/xenia/cpu/x64/x64_jit.h index 09bede44b..739f36e20 100644 --- a/src/xenia/cpu/x64/x64_jit.h +++ b/src/xenia/cpu/x64/x64_jit.h @@ -43,6 +43,7 @@ protected: int CheckProcessor(); void DumpCPUInfo(); + xe_mutex_t* jit_lock_; X64Emitter* emitter_; };