From ab9fac9a988239ad050c1a677653ffc6845e4683 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Wed, 16 Dec 2015 17:27:25 -0600 Subject: [PATCH] XMutant Save/Restore --- src/xenia/kernel/xmutant.cc | 45 +++++++++++++++++++++++++++++++++++++ src/xenia/kernel/xmutant.h | 11 +++++++++ src/xenia/kernel/xobject.cc | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xmutant.cc b/src/xenia/kernel/xmutant.cc index 8e2de374f..5bb03cc9a 100644 --- a/src/xenia/kernel/xmutant.cc +++ b/src/xenia/kernel/xmutant.cc @@ -9,9 +9,16 @@ #include "xenia/kernel/xmutant.h" +#include "xenia/base/byte_stream.h" +#include "xenia/base/logging.h" +#include "xenia/kernel/kernel_state.h" +#include "xenia/kernel/xthread.h" + namespace xe { namespace kernel { +XMutant::XMutant() : XObject(kTypeMutant) {} + XMutant::XMutant(KernelState* kernel_state) : XObject(kernel_state, kTypeMutant) {} @@ -32,6 +39,11 @@ void XMutant::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { X_STATUS XMutant::ReleaseMutant(uint32_t priority_increment, bool abandon, bool wait) { + // Call should succeed if we own the mutant, so go ahead and do this. + if (owning_thread_ == XThread::GetCurrentThread()) { + owning_thread_ = nullptr; + } + // TODO(benvanik): abandoning. assert_false(abandon); if (mutant_->Release()) { @@ -41,5 +53,38 @@ X_STATUS XMutant::ReleaseMutant(uint32_t priority_increment, bool abandon, } } +bool XMutant::Save(ByteStream* stream) { + XELOGD("XMutant %.8X", handle()); + if (!SaveObject(stream)) { + return false; + } + + stream->Write(owning_thread_->handle()); + return true; +} + +object_ref XMutant::Restore(KernelState* kernel_state, + ByteStream* stream) { + auto mutant = new XMutant(); + mutant->kernel_state_ = kernel_state; + + if (!mutant->RestoreObject(stream)) { + delete mutant; + return nullptr; + } + + mutant->Initialize(false); + + // TODO: Make the thread acquire this mutex... Somehow. + auto owning_thread_handle = stream->Read(); + mutant->owning_thread_ = kernel_state->object_table() + ->LookupObject(owning_thread_handle) + .get(); + + return object_ref(mutant); +} + +void XMutant::WaitCallback() { owning_thread_ = XThread::GetCurrentThread(); } + } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xmutant.h b/src/xenia/kernel/xmutant.h index b87c01020..bd4b8a839 100644 --- a/src/xenia/kernel/xmutant.h +++ b/src/xenia/kernel/xmutant.h @@ -16,6 +16,7 @@ namespace xe { namespace kernel { +class XThread; class XMutant : public XObject { public: @@ -31,8 +32,18 @@ class XMutant : public XObject { xe::threading::WaitHandle* GetWaitHandle() override { return mutant_.get(); } + bool Save(ByteStream* stream) override; + static object_ref Restore(KernelState* kernel_state, + ByteStream* stream); + + protected: + void WaitCallback() override; + private: + XMutant(); + std::unique_ptr mutant_; + XThread* owning_thread_ = nullptr; }; } // namespace kernel diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index 0148b23f2..fa3dd4cff 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -139,7 +139,7 @@ object_ref XObject::Restore(KernelState* kernel_state, Type type, case kTypeModule: return XModule::Restore(kernel_state, stream); case kTypeMutant: - break; + return XMutant::Restore(kernel_state, stream); case kTypeNotifyListener: return NotifyListener::Restore(kernel_state, stream); case kTypeSemaphore: