diff options
-rw-r--r-- | src/citra_qt/debugger/wait_tree.cpp | 15 | ||||
-rw-r--r-- | src/citra_qt/debugger/wait_tree.h | 6 | ||||
-rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/condition_variable.cpp | 65 | ||||
-rw-r--r-- | src/core/hle/kernel/condition_variable.h | 65 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 64 | ||||
-rw-r--r-- | src/core/hle/kernel/semaphore.h | 66 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 58 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 2 |
11 files changed, 180 insertions, 171 deletions
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index 6d15e43aa..cd03a6554 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp @@ -5,9 +5,9 @@ #include "citra_qt/debugger/wait_tree.h" #include "citra_qt/util/util.h" +#include "core/hle/kernel/condition_variable.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" -#include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" #include "core/hle/kernel/wait_object.h" @@ -85,8 +85,9 @@ std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitO return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object)); case Kernel::HandleType::Mutex: return std::make_unique<WaitTreeMutex>(static_cast<const Kernel::Mutex&>(object)); - case Kernel::HandleType::Semaphore: - return std::make_unique<WaitTreeSemaphore>(static_cast<const Kernel::Semaphore&>(object)); + case Kernel::HandleType::ConditionVariable: + return std::make_unique<WaitTreeConditionVariable>( + static_cast<const Kernel::ConditionVariable&>(object)); case Kernel::HandleType::Timer: return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object)); case Kernel::HandleType::Thread: @@ -266,15 +267,15 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutex::GetChildren() const { return list; } -WaitTreeSemaphore::WaitTreeSemaphore(const Kernel::Semaphore& object) +WaitTreeConditionVariable::WaitTreeConditionVariable(const Kernel::ConditionVariable& object) : WaitTreeWaitObject(object) {} -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSemaphore::GetChildren() const { +std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeConditionVariable::GetChildren() const { std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren()); - const auto& semaphore = static_cast<const Kernel::Semaphore&>(object); + const auto& condition_variable = static_cast<const Kernel::ConditionVariable&>(object); list.push_back(std::make_unique<WaitTreeText>( - tr("available count = %1").arg(semaphore.GetAvailableCount()))); + tr("available count = %1").arg(condition_variable.GetAvailableCount()))); return list; } diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h index 2b38712b9..4034e909b 100644 --- a/src/citra_qt/debugger/wait_tree.h +++ b/src/citra_qt/debugger/wait_tree.h @@ -17,7 +17,7 @@ namespace Kernel { class WaitObject; class Event; class Mutex; -class Semaphore; +class ConditionVariable; class Thread; class Timer; } @@ -111,10 +111,10 @@ public: std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; -class WaitTreeSemaphore : public WaitTreeWaitObject { +class WaitTreeConditionVariable : public WaitTreeWaitObject { Q_OBJECT public: - explicit WaitTreeSemaphore(const Kernel::Semaphore& object); + explicit WaitTreeConditionVariable(const Kernel::ConditionVariable& object); std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d35f974ca..a5dc67b07 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -16,6 +16,7 @@ set(SRCS hle/kernel/address_arbiter.cpp hle/kernel/client_port.cpp hle/kernel/client_session.cpp + hle/kernel/condition_variable.cpp hle/kernel/domain.cpp hle/kernel/event.cpp hle/kernel/handle_table.cpp @@ -26,7 +27,6 @@ set(SRCS hle/kernel/object_address_table.cpp hle/kernel/process.cpp hle/kernel/resource_limit.cpp - hle/kernel/semaphore.cpp hle/kernel/server_port.cpp hle/kernel/server_session.cpp hle/kernel/shared_memory.cpp @@ -94,6 +94,7 @@ set(HEADERS hle/kernel/address_arbiter.h hle/kernel/client_port.h hle/kernel/client_session.h + hle/kernel/condition_variable.h hle/kernel/domain.h hle/kernel/errors.h hle/kernel/event.h @@ -105,7 +106,6 @@ set(HEADERS hle/kernel/object_address_table.h hle/kernel/process.h hle/kernel/resource_limit.h - hle/kernel/semaphore.h hle/kernel/server_port.h hle/kernel/server_session.h hle/kernel/session.h diff --git a/src/core/hle/kernel/condition_variable.cpp b/src/core/hle/kernel/condition_variable.cpp new file mode 100644 index 000000000..8908aeeb6 --- /dev/null +++ b/src/core/hle/kernel/condition_variable.cpp @@ -0,0 +1,65 @@ +// Copyright 2018 Yuzu Emulator Team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "core/hle/kernel/condition_variable.h" +#include "core/hle/kernel/errors.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/object_address_table.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +ConditionVariable::ConditionVariable() {} +ConditionVariable::~ConditionVariable() {} + +ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr, + VAddr mutex_addr, + std::string name) { + SharedPtr<ConditionVariable> condition_variable(new ConditionVariable); + + condition_variable->name = std::move(name); + condition_variable->guest_addr = guest_addr; + condition_variable->mutex_addr = mutex_addr; + + // Condition variables are referenced by guest address, so track this in the kernel + g_object_address_table.Insert(guest_addr, condition_variable); + + return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable)); +} + +bool ConditionVariable::ShouldWait(Thread* thread) const { + return GetAvailableCount() <= 0; +} + +void ConditionVariable::Acquire(Thread* thread) { + if (GetAvailableCount() <= 0) + return; + + SetAvailableCount(GetAvailableCount() - 1); +} + +ResultCode ConditionVariable::Release(s32 target) { + if (target == -1) { + // When -1, wake up all waiting threads + SetAvailableCount(GetWaitingThreads().size()); + WakeupAllWaitingThreads(); + } else { + // Otherwise, wake up just a single thread + SetAvailableCount(target); + WakeupWaitingThread(GetHighestPriorityReadyThread()); + } + + return RESULT_SUCCESS; +} + +s32 ConditionVariable::GetAvailableCount() const { + return Memory::Read32(guest_addr); +} + +void ConditionVariable::SetAvailableCount(s32 value) const { + Memory::Write32(guest_addr, value); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/condition_variable.h b/src/core/hle/kernel/condition_variable.h new file mode 100644 index 000000000..27b8547c0 --- /dev/null +++ b/src/core/hle/kernel/condition_variable.h @@ -0,0 +1,65 @@ +// Copyright 2018 Yuzu Emulator Team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <queue> +#include <string> +#include "common/common_types.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/wait_object.h" +#include "core/hle/result.h" + +namespace Kernel { + +class ConditionVariable final : public WaitObject { +public: + /** + * Creates a condition variable. + * @param guest_addr Address of the object tracking the condition variable in guest memory. If + * specified, this condition variable will update the guest object when its state changes. + * @param mutex_addr Optional address of a guest mutex associated with this condition variable, + * used by the OS for implementing events. + * @param name Optional name of condition variable. + * @return The created condition variable. + */ + static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr, VAddr mutex_addr = 0, + std::string name = "Unknown"); + + std::string GetTypeName() const override { + return "ConditionVariable"; + } + std::string GetName() const override { + return name; + } + + static const HandleType HANDLE_TYPE = HandleType::ConditionVariable; + HandleType GetHandleType() const override { + return HANDLE_TYPE; + } + + s32 GetAvailableCount() const; + void SetAvailableCount(s32 value) const; + + std::string name; ///< Name of condition variable (optional) + VAddr guest_addr; ///< Address of the guest condition variable value + VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this condition + ///< variable, used for implementing events + + bool ShouldWait(Thread* thread) const override; + void Acquire(Thread* thread) override; + + /** + * Releases a slot from a condition variable. + * @param target The number of threads to wakeup, -1 is all. + * @return ResultCode indicating if the operation succeeded. + */ + ResultCode Release(s32 target); + +private: + ConditionVariable(); + ~ConditionVariable() override; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index e43055bfd..a1f2090f7 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -23,7 +23,7 @@ enum class HandleType : u32 { Thread, Process, AddressArbiter, - Semaphore, + ConditionVariable, Timer, ResourceLimit, CodeSet, @@ -70,7 +70,7 @@ public: case HandleType::Event: case HandleType::Mutex: case HandleType::Thread: - case HandleType::Semaphore: + case HandleType::ConditionVariable: case HandleType::Timer: case HandleType::ServerPort: case HandleType::ServerSession: diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp deleted file mode 100644 index b555bb28e..000000000 --- a/src/core/hle/kernel/semaphore.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/assert.h" -#include "core/hle/kernel/errors.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/object_address_table.h" -#include "core/hle/kernel/semaphore.h" -#include "core/hle/kernel/thread.h" - -namespace Kernel { - -Semaphore::Semaphore() {} -Semaphore::~Semaphore() {} - -ResultVal<SharedPtr<Semaphore>> Semaphore::Create(VAddr guest_addr, VAddr mutex_addr, - std::string name) { - SharedPtr<Semaphore> semaphore(new Semaphore); - - semaphore->name = std::move(name); - semaphore->guest_addr = guest_addr; - semaphore->mutex_addr = mutex_addr; - - // Semaphores are referenced by guest address, so track this in the kernel - g_object_address_table.Insert(guest_addr, semaphore); - - return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); -} - -bool Semaphore::ShouldWait(Thread* thread) const { - return GetAvailableCount() <= 0; -} - -void Semaphore::Acquire(Thread* thread) { - if (GetAvailableCount() <= 0) - return; - - SetAvailableCount(GetAvailableCount() - 1); -} - -ResultCode Semaphore::Release(s32 target) { - if (target == -1) { - // When -1, wake up all waiting threads - SetAvailableCount(GetWaitingThreads().size()); - WakeupAllWaitingThreads(); - } else { - // Otherwise, wake up just a single thread - SetAvailableCount(target); - WakeupWaitingThread(GetHighestPriorityReadyThread()); - } - - return RESULT_SUCCESS; -} - -s32 Semaphore::GetAvailableCount() const { - return Memory::Read32(guest_addr); -} - -void Semaphore::SetAvailableCount(s32 value) const { - Memory::Write32(guest_addr, value); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h deleted file mode 100644 index 7254eb26d..000000000 --- a/src/core/hle/kernel/semaphore.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <queue> -#include <string> -#include "common/common_types.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/wait_object.h" -#include "core/hle/result.h" - -namespace Kernel { - -// TODO(Subv): This is actually a Condition Variable. -class Semaphore final : public WaitObject { -public: - /** - * Creates a semaphore. - * @param guest_addr Address of the object tracking the semaphore in guest memory. If specified, - * this semaphore will update the guest object when its state changes. - * @param mutex_addr Optional address of a guest mutex associated with this semaphore, used by - * the OS for implementing events. - * @param name Optional name of semaphore. - * @return The created semaphore. - */ - static ResultVal<SharedPtr<Semaphore>> Create(VAddr guest_addr, VAddr mutex_addr = 0, - std::string name = "Unknown"); - - std::string GetTypeName() const override { - return "Semaphore"; - } - std::string GetName() const override { - return name; - } - - static const HandleType HANDLE_TYPE = HandleType::Semaphore; - HandleType GetHandleType() const override { - return HANDLE_TYPE; - } - - s32 GetAvailableCount() const; - void SetAvailableCount(s32 value) const; - - std::string name; ///< Name of semaphore (optional) - VAddr guest_addr; ///< Address of the guest semaphore value - VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this semaphore, - ///< used for implementing events - - bool ShouldWait(Thread* thread) const override; - void Acquire(Thread* thread) override; - - /** - * Releases a slot from a semaphore. - * @param target The number of threads to wakeup, -1 is all. - * @return ResultCode indicating if the operation succeeded. - */ - ResultCode Release(s32 target); - -private: - Semaphore(); - ~Semaphore() override; -}; - -} // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index d18d7a182..b94503536 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright 2018 Yuzu Emulator Team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -8,12 +8,12 @@ #include "core/core_timing.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/condition_variable.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/object_address_table.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" -#include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc_wrap.h" #include "core/hle/kernel/sync_object.h" @@ -476,11 +476,12 @@ static void SleepThread(s64 nanoseconds) { } /// Signal process wide key atomic -static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_addr, +static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, Handle thread_handle, s64 nano_seconds) { - LOG_TRACE(Kernel_SVC, - "called mutex_addr=%llx, semaphore_addr=%llx, thread_handle=0x%08X, timeout=%d", - mutex_addr, semaphore_addr, thread_handle, nano_seconds); + LOG_TRACE( + Kernel_SVC, + "called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d", + mutex_addr, condition_variable_addr, thread_handle, nano_seconds); SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); ASSERT(thread); @@ -494,15 +495,18 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add ASSERT(mutex->GetOwnerHandle() == thread_handle); - SharedPtr<Semaphore> semaphore = g_object_address_table.Get<Semaphore>(semaphore_addr); - if (!semaphore) { - // Create a new semaphore for the specified address if one does not already exist - semaphore = Semaphore::Create(semaphore_addr, mutex_addr).Unwrap(); - semaphore->name = Common::StringFromFormat("semaphore-%llx", semaphore_addr); + SharedPtr<ConditionVariable> condition_variable = + g_object_address_table.Get<ConditionVariable>(condition_variable_addr); + if (!condition_variable) { + // Create a new condition_variable for the specified address if one does not already exist + condition_variable = + ConditionVariable::Create(condition_variable_addr, mutex_addr).Unwrap(); + condition_variable->name = + Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); } - ASSERT(semaphore->GetAvailableCount() == 0); - ASSERT(semaphore->mutex_addr == mutex_addr); + ASSERT(condition_variable->GetAvailableCount() == 0); + ASSERT(condition_variable->mutex_addr == mutex_addr); auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, SharedPtr<Thread> thread, @@ -541,7 +545,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add return false; }; - CASCADE_CODE(WaitSynchronization1(semaphore, thread.get(), nano_seconds, wakeup_callback)); + CASCADE_CODE( + WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback)); mutex->Release(thread.get()); @@ -549,24 +554,27 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add } /// Signal process wide key -static ResultCode SignalProcessWideKey(VAddr semaphore_addr, s32 target) { - LOG_TRACE(Kernel_SVC, "called, semaphore_addr=0x%llx, target=0x%08x", semaphore_addr, target); +static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) { + LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x", + condition_variable_addr, target); // Wakeup all or one thread - Any other value is unimplemented ASSERT(target == -1 || target == 1); - SharedPtr<Semaphore> semaphore = g_object_address_table.Get<Semaphore>(semaphore_addr); - if (!semaphore) { - // Create a new semaphore for the specified address if one does not already exist - semaphore = Semaphore::Create(semaphore_addr).Unwrap(); - semaphore->name = Common::StringFromFormat("semaphore-%llx", semaphore_addr); + SharedPtr<ConditionVariable> condition_variable = + g_object_address_table.Get<ConditionVariable>(condition_variable_addr); + if (!condition_variable) { + // Create a new condition_variable for the specified address if one does not already exist + condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap(); + condition_variable->name = + Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); } - CASCADE_CODE(semaphore->Release(target)); + CASCADE_CODE(condition_variable->Release(target)); - if (semaphore->mutex_addr) { - // If a mutex was created for this semaphore, wait the current thread on it - SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(semaphore->mutex_addr); + if (condition_variable->mutex_addr) { + // If a mutex was created for this condition_variable, wait the current thread on it + SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr); return WaitSynchronization1(mutex, GetCurrentThread()); } diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h index b0265b6c8..a95598994 100644 --- a/src/core/hle/kernel/svc.h +++ b/src/core/hle/kernel/svc.h @@ -1,4 +1,4 @@ -// Copyright 2018 Citra Emulator Project +// Copyright 2018 Yuzu Emulator Team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 4798ce733..bffa2f7f8 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -1,4 +1,4 @@ -// Copyright 2018 Citra Emulator Project +// Copyright 2018 Yuzu Emulator Team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. |