Kernel state terminate notification support
This commit is contained in:
parent
b6f8985c8c
commit
8d0fef1433
|
@ -144,6 +144,25 @@ void KernelState::set_process_type(uint32_t value) {
|
||||||
pib->process_type = uint8_t(value);
|
pib->process_type = uint8_t(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KernelState::RegisterTitleTerminateNotification(uint32_t routine,
|
||||||
|
uint32_t priority) {
|
||||||
|
TerminateNotification notify;
|
||||||
|
notify.guest_routine = routine;
|
||||||
|
notify.priority = priority;
|
||||||
|
|
||||||
|
terminate_notifications.push_back(notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KernelState::RemoveTitleTerminateNotification(uint32_t routine) {
|
||||||
|
for (auto it = terminate_notifications.begin();
|
||||||
|
it != terminate_notifications.end(); it++) {
|
||||||
|
if (it->guest_routine == routine) {
|
||||||
|
terminate_notifications.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KernelState::RegisterModule(XModule* module) {}
|
void KernelState::RegisterModule(XModule* module) {}
|
||||||
|
|
||||||
void KernelState::UnregisterModule(XModule* module) {}
|
void KernelState::UnregisterModule(XModule* module) {}
|
||||||
|
@ -318,7 +337,21 @@ object_ref<XUserModule> KernelState::LoadUserModule(const char* raw_name) {
|
||||||
void KernelState::TerminateTitle(bool from_guest_thread) {
|
void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
std::lock_guard<xe::recursive_mutex> lock(object_mutex_);
|
std::lock_guard<xe::recursive_mutex> lock(object_mutex_);
|
||||||
|
|
||||||
// First: Kill all guest threads.
|
// First: Call terminate routines
|
||||||
|
// TODO: These might take arguments
|
||||||
|
// FIXME: Calling these will send some threads into kernel code and they'll
|
||||||
|
// hold the lock when terminated! Do we need to wait for all threads to exit?
|
||||||
|
/*
|
||||||
|
if (from_guest_thread) {
|
||||||
|
for (auto routine : terminate_notifications) {
|
||||||
|
auto thread_state = XThread::GetCurrentThread()->thread_state();
|
||||||
|
processor()->Execute(thread_state, routine.guest_routine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminate_notifications.clear();
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Second: Kill all guest threads.
|
||||||
for (auto it = threads_by_id_.begin(); it != threads_by_id_.end();) {
|
for (auto it = threads_by_id_.begin(); it != threads_by_id_.end();) {
|
||||||
if (it->second->guest_thread()) {
|
if (it->second->guest_thread()) {
|
||||||
auto thread = it->second;
|
auto thread = it->second;
|
||||||
|
@ -329,7 +362,7 @@ void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->second->running()) {
|
if (thread->running()) {
|
||||||
thread->Terminate(0);
|
thread->Terminate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +373,7 @@ void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second: Unload all user modules (including the executable)
|
// Third: Unload all user modules (including the executable)
|
||||||
for (int i = 0; i < user_modules_.size(); i++) {
|
for (int i = 0; i < user_modules_.size(); i++) {
|
||||||
X_STATUS status = user_modules_[i]->Unload();
|
X_STATUS status = user_modules_[i]->Unload();
|
||||||
assert_true(XSUCCEEDED(status));
|
assert_true(XSUCCEEDED(status));
|
||||||
|
|
|
@ -79,6 +79,11 @@ struct ProcessInfoBlock {
|
||||||
xe::be<uint32_t> unk_5C;
|
xe::be<uint32_t> unk_5C;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TerminateNotification {
|
||||||
|
uint32_t guest_routine;
|
||||||
|
uint32_t priority;
|
||||||
|
};
|
||||||
|
|
||||||
class KernelState {
|
class KernelState {
|
||||||
public:
|
public:
|
||||||
KernelState(Emulator* emulator);
|
KernelState(Emulator* emulator);
|
||||||
|
@ -108,6 +113,9 @@ class KernelState {
|
||||||
return process_info_block_address_;
|
return process_info_block_address_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterTitleTerminateNotification(uint32_t routine, uint32_t priority);
|
||||||
|
void RemoveTitleTerminateNotification(uint32_t routine);
|
||||||
|
|
||||||
void RegisterModule(XModule* module);
|
void RegisterModule(XModule* module);
|
||||||
void UnregisterModule(XModule* module);
|
void UnregisterModule(XModule* module);
|
||||||
bool IsKernelModule(const char* name);
|
bool IsKernelModule(const char* name);
|
||||||
|
@ -179,6 +187,7 @@ class KernelState {
|
||||||
object_ref<XUserModule> executable_module_;
|
object_ref<XUserModule> executable_module_;
|
||||||
std::vector<object_ref<XKernelModule>> kernel_modules_;
|
std::vector<object_ref<XKernelModule>> kernel_modules_;
|
||||||
std::vector<object_ref<XUserModule>> user_modules_;
|
std::vector<object_ref<XUserModule>> user_modules_;
|
||||||
|
std::vector<TerminateNotification> terminate_notifications;
|
||||||
|
|
||||||
uint32_t process_info_block_address_;
|
uint32_t process_info_block_address_;
|
||||||
|
|
||||||
|
|
|
@ -318,27 +318,25 @@ SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_context,
|
||||||
SHIM_SET_RETURN_32(result);
|
SHIM_SET_RETURN_32(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CALL ExRegisterTitleTerminateNotification_shim(PPCContext* ppc_context,
|
void AppendParam(StringBuffer& string_buffer,
|
||||||
KernelState* kernel_state) {
|
pointer_t<X_EX_TITLE_TERMINATE_REGISTRATION> reg) {
|
||||||
uint32_t registration_ptr = SHIM_GET_ARG_32(0);
|
string_buffer.AppendFormat("%.8X(%.8X, %.8X)", reg.guest_address(),
|
||||||
uint32_t create = SHIM_GET_ARG_32(1);
|
reg->notification_routine, reg->priority);
|
||||||
|
}
|
||||||
uint32_t routine = SHIM_MEM_32(registration_ptr + 0);
|
|
||||||
uint32_t priority = SHIM_MEM_32(registration_ptr + 4);
|
|
||||||
// list entry flink
|
|
||||||
// list entry blink
|
|
||||||
|
|
||||||
XELOGD("ExRegisterTitleTerminateNotification(%.8X(%.8X, %d), %.1X)",
|
|
||||||
registration_ptr, routine, priority, create);
|
|
||||||
|
|
||||||
|
void ExRegisterTitleTerminateNotification(
|
||||||
|
pointer_t<X_EX_TITLE_TERMINATE_REGISTRATION> reg, dword_t create) {
|
||||||
if (create) {
|
if (create) {
|
||||||
// Adding.
|
// Adding.
|
||||||
// TODO(benvanik): add to master list (kernel?).
|
kernel_state()->RegisterTitleTerminateNotification(
|
||||||
|
reg->notification_routine, reg->priority);
|
||||||
} else {
|
} else {
|
||||||
// Removing.
|
// Removing.
|
||||||
// TODO(benvanik): remove from master list.
|
kernel_state()->RemoveTitleTerminateNotification(reg->notification_routine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DECLARE_XBOXKRNL_EXPORT(ExRegisterTitleTerminateNotification,
|
||||||
|
ExportTag::kImplemented);
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
@ -354,6 +352,4 @@ void xe::kernel::xboxkrnl::RegisterModuleExports(
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);
|
||||||
|
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", ExRegisterTitleTerminateNotification, state);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue