Modules using object_ref.

This commit is contained in:
Ben Vanik 2015-05-24 20:44:27 -07:00
parent fff1a7c132
commit 5cfb69434c
11 changed files with 63 additions and 94 deletions

View File

@ -300,7 +300,9 @@ void Debugger::StopSession() {
shutdown(listen_socket_, SD_SEND);
closesocket(listen_socket_);
listen_socket_ = INVALID_SOCKET;
if (accept_thread_.joinable()) {
accept_thread_.join();
}
functions_file_.reset();
functions_trace_file_.reset();

View File

@ -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::XboxkrnlModule*>(
kernel_state_->GetModule("xboxkrnl.exe"));
auto xboxkrnl_module = kernel_state_->GetModule("xboxkrnl.exe");
auto xboxkrnl = kernel::object_ref<kernel::XboxkrnlModule>(
reinterpret_cast<kernel::XboxkrnlModule*>(xboxkrnl_module.release()));
int result = xboxkrnl->LaunchModule(module_path.c_str());
xboxkrnl->Release();
if (result == 0) {
return X_STATUS_SUCCESS;
} else {

View File

@ -202,10 +202,11 @@ void CommandProcessor::WorkerThreadMain() {
SwitchToThread();
MemoryBarrier();
write_ptr_index = write_ptr_index_.load();
} while (pending_fns_.empty() && (write_ptr_index == 0xBAADF00D ||
} 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;
}
}

View File

@ -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<XModule> 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<xe::recursive_mutex> 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<XUserModule> 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<XUserModule> 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<XKernelModule> kernel_module) {
std::lock_guard<xe::recursive_mutex> 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<XUserModule> 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<XUserModule> module;
{
std::lock_guard<xe::recursive_mutex> 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<XUserModule>(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();

View File

@ -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<XModule> GetModule(const char* name);
object_ref<XUserModule> GetExecutableModule();
void SetExecutableModule(object_ref<XUserModule> module);
template <typename T>
XKernelModule* LoadKernelModule() {
auto kernel_module = std::make_unique<T>(emulator_, this);
LoadKernelModule(kernel_module.get());
return kernel_module.release();
object_ref<XKernelModule> LoadKernelModule() {
auto kernel_module = object_ref<XKernelModule>(new T(emulator_, this));
LoadKernelModule(kernel_module);
return kernel_module;
}
XUserModule* LoadUserModule(const char* name);
object_ref<XUserModule> 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<XKernelModule> 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<XKernelModule*> kernel_modules_;
std::vector<XUserModule*> user_modules_;
object_ref<XUserModule> executable_module_;
std::vector<object_ref<XKernelModule>> kernel_modules_;
std::vector<object_ref<XUserModule>> user_modules_;
friend class XObject;
};

View File

@ -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) {

View File

@ -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_,

View File

@ -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);
}

View File

@ -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<XUserModule>(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;
}

View File

@ -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<XModule> 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 =
X_STATUS result = X_STATUS_INVALID_HANDLE;
XModule* module = nullptr;
state->object_table()->GetObject(handle, (XObject**)&module);
if (XSUCCEEDED(result)) {
if (module) {
uint32_t section_data = 0;
uint32_t section_size = 0;
result = module->GetSection(name, &section_data, &section_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);

View File

@ -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);
}