diff options
| author | 2018-01-08 14:14:30 -0500 | |
|---|---|---|
| committer | 2018-01-08 21:12:54 -0500 | |
| commit | db3a5251664ae77f5e67dba571a11d208e448a86 (patch) | |
| tree | f53b53b9620ca36a5b8085e3e9d2b603477142fc /src/core | |
| parent | Kernel: Properly keep track of mutex lock data in the guest memory. This fixe... (diff) | |
| download | yuzu-db3a5251664ae77f5e67dba571a11d208e448a86.tar.gz yuzu-db3a5251664ae77f5e67dba571a11d208e448a86.tar.xz yuzu-db3a5251664ae77f5e67dba571a11d208e448a86.zip | |
Kernel: Actually wake up the requested number of threads in Semaphore::Release.
Also properly keep track of data in guest memory, this fixes managing the semaphore from userland.
It was found that Semaphores are actually Condition Variables, with Release(1) and Release(-1) being equivalent to notify_one and notify_all. We should change the name of the class to reflect this.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.h | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 |
3 files changed, 16 insertions, 18 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 9c58aa42f..b555bb28e 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp | |||
| @@ -18,9 +18,6 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(VAddr guest_addr, VAddr mutex_ | |||
| 18 | std::string name) { | 18 | std::string name) { |
| 19 | SharedPtr<Semaphore> semaphore(new Semaphore); | 19 | SharedPtr<Semaphore> semaphore(new Semaphore); |
| 20 | 20 | ||
| 21 | // When the semaphore is created, some slots are reserved for other threads, | ||
| 22 | // and the rest is reserved for the caller thread; | ||
| 23 | semaphore->available_count = Memory::Read32(guest_addr); | ||
| 24 | semaphore->name = std::move(name); | 21 | semaphore->name = std::move(name); |
| 25 | semaphore->guest_addr = guest_addr; | 22 | semaphore->guest_addr = guest_addr; |
| 26 | semaphore->mutex_addr = mutex_addr; | 23 | semaphore->mutex_addr = mutex_addr; |
| @@ -32,34 +29,36 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(VAddr guest_addr, VAddr mutex_ | |||
| 32 | } | 29 | } |
| 33 | 30 | ||
| 34 | bool Semaphore::ShouldWait(Thread* thread) const { | 31 | bool Semaphore::ShouldWait(Thread* thread) const { |
| 35 | return available_count <= 0; | 32 | return GetAvailableCount() <= 0; |
| 36 | } | 33 | } |
| 37 | 34 | ||
| 38 | void Semaphore::Acquire(Thread* thread) { | 35 | void Semaphore::Acquire(Thread* thread) { |
| 39 | if (available_count <= 0) | 36 | if (GetAvailableCount() <= 0) |
| 40 | return; | 37 | return; |
| 41 | 38 | ||
| 42 | --available_count; | 39 | SetAvailableCount(GetAvailableCount() - 1); |
| 43 | UpdateGuestState(); | ||
| 44 | } | 40 | } |
| 45 | 41 | ||
| 46 | ResultCode Semaphore::Release(s32 target) { | 42 | ResultCode Semaphore::Release(s32 target) { |
| 47 | ++available_count; | ||
| 48 | UpdateGuestState(); | ||
| 49 | |||
| 50 | if (target == -1) { | 43 | if (target == -1) { |
| 51 | // When -1, wake up all waiting threads | 44 | // When -1, wake up all waiting threads |
| 45 | SetAvailableCount(GetWaitingThreads().size()); | ||
| 52 | WakeupAllWaitingThreads(); | 46 | WakeupAllWaitingThreads(); |
| 53 | } else { | 47 | } else { |
| 54 | // Otherwise, wake up just a single thread | 48 | // Otherwise, wake up just a single thread |
| 49 | SetAvailableCount(target); | ||
| 55 | WakeupWaitingThread(GetHighestPriorityReadyThread()); | 50 | WakeupWaitingThread(GetHighestPriorityReadyThread()); |
| 56 | } | 51 | } |
| 57 | 52 | ||
| 58 | return RESULT_SUCCESS; | 53 | return RESULT_SUCCESS; |
| 59 | } | 54 | } |
| 60 | 55 | ||
| 61 | void Semaphore::UpdateGuestState() { | 56 | s32 Semaphore::GetAvailableCount() const { |
| 62 | Memory::Write32(guest_addr, available_count); | 57 | return Memory::Read32(guest_addr); |
| 58 | } | ||
| 59 | |||
| 60 | void Semaphore::SetAvailableCount(s32 value) const { | ||
| 61 | Memory::Write32(guest_addr, value); | ||
| 63 | } | 62 | } |
| 64 | 63 | ||
| 65 | } // namespace Kernel | 64 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index e80230cac..7254eb26d 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | // TODO(Subv): This is actually a Condition Variable. | ||
| 16 | class Semaphore final : public WaitObject { | 17 | class Semaphore final : public WaitObject { |
| 17 | public: | 18 | public: |
| 18 | /** | 19 | /** |
| @@ -39,8 +40,9 @@ public: | |||
| 39 | return HANDLE_TYPE; | 40 | return HANDLE_TYPE; |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have | 43 | s32 GetAvailableCount() const; |
| 43 | s32 available_count; ///< Number of free slots left in the semaphore | 44 | void SetAvailableCount(s32 value) const; |
| 45 | |||
| 44 | std::string name; ///< Name of semaphore (optional) | 46 | std::string name; ///< Name of semaphore (optional) |
| 45 | VAddr guest_addr; ///< Address of the guest semaphore value | 47 | VAddr guest_addr; ///< Address of the guest semaphore value |
| 46 | VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this semaphore, | 48 | VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this semaphore, |
| @@ -59,9 +61,6 @@ public: | |||
| 59 | private: | 61 | private: |
| 60 | Semaphore(); | 62 | Semaphore(); |
| 61 | ~Semaphore() override; | 63 | ~Semaphore() override; |
| 62 | |||
| 63 | /// Updates the state of the object tracking this semaphore in guest memory | ||
| 64 | void UpdateGuestState(); | ||
| 65 | }; | 64 | }; |
| 66 | 65 | ||
| 67 | } // namespace Kernel | 66 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a3ac3d782..d18d7a182 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -501,7 +501,7 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add | |||
| 501 | semaphore->name = Common::StringFromFormat("semaphore-%llx", semaphore_addr); | 501 | semaphore->name = Common::StringFromFormat("semaphore-%llx", semaphore_addr); |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | ASSERT(semaphore->available_count == 0); | 504 | ASSERT(semaphore->GetAvailableCount() == 0); |
| 505 | ASSERT(semaphore->mutex_addr == mutex_addr); | 505 | ASSERT(semaphore->mutex_addr == mutex_addr); |
| 506 | 506 | ||
| 507 | auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, | 507 | auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, |