diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/citra_qt/debugger/wait_tree.cpp | 5 | ||||
| -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 |
4 files changed, 18 insertions, 21 deletions
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index ebcc02894..6d15e43aa 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp | |||
| @@ -273,9 +273,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSemaphore::GetChildren() cons | |||
| 273 | std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren()); | 273 | std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren()); |
| 274 | 274 | ||
| 275 | const auto& semaphore = static_cast<const Kernel::Semaphore&>(object); | 275 | const auto& semaphore = static_cast<const Kernel::Semaphore&>(object); |
| 276 | list.push_back( | 276 | list.push_back(std::make_unique<WaitTreeText>( |
| 277 | std::make_unique<WaitTreeText>(tr("available count = %1").arg(semaphore.available_count))); | 277 | tr("available count = %1").arg(semaphore.GetAvailableCount()))); |
| 278 | list.push_back(std::make_unique<WaitTreeText>(tr("max count = %1").arg(semaphore.max_count))); | ||
| 279 | return list; | 278 | return list; |
| 280 | } | 279 | } |
| 281 | 280 | ||
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, |