From d0284e943da4ca2cb78b62aa0663cfb7a191c777 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Fri, 11 Dec 2015 19:51:47 -0600 Subject: [PATCH] XSemaphore Save/Restore --- src/xenia/kernel/xobject.cc | 2 +- src/xenia/kernel/xsemaphore.cc | 50 ++++++++++++++++++++++++++++++++++ src/xenia/kernel/xsemaphore.h | 5 ++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index 50fb69944..d6fc3398a 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -143,7 +143,7 @@ object_ref XObject::Restore(KernelState* kernel_state, Type type, case kTypeNotifyListener: return NotifyListener::Restore(kernel_state, stream); case kTypeSemaphore: - break; + return XSemaphore::Restore(kernel_state, stream); case kTypeSession: break; case kTypeSocket: diff --git a/src/xenia/kernel/xsemaphore.cc b/src/xenia/kernel/xsemaphore.cc index ff7a69ff0..c15658ad8 100644 --- a/src/xenia/kernel/xsemaphore.cc +++ b/src/xenia/kernel/xsemaphore.cc @@ -9,6 +9,9 @@ #include "xenia/kernel/xsemaphore.h" +#include "xenia/base/byte_stream.h" +#include "xenia/base/logging.h" + namespace xe { namespace kernel { @@ -22,6 +25,7 @@ void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) { CreateNative(sizeof(X_KSEMAPHORE)); + maximum_count_ = maximum_count; semaphore_ = xe::threading::Semaphore::Create(initial_count, maximum_count); } @@ -29,6 +33,7 @@ void XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER* header) { assert_false(semaphore_); auto semaphore = reinterpret_cast(native_ptr); + maximum_count_ = semaphore->limit; semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state, semaphore->limit); } @@ -39,5 +44,50 @@ int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) { return previous_count; } +bool XSemaphore::Save(ByteStream* stream) { + if (!SaveObject(stream)) { + return false; + } + + // Get the free number of slots from the semaphore. + uint32_t free_count = 0; + while ( + threading::Wait(semaphore_.get(), false, std::chrono::milliseconds(0)) == + threading::WaitResult::kSuccess) { + free_count++; + } + + uint32_t used_count = maximum_count_ - free_count; + XELOGD("XSemaphore %.8X (count %d/%d)", handle(), used_count, maximum_count_); + + // Restore the semaphore back to its previous count. + semaphore_->Release(free_count, nullptr); + + stream->Write(maximum_count_); + stream->Write(used_count); + + return true; +} + +object_ref XSemaphore::Restore(KernelState* kernel_state, + ByteStream* stream) { + auto sem = new XSemaphore(nullptr); + sem->kernel_state_ = kernel_state; + + if (!sem->RestoreObject(stream)) { + return nullptr; + } + + sem->maximum_count_ = stream->Read(); + auto initial_count = stream->Read(); + XELOGD("XSemaphore %.8X (count %d/%d)", sem->handle(), initial_count, + sem->maximum_count_); + + sem->semaphore_ = + threading::Semaphore::Create(initial_count, sem->maximum_count_); + + return object_ref(sem); +} + } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xsemaphore.h b/src/xenia/kernel/xsemaphore.h index 6dbd4f5d6..3cfdc6bf7 100644 --- a/src/xenia/kernel/xsemaphore.h +++ b/src/xenia/kernel/xsemaphore.h @@ -38,8 +38,13 @@ class XSemaphore : public XObject { return semaphore_.get(); } + bool Save(ByteStream* stream) override; + static object_ref Restore(KernelState* kernel_state, + ByteStream* stream); + private: std::unique_ptr semaphore_; + uint32_t maximum_count_ = 0; }; } // namespace kernel