diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.h | 21 |
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 { | |||
| 13 | Semaphore::Semaphore() {} | 14 | Semaphore::Semaphore() {} |
| 14 | Semaphore::~Semaphore() {} | 15 | Semaphore::~Semaphore() {} |
| 15 | 16 | ||
| 16 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, VAddr address, | 17 | ResultVal<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 | ||
| 44 | ResultVal<s32> Semaphore::Release(s32 release_count) { | 44 | ResultVal<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 | 54 | void 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 { | |||
| 17 | public: | 17 | public: |
| 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: | |||
| 55 | private: | 59 | private: |
| 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 |