summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/core/hle/function_wrappers.h7
-rw-r--r--src/core/hle/kernel/semaphore.cpp65
-rw-r--r--src/core/hle/kernel/semaphore.h15
-rw-r--r--src/core/hle/svc.cpp13
4 files changed, 81 insertions, 19 deletions
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index dc3668624..b44479b2f 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -121,6 +121,13 @@ template<s32 func(u32*, s32, s32)> void Wrap() {
121 FuncReturn(retval); 121 FuncReturn(retval);
122} 122}
123 123
124template<s32 func(s32*, u32, s32)> void Wrap() {
125 s32 param_1 = 0;
126 u32 retval = func(&param_1, PARAM(1), PARAM(2));
127 Core::g_app_core->SetReg(1, param_1);
128 FuncReturn(retval);
129}
130
124//////////////////////////////////////////////////////////////////////////////////////////////////// 131////////////////////////////////////////////////////////////////////////////////////////////////////
125// Function wrappers that return type u32 132// Function wrappers that return type u32
126 133
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
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 107d12156..2846bb482 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -291,10 +291,17 @@ static Result GetThreadId(u32* thread_id, Handle handle) {
291 291
292/// Creates a semaphore 292/// Creates a semaphore
293static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { 293static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) {
294 *semaphore = Kernel::CreateSemaphore(initial_count, max_count); 294 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count);
295 DEBUG_LOG(SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 295 DEBUG_LOG(SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
296 initial_count, max_count, *semaphore); 296 initial_count, max_count, *semaphore);
297 return 0; 297 return res.raw;
298}
299
300/// Releases a certain number of slots in a semaphore
301static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) {
302 DEBUG_LOG(SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore);
303 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count);
304 return res.raw;
298} 305}
299 306
300/// Query memory 307/// Query memory
@@ -376,7 +383,7 @@ const HLE::FunctionDef SVC_Table[] = {
376 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 383 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
377 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 384 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
378 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, 385 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
379 {0x16, nullptr, "ReleaseSemaphore"}, 386 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
380 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 387 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
381 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 388 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
382 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 389 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},