summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/semaphore.cpp20
1 files changed, 9 insertions, 11 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index f7a895c3f..331d32069 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -20,9 +20,8 @@ public:
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } 20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; }
21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } 21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; }
22 22
23 u32 initial_count; ///< Number of entries reserved for other threads
24 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 23 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
25 u32 current_usage; ///< Number of currently used entries in the semaphore 24 u32 available_count; ///< Number of free slots left in the semaphore
26 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore 25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore
27 std::string name; ///< Name of semaphore (optional) 26 std::string name; ///< Name of semaphore (optional)
28 27
@@ -31,17 +30,17 @@ public:
31 * @return Whether the semaphore is available 30 * @return Whether the semaphore is available
32 */ 31 */
33 bool IsAvailable() const { 32 bool IsAvailable() const {
34 return current_usage < max_count; 33 return available_count > 0;
35 } 34 }
36 35
37 ResultVal<bool> WaitSynchronization() override { 36 ResultVal<bool> WaitSynchronization() override {
38 bool wait = current_usage == max_count; 37 bool wait = available_count == 0;
39 38
40 if (wait) { 39 if (wait) {
41 Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle()); 40 Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle());
42 waiting_threads.push(GetCurrentThreadHandle()); 41 waiting_threads.push(GetCurrentThreadHandle());
43 } else { 42 } else {
44 ++current_usage; 43 --available_count;
45 } 44 }
46 45
47 return MakeResult<bool>(wait); 46 return MakeResult<bool>(wait);
@@ -60,11 +59,10 @@ ResultCode CreateSemaphore(Handle* handle, u32 initial_count,
60 Semaphore* semaphore = new Semaphore; 59 Semaphore* semaphore = new Semaphore;
61 *handle = g_object_pool.Create(semaphore); 60 *handle = g_object_pool.Create(semaphore);
62 61
63 semaphore->initial_count = initial_count;
64 // When the semaphore is created, some slots are reserved for other threads, 62 // When the semaphore is created, some slots are reserved for other threads,
65 // and the rest is reserved for the caller thread 63 // and the rest is reserved for the caller thread
66 semaphore->max_count = max_count; 64 semaphore->max_count = max_count;
67 semaphore->current_usage = max_count - initial_count; 65 semaphore->available_count = initial_count;
68 semaphore->name = name; 66 semaphore->name = name;
69 67
70 return RESULT_SUCCESS; 68 return RESULT_SUCCESS;
@@ -75,19 +73,19 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
75 if (semaphore == nullptr) 73 if (semaphore == nullptr)
76 return InvalidHandle(ErrorModule::Kernel); 74 return InvalidHandle(ErrorModule::Kernel);
77 75
78 if (semaphore->current_usage < release_count) 76 if (semaphore->max_count - semaphore->available_count < release_count)
79 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 77 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
80 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 78 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
81 79
82 *count = semaphore->max_count - semaphore->current_usage; 80 *count = semaphore->available_count;
83 semaphore->current_usage = semaphore->current_usage - release_count; 81 semaphore->available_count += release_count;
84 82
85 // Notify some of the threads that the semaphore has been released 83 // Notify some of the threads that the semaphore has been released
86 // stop once the semaphore is full again or there are no more waiting threads 84 // stop once the semaphore is full again or there are no more waiting threads
87 while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) { 85 while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
88 Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front()); 86 Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front());
89 semaphore->waiting_threads.pop(); 87 semaphore->waiting_threads.pop();
90 semaphore->current_usage++; 88 --semaphore->available_count;
91 } 89 }
92 90
93 return RESULT_SUCCESS; 91 return RESULT_SUCCESS;