summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/semaphore.cpp31
-rw-r--r--src/core/hle/kernel/semaphore.h21
2 files changed, 31 insertions, 21 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 2605b2595..3f364661b 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/hle/kernel/errors.h" 6#include "core/hle/kernel/errors.h"
7#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/object_address_table.h"
8#include "core/hle/kernel/semaphore.h" 9#include "core/hle/kernel/semaphore.h"
9#include "core/hle/kernel/thread.h" 10#include "core/hle/kernel/thread.h"
10 11
@@ -13,20 +14,18 @@ namespace Kernel {
13Semaphore::Semaphore() {} 14Semaphore::Semaphore() {}
14Semaphore::~Semaphore() {} 15Semaphore::~Semaphore() {}
15 16
16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, VAddr address, 17ResultVal<SharedPtr<Semaphore>> Semaphore::Create(VAddr guest_addr, VAddr mutex_addr, std::string name) {
17 std::string name) {
18
19 if (initial_count > max_count)
20 return ERR_INVALID_COMBINATION_KERNEL;
21
22 SharedPtr<Semaphore> semaphore(new Semaphore); 18 SharedPtr<Semaphore> semaphore(new Semaphore);
23 19
24 // When the semaphore is created, some slots are reserved for other threads, 20 // When the semaphore is created, some slots are reserved for other threads,
25 // and the rest is reserved for the caller thread 21 // and the rest is reserved for the caller thread;
26 semaphore->max_count = max_count; 22 semaphore->available_count = Memory::Read32(guest_addr);
27 semaphore->available_count = initial_count;
28 semaphore->address = address;
29 semaphore->name = std::move(name); 23 semaphore->name = std::move(name);
24 semaphore->guest_addr = guest_addr;
25 semaphore->mutex_addr = mutex_addr;
26
27 // Semaphores are referenced by guest address, so track this in the kernel
28 g_object_address_table.Insert(guest_addr, semaphore);
30 29
31 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); 30 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
32} 31}
@@ -39,18 +38,22 @@ void Semaphore::Acquire(Thread* thread) {
39 if (available_count <= 0) 38 if (available_count <= 0)
40 return; 39 return;
41 --available_count; 40 --available_count;
41 UpdateGuestState();
42} 42}
43 43
44ResultVal<s32> Semaphore::Release(s32 release_count) { 44ResultVal<s32> Semaphore::Release(s32 release_count) {
45 if (max_count - available_count < release_count)
46 return ERR_OUT_OF_RANGE_KERNEL;
47
48 s32 previous_count = available_count; 45 s32 previous_count = available_count;
49 available_count += release_count; 46 available_count += release_count;
47 UpdateGuestState();
50 48
51 WakeupAllWaitingThreads(); 49 WakeupAllWaitingThreads();
52 50
53 return MakeResult<s32>(previous_count); 51 return MakeResult<s32>(previous_count);
54} 52}
55 53
56} // namespace 54void Semaphore::UpdateGuestState() {
55 Memory::Write32(guest_addr, available_count);
56}
57
58
59} // namespace Kernel
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 77c491a24..9cad4450a 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -17,12 +17,14 @@ class Semaphore final : public WaitObject {
17public: 17public:
18 /** 18 /**
19 * Creates a semaphore. 19 * Creates a semaphore.
20 * @param initial_count Number of slots reserved for other threads 20 * @param guest_addr Address of the object tracking the semaphore in guest memory. If specified,
21 * @param max_count Maximum number of slots the semaphore can have 21 * this semaphore will update the guest object when its state changes.
22 * @param name Optional name of semaphore 22 * @param mutex_addr Optional address of a guest mutex associated with this semaphore, used by
23 * @return The created semaphore 23 * the OS for implementing events.
24 * @param name Optional name of semaphore.
25 * @return The created semaphore.
24 */ 26 */
25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, VAddr address, 27 static ResultVal<SharedPtr<Semaphore>> Create(VAddr guest_addr, VAddr mutex_addr = 0,
26 std::string name = "Unknown"); 28 std::string name = "Unknown");
27 29
28 std::string GetTypeName() const override { 30 std::string GetTypeName() const override {
@@ -39,8 +41,10 @@ public:
39 41
40 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 42 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
41 s32 available_count; ///< Number of free slots left in the semaphore 43 s32 available_count; ///< Number of free slots left in the semaphore
42 VAddr address;
43 std::string name; ///< Name of semaphore (optional) 44 std::string name; ///< Name of semaphore (optional)
45 VAddr guest_addr; ///< Address of the guest semaphore value
46 VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this semaphore,
47 ///< used for implementing events
44 48
45 bool ShouldWait(Thread* thread) const override; 49 bool ShouldWait(Thread* thread) const override;
46 void Acquire(Thread* thread) override; 50 void Acquire(Thread* thread) override;
@@ -55,6 +59,9 @@ public:
55private: 59private:
56 Semaphore(); 60 Semaphore();
57 ~Semaphore() override; 61 ~Semaphore() override;
62
63 /// Updates the state of the object tracking this semaphore in guest memory
64 void UpdateGuestState();
58}; 65};
59 66
60} // namespace 67} // namespace Kernel