From afb514528ee694a5ff3d3a07b6a88835141b3939 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 8 Dec 2015 21:26:08 -0600 Subject: [PATCH] Save/Restore XThreads before any other kernel objects --- src/xenia/kernel/kernel_state.cc | 63 ++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 8bf404cb4..4f934470d 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -607,18 +607,49 @@ bool KernelState::Save(ByteStream* stream) { // Save the object table object_table_.Save(stream); - // Save all objects - auto objects = object_table_.GetAllObjects(); - uint32_t* num_objects_ptr = (uint32_t*)(stream->data() + stream->offset()); - size_t num_objects = objects.size(); - stream->Write((uint32_t)num_objects); + // We save XThreads absolutely first, as they will execute code upon save + // (which could modify the kernel state) + auto threads = object_table_.GetObjectsByType(); + uint32_t* num_threads_ptr = + reinterpret_cast(stream->data() + stream->offset()); + stream->Write(static_cast(threads.size())); - XELOGD("Serializing %d objects", num_objects); + size_t num_threads = threads.size(); + XELOGD("Serializing %d threads...", threads.size()); + for (auto thread : threads) { + if (!thread->is_guest_thread()) { + // Don't save host threads. They can be reconstructed on startup. + num_threads--; + continue; + } + + if (!thread->Save(stream)) { + XELOGD("Did not save thread \"%s\"", thread->name().c_str()); + num_threads--; + } + } + + *num_threads_ptr = static_cast(num_threads); + + // Save all other objects + auto objects = object_table_.GetAllObjects(); + uint32_t* num_objects_ptr = + reinterpret_cast(stream->data() + stream->offset()); + stream->Write(static_cast(objects.size())); + + size_t num_objects = objects.size(); + XELOGD("Serializing %d objects...", num_objects); for (auto object : objects) { auto prev_offset = stream->offset(); - stream->Write((uint32_t)object->type()); - if (object->is_host_object() || !object->Save(stream)) { + if (object->is_host_object() || object->type() == XObject::kTypeThread) { + // Don't save host objects or save XThreads again + num_objects--; + continue; + } + + stream->Write(object->type()); + if (!object->Save(stream)) { XELOGD("Did not save object of type %d", object->type()); // Revert backwards and overwrite if a save failed. @@ -627,7 +658,7 @@ bool KernelState::Save(ByteStream* stream) { } } - *num_objects_ptr = (uint32_t)num_objects; + *num_objects_ptr = static_cast(num_objects); return true; } @@ -640,13 +671,23 @@ bool KernelState::Restore(ByteStream* stream) { // Restore the object table object_table_.Restore(stream); + uint32_t num_threads = stream->Read(); + XELOGD("Loading %d threads...", num_threads); + for (uint32_t i = 0; i < num_threads; i++) { + auto thread = XObject::Restore(this, XObject::kTypeThread, stream); + if (!thread) { + // Can't continue the restore or we risk misalignment. + assert_always(); + return false; + } + } + uint32_t num_objects = stream->Read(); XELOGD("Loading %d objects...", num_objects); for (uint32_t i = 0; i < num_objects; i++) { uint32_t type = stream->Read(); - object_ref obj = - XObject::Restore(this, XObject::Type(type), stream); + auto obj = XObject::Restore(this, XObject::Type(type), stream); if (!obj) { // Can't continue the restore or we risk misalignment. assert_always();