diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 65 | ||||
-rw-r--r-- | src/core/hle/kernel/semaphore.h | 57 | ||||
-rw-r--r-- | src/core/hle/svc.cpp | 33 |
3 files changed, 88 insertions, 67 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 135d8fb2a..a9e406ef4 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <queue> - #include "common/common.h" #include "core/hle/kernel/kernel.h" @@ -12,69 +10,50 @@ namespace Kernel { -class Semaphore : public WaitObject { -public: - 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 max_count; ///< Maximum number of simultaneous holders the semaphore can have - s32 available_count; ///< Number of free slots left in the semaphore - std::string name; ///< Name of semaphore (optional) - - bool ShouldWait() override { - return available_count <= 0; - } - - void Acquire() override { - _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); - --available_count; - } -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -ResultCode CreateSemaphore(Handle* handle, s32 initial_count, - s32 max_count, const std::string& name) { +ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, + std::string name) { if (initial_count > max_count) return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Permanent); - Semaphore* semaphore = new Semaphore; - // TOOD(yuriks): Fix error reporting - *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); + SharedPtr<Semaphore> semaphore(new Semaphore); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); // When the semaphore is created, some slots are reserved for other threads, // and the rest is reserved for the caller thread semaphore->max_count = max_count; semaphore->available_count = initial_count; - semaphore->name = name; + semaphore->name = std::move(name); - return RESULT_SUCCESS; + return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); } -ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { - Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); - if (semaphore == nullptr) - return InvalidHandle(ErrorModule::Kernel); +bool Semaphore::ShouldWait() { + return available_count <= 0; +} + +void Semaphore::Acquire() { + _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); + --available_count; +} - if (semaphore->max_count - semaphore->available_count < release_count) +ResultVal<s32> Semaphore::Release(s32 release_count) { + if (max_count - available_count < release_count) return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); - *count = semaphore->available_count; - semaphore->available_count += release_count; + s32 previous_count = available_count; + available_count += release_count; // Notify some of the threads that the semaphore has been released // stop once the semaphore is full again or there are no more waiting threads - while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { - semaphore->Acquire(); + while (!ShouldWait() && WakeupNextThread() != nullptr) { + Acquire(); } - return RESULT_SUCCESS; + return MakeResult<s32>(previous_count); } } // namespace diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 8644ecf0c..b7f22b86e 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -4,29 +4,50 @@ #pragma once +#include <queue> +#include <string> + #include "common/common_types.h" #include "core/hle/kernel/kernel.h" namespace Kernel { -/** - * Creates a semaphore. - * @param handle Pointer to the handle of the newly created object - * @param initial_count Number of slots reserved for other threads - * @param max_count Maximum number of slots the semaphore can have - * @param name Optional name of semaphore - * @return ResultCode of the error - */ -ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); - -/** - * Releases a certain number of slots from a semaphore. - * @param count The number of free slots the semaphore had before this call - * @param handle The handle of the semaphore to release - * @param release_count The number of slots to release - * @return ResultCode of the error - */ -ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); +class Semaphore : public WaitObject { +public: + /** + * Creates a semaphore. + * @param handle Pointer to the handle of the newly created object + * @param initial_count Number of slots reserved for other threads + * @param max_count Maximum number of slots the semaphore can have + * @param name Optional name of semaphore + * @return The created semaphore + */ + static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, + 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 max_count; ///< Maximum number of simultaneous holders the semaphore can have + s32 available_count; ///< Number of free slots left in the semaphore + std::string name; ///< Name of semaphore (optional) + + bool ShouldWait() override; + void Acquire() override; + + /** + * Releases a certain number of slots from a semaphore. + * @param release_count The number of slots to release + * @return The number of free slots the semaphore had before this call + */ + ResultVal<s32> Release(s32 release_count); + +private: + Semaphore() = default; +}; } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 165da0402..6cbe38bc3 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -374,17 +374,38 @@ static Result GetThreadId(u32* thread_id, Handle handle) { /// Creates a semaphore static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { - ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); + using Kernel::Semaphore; + + ResultVal<SharedPtr<Semaphore>> semaphore_res = Semaphore::Create(initial_count, max_count); + if (semaphore_res.Failed()) + return semaphore_res.Code().raw; + + ResultVal<Handle> handle_res = Kernel::g_handle_table.Create(*semaphore_res); + if (handle_res.Failed()) + return handle_res.Code().raw; + + *semaphore = *handle_res; LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", initial_count, max_count, *semaphore); - return res.raw; + return RESULT_SUCCESS.raw; } /// Releases a certain number of slots in a semaphore -static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { - LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); - ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); - return res.raw; +static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { + using Kernel::Semaphore; + + LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); + + SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle); + if (semaphore == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + ResultVal<s32> release_res = semaphore->Release(release_count); + if (release_res.Failed()) + return release_res.Code().raw; + + *count = *release_res; + return RESULT_SUCCESS.raw; } /// Query memory |