Files
Xenia-Canary/src/xenia/kernel/kernel_state.cc

131 lines
3.4 KiB
C++

/**
******************************************************************************
* 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 <xenia/kernel/kernel_state.h>
#include <xenia/emulator.h>
#include <xenia/kernel/dispatcher.h>
#include <xenia/kernel/xam_module.h>
#include <xenia/kernel/xboxkrnl_module.h>
#include <xenia/kernel/xboxkrnl_private.h>
#include <xenia/kernel/xobject.h>
#include <xenia/kernel/objects/xmodule.h>
#include <xenia/kernel/objects/xthread.h>
#include <xenia/kernel/objects/xuser_module.h>
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;
}