From 5cfb69434c6359511443e36ef5c1df5f113a7372 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 24 May 2015 20:44:27 -0700 Subject: [PATCH] Modules using object_ref. --- src/xenia/debug/debugger.cc | 4 +- src/xenia/emulator.cc | 16 ++++---- src/xenia/gpu/gl4/command_processor.cc | 7 ++-- src/xenia/kernel/kernel_state.cc | 53 +++++++++----------------- src/xenia/kernel/kernel_state.h | 24 ++++++------ src/xenia/kernel/object_table.cc | 2 +- src/xenia/kernel/objects/xthread.cc | 5 --- src/xenia/kernel/xam_info.cc | 2 - src/xenia/kernel/xboxkrnl_module.cc | 6 +-- src/xenia/kernel/xboxkrnl_modules.cc | 32 +++++++--------- src/xenia/kernel/xboxkrnl_rtl.cc | 6 +-- 11 files changed, 63 insertions(+), 94 deletions(-) diff --git a/src/xenia/debug/debugger.cc b/src/xenia/debug/debugger.cc index 500bc549f..90fc69724 100644 --- a/src/xenia/debug/debugger.cc +++ b/src/xenia/debug/debugger.cc @@ -300,7 +300,9 @@ void Debugger::StopSession() { shutdown(listen_socket_, SD_SEND); closesocket(listen_socket_); listen_socket_ = INVALID_SOCKET; - accept_thread_.join(); + if (accept_thread_.joinable()) { + accept_thread_.join(); + } functions_file_.reset(); functions_trace_file_.reset(); diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index e1e92c4df..324966cd4 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -38,21 +38,23 @@ Emulator::~Emulator() { // Note that we delete things in the reverse order they were initialized. // Kill the debugger first, so that we don't have it messing with things. - debugger_.reset(); + debugger_->StopSession(); // Give the systems time to shutdown before we delete them. graphics_system_->Shutdown(); audio_system_->Shutdown(); - kernel_state_.reset(); - file_system_.reset(); - input_system_.reset(); graphics_system_.reset(); audio_system_.reset(); + kernel_state_.reset(); + file_system_.reset(); + processor_.reset(); + debugger_.reset(); + export_resolver_.reset(); // Kill the window last, as until the graphics system/etc is dead it's needed. @@ -198,10 +200,10 @@ X_STATUS Emulator::LaunchSTFSTitle(const std::wstring& path) { X_STATUS Emulator::CompleteLaunch(const std::wstring& path, const std::string& module_path) { - auto xboxkrnl = static_cast( - kernel_state_->GetModule("xboxkrnl.exe")); + auto xboxkrnl_module = kernel_state_->GetModule("xboxkrnl.exe"); + auto xboxkrnl = kernel::object_ref( + reinterpret_cast(xboxkrnl_module.release())); int result = xboxkrnl->LaunchModule(module_path.c_str()); - xboxkrnl->Release(); if (result == 0) { return X_STATUS_SUCCESS; } else { diff --git a/src/xenia/gpu/gl4/command_processor.cc b/src/xenia/gpu/gl4/command_processor.cc index 1a52682fa..ceb5aade4 100644 --- a/src/xenia/gpu/gl4/command_processor.cc +++ b/src/xenia/gpu/gl4/command_processor.cc @@ -202,10 +202,11 @@ void CommandProcessor::WorkerThreadMain() { SwitchToThread(); MemoryBarrier(); write_ptr_index = write_ptr_index_.load(); - } while (pending_fns_.empty() && (write_ptr_index == 0xBAADF00D || - read_ptr_index_ == write_ptr_index)); + } while (worker_running_ && pending_fns_.empty() && + (write_ptr_index == 0xBAADF00D || + read_ptr_index_ == write_ptr_index)); // ReturnFromWait(); - if (!pending_fns_.empty()) { + if (!worker_running_ || !pending_fns_.empty()) { continue; } } diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index c2b81e64c..6929454cb 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -45,8 +45,7 @@ KernelState::KernelState(Emulator* emulator) memory_(emulator->memory()), object_table_(nullptr), has_notified_startup_(false), - process_type_(X_PROCTYPE_USER), - executable_module_(nullptr) { + process_type_(X_PROCTYPE_USER) { processor_ = emulator->processor(); file_system_ = emulator->file_system(); @@ -70,13 +69,8 @@ KernelState::KernelState(Emulator* emulator) KernelState::~KernelState() { SetExecutableModule(nullptr); - for (auto user_module : user_modules_) { - user_module->Release(); - } + executable_module_.reset(); user_modules_.clear(); - for (auto kernel_module : kernel_modules_) { - kernel_module->Release(); - } kernel_modules_.clear(); // Delete all objects. @@ -116,7 +110,7 @@ bool KernelState::IsKernelModule(const char* name) { return false; } -XModule* KernelState::GetModule(const char* name) { +object_ref KernelState::GetModule(const char* name) { if (!name) { // NULL name = self. // TODO(benvanik): lookup module from caller address. @@ -128,48 +122,37 @@ XModule* KernelState::GetModule(const char* name) { std::lock_guard lock(object_mutex_); for (auto kernel_module : kernel_modules_) { if (kernel_module->Matches(name)) { - kernel_module->Retain(); - return kernel_module; + return retain_object(kernel_module.get()); } } for (auto user_module : user_modules_) { if (user_module->Matches(name)) { - user_module->Retain(); - return user_module; + return retain_object(user_module.get()); } } return nullptr; } -XUserModule* KernelState::GetExecutableModule() { +object_ref KernelState::GetExecutableModule() { if (!executable_module_) { return nullptr; } - - executable_module_->Retain(); return executable_module_; } -void KernelState::SetExecutableModule(XUserModule* module) { - if (module == executable_module_) { +void KernelState::SetExecutableModule(object_ref module) { + if (module.get() == executable_module_.get()) { return; } - - if (executable_module_) { - executable_module_->Release(); - } - executable_module_ = module; - if (executable_module_) { - executable_module_->Retain(); - } + executable_module_ = std::move(module); } -void KernelState::LoadKernelModule(XKernelModule* kernel_module) { +void KernelState::LoadKernelModule(object_ref kernel_module) { std::lock_guard lock(object_mutex_); - kernel_modules_.push_back(kernel_module); + kernel_modules_.push_back(std::move(kernel_module)); } -XUserModule* KernelState::LoadUserModule(const char* raw_name) { +object_ref KernelState::LoadUserModule(const char* raw_name) { // Some games try to load relative to launch module, others specify full path. std::string name = xe::find_name_from_path(raw_name); std::string path(raw_name); @@ -177,28 +160,28 @@ XUserModule* KernelState::LoadUserModule(const char* raw_name) { path = xe::join_paths(xe::find_base_path(executable_module_->path()), name); } - XUserModule* module = nullptr; + object_ref module; { std::lock_guard lock(object_mutex_); // See if we've already loaded it - for (XUserModule* existing_module : user_modules_) { + for (auto& existing_module : user_modules_) { if (existing_module->path() == path) { existing_module->Retain(); - return existing_module; + return retain_object(existing_module.get()); } } // Module wasn't loaded, so load it. - module = new XUserModule(this, path.c_str()); + module = object_ref(new XUserModule(this, path.c_str())); X_STATUS status = module->LoadFromFile(path); if (XFAILED(status)) { - module->Release(); return nullptr; } - user_modules_.push_back(module); + // Retain when putting into the listing. module->Retain(); + user_modules_.push_back(module); } module->Dump(); diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index e3676b888..c6ad778b0 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -73,16 +73,16 @@ class KernelState { void RegisterModule(XModule* module); void UnregisterModule(XModule* module); bool IsKernelModule(const char* name); - XModule* GetModule(const char* name); - XUserModule* GetExecutableModule(); - void SetExecutableModule(XUserModule* module); + object_ref GetModule(const char* name); + object_ref GetExecutableModule(); + void SetExecutableModule(object_ref module); template - XKernelModule* LoadKernelModule() { - auto kernel_module = std::make_unique(emulator_, this); - LoadKernelModule(kernel_module.get()); - return kernel_module.release(); + object_ref LoadKernelModule() { + auto kernel_module = object_ref(new T(emulator_, this)); + LoadKernelModule(kernel_module); + return kernel_module; } - XUserModule* LoadUserModule(const char* name); + object_ref LoadUserModule(const char* name); void RegisterThread(XThread* thread); void UnregisterThread(XThread* thread); @@ -102,7 +102,7 @@ class KernelState { uint32_t extended_error, uint32_t length); private: - void LoadKernelModule(XKernelModule* kernel_module); + void LoadKernelModule(object_ref kernel_module); Emulator* emulator_; Memory* memory_; @@ -122,9 +122,9 @@ class KernelState { bool has_notified_startup_; uint32_t process_type_; - XUserModule* executable_module_; - std::vector kernel_modules_; - std::vector user_modules_; + object_ref executable_module_; + std::vector> kernel_modules_; + std::vector> user_modules_; friend class XObject; }; diff --git a/src/xenia/kernel/object_table.cc b/src/xenia/kernel/object_table.cc index b4b3811f6..ab0797fb8 100644 --- a/src/xenia/kernel/object_table.cc +++ b/src/xenia/kernel/object_table.cc @@ -35,7 +35,7 @@ ObjectTable::~ObjectTable() { table_capacity_ = 0; last_free_entry_ = 0; free(table_); - table_ = NULL; + table_ = nullptr; } X_STATUS ObjectTable::FindFreeSlot(uint32_t* out_slot) { diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index 8ff3e637a..fe3b3efc4 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -172,7 +172,6 @@ X_STATUS XThread::Create() { tls_address_ = memory()->SystemHeapAlloc(tls_size); if (!tls_address_) { XELOGW("Unable to allocate thread local storage block"); - module->Release(); return X_STATUS_NO_MEMORY; } @@ -187,10 +186,6 @@ X_STATUS XThread::Create() { memory()->Fill(tls_address_, tls_size, 0); } - if (module) { - module->Release(); - } - // Allocate processor thread state. // This is thread safe. thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_, diff --git a/src/xenia/kernel/xam_info.cc b/src/xenia/kernel/xam_info.cc index 3904d176c..1b53aa3ce 100644 --- a/src/xenia/kernel/xam_info.cc +++ b/src/xenia/kernel/xam_info.cc @@ -79,8 +79,6 @@ SHIM_CALL XamGetExecutionId_shim(PPCContext* ppc_state, KernelState* state) { SHIM_SET_MEM_32(info_ptr, module->execution_info_ptr()); - module->Release(); - SHIM_SET_RETURN_32(0); } diff --git a/src/xenia/kernel/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl_module.cc index 03a9c6d4c..b42ff95f8 100644 --- a/src/xenia/kernel/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl_module.cc @@ -171,13 +171,12 @@ XboxkrnlModule::~XboxkrnlModule() { int XboxkrnlModule::LaunchModule(const char* path) { // Create and register the module. We keep it local to this function and // dispose it on exit. - XUserModule* module = new XUserModule(kernel_state_, path); + auto module = object_ref(new XUserModule(kernel_state_, path)); // Load the module into memory from the filesystem. X_STATUS result_code = module->LoadFromFile(path); if (XFAILED(result_code)) { XELOGE("Failed to load module %s: %.8X", path, result_code); - module->Release(); return 1; } @@ -193,12 +192,9 @@ int XboxkrnlModule::LaunchModule(const char* path) { kernel_state_->SetExecutableModule(NULL); if (XFAILED(result_code)) { XELOGE("Failed to launch module %s: %.8X", path, result_code); - module->Release(); return 2; } - module->Release(); - return 0; } diff --git a/src/xenia/kernel/xboxkrnl_modules.cc b/src/xenia/kernel/xboxkrnl_modules.cc index 10642011a..b31a6159b 100644 --- a/src/xenia/kernel/xboxkrnl_modules.cc +++ b/src/xenia/kernel/xboxkrnl_modules.cc @@ -135,7 +135,7 @@ SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state, // Privilege=6 -> 0x00000040 -> XEX_SYSTEM_INSECURE_SOCKETS uint32_t mask = 1 << privilege; - XUserModule* module = state->GetExecutableModule(); + auto module = state->GetExecutableModule(); if (!module) { SHIM_SET_RETURN_32(0); return; @@ -145,8 +145,6 @@ SHIM_CALL XexCheckExecutablePrivilege_shim(PPCContext* ppc_state, const xe_xex2_header_t* header = xe_xex2_get_header(xex); uint32_t result = (header->system_flags & mask) > 0; - module->Release(); - SHIM_SET_RETURN_32(result); } @@ -157,7 +155,7 @@ SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_state, KernelState* state) { XELOGD("XexGetModuleHandle(%s, %.8X)", module_name, module_handle_ptr); - XModule* module = nullptr; + object_ref module; if (!module_name) { module = state->GetExecutableModule(); } else { @@ -172,8 +170,6 @@ SHIM_CALL XexGetModuleHandle_shim(PPCContext* ppc_state, KernelState* state) { // NOTE: we don't retain the handle for return. SHIM_SET_MEM_32(module_handle_ptr, module->handle()); - module->Release(); - SHIM_SET_RETURN_32(X_ERROR_SUCCESS); } @@ -187,10 +183,11 @@ SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) { XELOGD("XexGetModuleSection(%.8X, %s, %.8X, %.8X)", handle, name, data_ptr, size_ptr); - XModule* module = NULL; - X_STATUS result = - state->object_table()->GetObject(handle, (XObject**)&module); - if (XSUCCEEDED(result)) { + X_STATUS result = X_STATUS_INVALID_HANDLE; + + XModule* module = nullptr; + state->object_table()->GetObject(handle, (XObject**)&module); + if (module) { uint32_t section_data = 0; uint32_t section_size = 0; result = module->GetSection(name, §ion_data, §ion_size); @@ -198,7 +195,6 @@ SHIM_CALL XexGetModuleSection_shim(PPCContext* ppc_state, KernelState* state) { SHIM_SET_MEM_32(data_ptr, section_data); SHIM_SET_MEM_32(size_ptr, section_size); } - module->Release(); } @@ -218,16 +214,16 @@ SHIM_CALL XexLoadImage_shim(PPCContext* ppc_state, KernelState* state) { X_STATUS result = X_STATUS_NO_SUCH_FILE; X_HANDLE module_handle = X_INVALID_HANDLE_VALUE; - XModule* module = state->GetModule(module_name); + auto module = state->GetModule(module_name); if (module) { // Existing module found, just add a reference and obtain a handle. - result = state->object_table()->AddHandle(module, &module_handle); + result = state->object_table()->AddHandle(module.get(), &module_handle); } else { // Not found; attempt to load as a user module. - module = state->LoadUserModule(module_name); - if (module) { - module->RetainHandle(); - module_handle = module->handle(); + auto user_module = state->LoadUserModule(module_name); + if (user_module) { + user_module->RetainHandle(); + module_handle = user_module->handle(); result = X_STATUS_SUCCESS; } } @@ -272,7 +268,7 @@ SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state, XModule* module = NULL; if (!module_handle) { - module = state->GetExecutableModule(); + module = state->GetExecutableModule().get(); } else { result = state->object_table()->GetObject(module_handle, (XObject**)&module); diff --git a/src/xenia/kernel/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl_rtl.cc index 0053d61f5..2b86a563f 100644 --- a/src/xenia/kernel/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl_rtl.cc @@ -397,24 +397,20 @@ SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* ppc_state, // The only ImageField I've seen in the wild is // 0x20401 (XEX_HEADER_DEFAULT_HEAP_SIZE), so that's all we'll support. - XUserModule* module = NULL; - // TODO(benvanik): use xex_header_base to dereference this. // Right now we are only concerned with games making this call on their main // module, so this hack is fine. - module = state->GetExecutableModule(); + auto module = state->GetExecutableModule(); const xe_xex2_header_t* xex_header = module->xex_header(); for (size_t n = 0; n < xex_header->header_count; n++) { if (xex_header->headers[n].key == image_field) { uint32_t value = xex_header->headers[n].value; - module->Release(); SHIM_SET_RETURN_64(value); return; } } - module->Release(); SHIM_SET_RETURN_64(0); }