/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include #include #include #include #include #include #include #include #include #include using namespace xe; using namespace xe::kernel; // This is a global object initialized with the XboxkrnlModule. // It references the current kernel state object that all kernel methods should // be using to stash their variables. KernelState* xe::kernel::shared_kernel_state_ = NULL; KernelState::KernelState(Emulator* emulator) : emulator_(emulator), memory_(emulator->memory()), executable_module_(NULL) { processor_ = emulator->processor(); file_system_ = emulator->file_system(); dispatcher_ = new Dispatcher(this); object_table_ = new ObjectTable(); object_mutex_ = xe_mutex_alloc(10000); XEASSERTNULL(shared_kernel_state_); shared_kernel_state_ = this; } KernelState::~KernelState() { SetExecutableModule(NULL); // Delete all objects. xe_mutex_free(object_mutex_); delete object_table_; delete dispatcher_; XEASSERT(shared_kernel_state_ == this); shared_kernel_state_ = NULL; } KernelState* KernelState::shared() { return shared_kernel_state_; } XModule* KernelState::GetModule(const char* name) { if (xestrcasecmpa(name, "xam.xex") == 0) { auto module = emulator_->xam(); module->Retain(); return module; } else if (xestrcasecmpa(name, "xboxkrnl.exe") == 0) { auto module = emulator_->xboxkrnl(); module->Retain(); return module; } else { // TODO(benvanik): support user modules/loading/etc. XEASSERTALWAYS(); return NULL; } } XUserModule* KernelState::GetExecutableModule() { if (!executable_module_) { return NULL; } executable_module_->Retain(); return executable_module_; } void KernelState::SetExecutableModule(XUserModule* module) { if (module == executable_module_) { return; } if (executable_module_) { executable_module_->Release(); } executable_module_ = module; if (executable_module_) { executable_module_->Retain(); } } void KernelState::RegisterThread(XThread* thread) { xe_mutex_lock(object_mutex_); threads_by_id_[thread->thread_id()] = thread; xe_mutex_unlock(object_mutex_); } void KernelState::UnregisterThread(XThread* thread) { xe_mutex_lock(object_mutex_); auto it = threads_by_id_.find(thread->thread_id()); if (it != threads_by_id_.end()) { threads_by_id_.erase(it); } xe_mutex_unlock(object_mutex_); } XThread* KernelState::GetThreadByID(uint32_t thread_id) { XThread* thread = NULL; xe_mutex_lock(object_mutex_); auto it = threads_by_id_.find(thread_id); if (it != threads_by_id_.end()) { thread = it->second; // Caller must release. thread->Retain(); } xe_mutex_unlock(object_mutex_); return thread; }