summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Subv2014-12-04 11:40:36 -0500
committerGravatar Subv2014-12-13 13:40:10 -0500
commit49b31badba5672bae3a5950abe3d45c883879c0d (patch)
tree9e0b3da4ac87b39e58ea8d0f1c347b06a6e82169 /src/core/hle/kernel
parentSVC: Implemented svcCreateSemaphore (diff)
downloadyuzu-49b31badba5672bae3a5950abe3d45c883879c0d.tar.gz
yuzu-49b31badba5672bae3a5950abe3d45c883879c0d.tar.xz
yuzu-49b31badba5672bae3a5950abe3d45c883879c0d.zip
SVC: Implemented ReleaseSemaphore.
This behavior was tested on hardware, however i'm still not sure what use the "initial_count" parameter has
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/semaphore.cpp65
-rw-r--r--src/core/hle/kernel/semaphore.h15
2 files changed, 64 insertions, 16 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 73ffbe3cf..674b727d5 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -2,8 +2,7 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <queue>
6#include <vector>
7 6
8#include "common/common.h" 7#include "common/common.h"
9 8
@@ -21,12 +20,20 @@ public:
21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } 20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; }
22 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } 21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; }
23 22
24 u32 initial_count; ///< Number of reserved entries 23 u32 initial_count; ///< Number of reserved entries TODO(Subv): Make use of this
25 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 24 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
26 u32 current_usage; ///< Number of currently used entries in the semaphore 25 u32 current_usage; ///< Number of currently used entries in the semaphore
27 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the semaphore 26 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore
28 std::string name; ///< Name of semaphore (optional) 27 std::string name; ///< Name of semaphore (optional)
29 28
29 /**
30 * Tests whether a semaphore is at its peak capacity
31 * @return Whether the semaphore is full
32 */
33 bool IsFull() const {
34 return current_usage == max_count;
35 }
36
30 ResultVal<bool> SyncRequest() override { 37 ResultVal<bool> SyncRequest() override {
31 // TODO(Subv): ImplementMe 38 // TODO(Subv): ImplementMe
32 return MakeResult<bool>(false); 39 return MakeResult<bool>(false);
@@ -37,7 +44,7 @@ public:
37 44
38 if (wait) { 45 if (wait) {
39 Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle()); 46 Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle());
40 waiting_threads.push_back(GetCurrentThreadHandle()); 47 waiting_threads.push(GetCurrentThreadHandle());
41 } else { 48 } else {
42 ++current_usage; 49 ++current_usage;
43 } 50 }
@@ -56,21 +63,53 @@ public:
56 * @param name Optional name of semaphore 63 * @param name Optional name of semaphore
57 * @return Pointer to new Semaphore object 64 * @return Pointer to new Semaphore object
58 */ 65 */
59Semaphore* CreateSemaphore(Handle& handle, u32 initial_count, u32 max_count, const std::string& name) { 66Semaphore* CreateSemaphore(Handle& handle, u32 initial_count,
67 u32 max_count, const std::string& name) {
68
60 Semaphore* semaphore = new Semaphore; 69 Semaphore* semaphore = new Semaphore;
61 handle = Kernel::g_object_pool.Create(semaphore); 70 handle = g_object_pool.Create(semaphore);
62 71
63 semaphore->initial_count = semaphore->current_usage = initial_count; 72 semaphore->initial_count = initial_count;
64 semaphore->max_count = max_count; 73 // When the semaphore is created, all slots are used by the creator thread
74 semaphore->max_count = semaphore->current_usage = max_count;
65 semaphore->name = name; 75 semaphore->name = name;
66 76
67 return semaphore; 77 return semaphore;
68} 78}
69 79
70Handle CreateSemaphore(u32 initial_count, u32 max_count, const std::string& name) { 80ResultCode CreateSemaphore(Handle* handle, u32 initial_count,
71 Handle handle; 81 u32 max_count, const std::string& name) {
72 Semaphore* semaphore = CreateSemaphore(handle, initial_count, max_count, name); 82
73 return handle; 83 if (initial_count > max_count)
84 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
85 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
86 Semaphore* semaphore = CreateSemaphore(*handle, initial_count, max_count, name);
87
88 return RESULT_SUCCESS;
89}
90
91ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
92
93 Semaphore* semaphore = g_object_pool.Get<Semaphore>(handle);
94 if (semaphore == nullptr)
95 return InvalidHandle(ErrorModule::Kernel);
96
97 if (semaphore->current_usage < release_count)
98 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
99 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
100
101 *count = semaphore->max_count - semaphore->current_usage;
102 semaphore->current_usage = semaphore->current_usage - release_count;
103
104 // Notify some of the threads that the semaphore has been released
105 // stop once the semaphore is full again or there are no more waiting threads
106 while (!semaphore->waiting_threads.empty() && !semaphore->IsFull()) {
107 Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front());
108 semaphore->waiting_threads.pop();
109 semaphore->current_usage++;
110 }
111
112 return RESULT_SUCCESS;
74} 113}
75 114
76} // namespace 115} // namespace
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 6a686db2e..854831ecf 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -12,11 +12,20 @@ namespace Kernel {
12 12
13/** 13/**
14 * Creates a semaphore 14 * Creates a semaphore
15 * @param handle Pointer to the handle of the newly created object
15 * @param initial_count number of reserved entries in the semaphore 16 * @param initial_count number of reserved entries in the semaphore
16 * @param max_count maximum number of holders the semaphore can have 17 * @param max_count maximum number of holders the semaphore can have
17 * @param name Optional name of semaphore 18 * @param name Optional name of semaphore
18 * @return Handle to newly created object 19 * @return ResultCode of the error
19 */ 20 */
20Handle CreateSemaphore(u32 initial_count, u32 max_count, const std::string& name = "Unknown"); 21ResultCode CreateSemaphore(Handle* handle, u32 initial_count, u32 max_count, const std::string& name = "Unknown");
21 22
23/**
24 * Releases a certain number of slots from a semaphore
25 * @param count The number of free slots the semaphore had before this call
26 * @param handle The handle of the semaphore to release
27 * @param release_count The number of slots to release
28 * @return ResultCode of the error
29 */
30ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count);
22} // namespace 31} // namespace