diff options
| author | 2015-01-11 13:53:11 -0200 | |
|---|---|---|
| committer | 2015-01-30 11:47:05 -0200 | |
| commit | d9b19be1d9c1baa5e8b92c1960c14e435e6b532f (patch) | |
| tree | da083beea826952f0a9c07ab392992ef6ca84c5c /src/core/hle | |
| parent | Kernel: Convert SharedMemory to not use Handles (diff) | |
| download | yuzu-d9b19be1d9c1baa5e8b92c1960c14e435e6b532f.tar.gz yuzu-d9b19be1d9c1baa5e8b92c1960c14e435e6b532f.tar.xz yuzu-d9b19be1d9c1baa5e8b92c1960c14e435e6b532f.zip | |
Kernel: Convert Semaphore to not use Handles
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 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <queue> | ||
| 6 | |||
| 7 | #include "common/common.h" | 5 | #include "common/common.h" |
| 8 | 6 | ||
| 9 | #include "core/hle/kernel/kernel.h" | 7 | #include "core/hle/kernel/kernel.h" |
| @@ -12,69 +10,50 @@ | |||
| 12 | 10 | ||
| 13 | namespace Kernel { | 11 | namespace Kernel { |
| 14 | 12 | ||
| 15 | class Semaphore : public WaitObject { | 13 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, |
| 16 | public: | 14 | std::string name) { |
| 17 | std::string GetTypeName() const override { return "Semaphore"; } | ||
| 18 | std::string GetName() const override { return name; } | ||
| 19 | |||
| 20 | static const HandleType HANDLE_TYPE = HandleType::Semaphore; | ||
| 21 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||
| 22 | |||
| 23 | s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have | ||
| 24 | s32 available_count; ///< Number of free slots left in the semaphore | ||
| 25 | std::string name; ///< Name of semaphore (optional) | ||
| 26 | |||
| 27 | bool ShouldWait() override { | ||
| 28 | return available_count <= 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | void Acquire() override { | ||
| 32 | _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); | ||
| 33 | --available_count; | ||
| 34 | } | ||
| 35 | }; | ||
| 36 | |||
| 37 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 38 | |||
| 39 | ResultCode CreateSemaphore(Handle* handle, s32 initial_count, | ||
| 40 | s32 max_count, const std::string& name) { | ||
| 41 | 15 | ||
| 42 | if (initial_count > max_count) | 16 | if (initial_count > max_count) |
| 43 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, | 17 | return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, |
| 44 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 18 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); |
| 45 | 19 | ||
| 46 | Semaphore* semaphore = new Semaphore; | 20 | SharedPtr<Semaphore> semaphore(new Semaphore); |
| 47 | // TOOD(yuriks): Fix error reporting | 21 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) |
| 48 | *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); | 22 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); |
| 49 | 23 | ||
| 50 | // When the semaphore is created, some slots are reserved for other threads, | 24 | // When the semaphore is created, some slots are reserved for other threads, |
| 51 | // and the rest is reserved for the caller thread | 25 | // and the rest is reserved for the caller thread |
| 52 | semaphore->max_count = max_count; | 26 | semaphore->max_count = max_count; |
| 53 | semaphore->available_count = initial_count; | 27 | semaphore->available_count = initial_count; |
| 54 | semaphore->name = name; | 28 | semaphore->name = std::move(name); |
| 55 | 29 | ||
| 56 | return RESULT_SUCCESS; | 30 | return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); |
| 57 | } | 31 | } |
| 58 | 32 | ||
| 59 | ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { | 33 | bool Semaphore::ShouldWait() { |
| 60 | Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); | 34 | return available_count <= 0; |
| 61 | if (semaphore == nullptr) | 35 | } |
| 62 | return InvalidHandle(ErrorModule::Kernel); | 36 | |
| 37 | void Semaphore::Acquire() { | ||
| 38 | _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); | ||
| 39 | --available_count; | ||
| 40 | } | ||
| 63 | 41 | ||
| 64 | if (semaphore->max_count - semaphore->available_count < release_count) | 42 | ResultVal<s32> Semaphore::Release(s32 release_count) { |
| 43 | if (max_count - available_count < release_count) | ||
| 65 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, | 44 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, |
| 66 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 45 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 67 | 46 | ||
| 68 | *count = semaphore->available_count; | 47 | s32 previous_count = available_count; |
| 69 | semaphore->available_count += release_count; | 48 | available_count += release_count; |
| 70 | 49 | ||
| 71 | // Notify some of the threads that the semaphore has been released | 50 | // Notify some of the threads that the semaphore has been released |
| 72 | // stop once the semaphore is full again or there are no more waiting threads | 51 | // stop once the semaphore is full again or there are no more waiting threads |
| 73 | while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { | 52 | while (!ShouldWait() && WakeupNextThread() != nullptr) { |
| 74 | semaphore->Acquire(); | 53 | Acquire(); |
| 75 | } | 54 | } |
| 76 | 55 | ||
| 77 | return RESULT_SUCCESS; | 56 | return MakeResult<s32>(previous_count); |
| 78 | } | 57 | } |
| 79 | 58 | ||
| 80 | } // namespace | 59 | } // 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 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <queue> | ||
| 8 | #include <string> | ||
| 9 | |||
| 7 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 8 | 11 | ||
| 9 | #include "core/hle/kernel/kernel.h" | 12 | #include "core/hle/kernel/kernel.h" |
| 10 | 13 | ||
| 11 | namespace Kernel { | 14 | namespace Kernel { |
| 12 | 15 | ||
| 13 | /** | 16 | class Semaphore : public WaitObject { |
| 14 | * Creates a semaphore. | 17 | public: |
| 15 | * @param handle Pointer to the handle of the newly created object | 18 | /** |
| 16 | * @param initial_count Number of slots reserved for other threads | 19 | * Creates a semaphore. |
| 17 | * @param max_count Maximum number of slots the semaphore can have | 20 | * @param handle Pointer to the handle of the newly created object |
| 18 | * @param name Optional name of semaphore | 21 | * @param initial_count Number of slots reserved for other threads |
| 19 | * @return ResultCode of the error | 22 | * @param max_count Maximum number of slots the semaphore can have |
| 20 | */ | 23 | * @param name Optional name of semaphore |
| 21 | ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); | 24 | * @return The created semaphore |
| 22 | 25 | */ | |
| 23 | /** | 26 | static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, |
| 24 | * Releases a certain number of slots from a semaphore. | 27 | std::string name = "Unknown"); |
| 25 | * @param count The number of free slots the semaphore had before this call | 28 | |
| 26 | * @param handle The handle of the semaphore to release | 29 | std::string GetTypeName() const override { return "Semaphore"; } |
| 27 | * @param release_count The number of slots to release | 30 | std::string GetName() const override { return name; } |
| 28 | * @return ResultCode of the error | 31 | |
| 29 | */ | 32 | static const HandleType HANDLE_TYPE = HandleType::Semaphore; |
| 30 | ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); | 33 | HandleType GetHandleType() const override { return HANDLE_TYPE; } |
| 34 | |||
| 35 | s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have | ||
| 36 | s32 available_count; ///< Number of free slots left in the semaphore | ||
| 37 | std::string name; ///< Name of semaphore (optional) | ||
| 38 | |||
| 39 | bool ShouldWait() override; | ||
| 40 | void Acquire() override; | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Releases a certain number of slots from a semaphore. | ||
| 44 | * @param release_count The number of slots to release | ||
| 45 | * @return The number of free slots the semaphore had before this call | ||
| 46 | */ | ||
| 47 | ResultVal<s32> Release(s32 release_count); | ||
| 48 | |||
| 49 | private: | ||
| 50 | Semaphore() = default; | ||
| 51 | }; | ||
| 31 | 52 | ||
| 32 | } // namespace | 53 | } // 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) { | |||
| 374 | 374 | ||
| 375 | /// Creates a semaphore | 375 | /// Creates a semaphore |
| 376 | static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { | 376 | static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { |
| 377 | ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); | 377 | using Kernel::Semaphore; |
| 378 | |||
| 379 | ResultVal<SharedPtr<Semaphore>> semaphore_res = Semaphore::Create(initial_count, max_count); | ||
| 380 | if (semaphore_res.Failed()) | ||
| 381 | return semaphore_res.Code().raw; | ||
| 382 | |||
| 383 | ResultVal<Handle> handle_res = Kernel::g_handle_table.Create(*semaphore_res); | ||
| 384 | if (handle_res.Failed()) | ||
| 385 | return handle_res.Code().raw; | ||
| 386 | |||
| 387 | *semaphore = *handle_res; | ||
| 378 | LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", | 388 | LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", |
| 379 | initial_count, max_count, *semaphore); | 389 | initial_count, max_count, *semaphore); |
| 380 | return res.raw; | 390 | return RESULT_SUCCESS.raw; |
| 381 | } | 391 | } |
| 382 | 392 | ||
| 383 | /// Releases a certain number of slots in a semaphore | 393 | /// Releases a certain number of slots in a semaphore |
| 384 | static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { | 394 | static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { |
| 385 | LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); | 395 | using Kernel::Semaphore; |
| 386 | ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); | 396 | |
| 387 | return res.raw; | 397 | LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); |
| 398 | |||
| 399 | SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle); | ||
| 400 | if (semaphore == nullptr) | ||
| 401 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 402 | |||
| 403 | ResultVal<s32> release_res = semaphore->Release(release_count); | ||
| 404 | if (release_res.Failed()) | ||
| 405 | return release_res.Code().raw; | ||
| 406 | |||
| 407 | *count = *release_res; | ||
| 408 | return RESULT_SUCCESS.raw; | ||
| 388 | } | 409 | } |
| 389 | 410 | ||
| 390 | /// Query memory | 411 | /// Query memory |