summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp6
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/svc.cpp19
-rw-r--r--src/core/hle/kernel/thread.cpp1
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
6 files changed, 22 insertions, 14 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 352190da8..c8842410b 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -26,7 +26,7 @@ void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_
26 // them all. 26 // them all.
27 std::size_t last = waiting_threads.size(); 27 std::size_t last = waiting_threads.size();
28 if (num_to_wake > 0) { 28 if (num_to_wake > 0) {
29 last = num_to_wake; 29 last = std::min(last, static_cast<std::size_t>(num_to_wake));
30 } 30 }
31 31
32 // Signal the waiting threads. 32 // Signal the waiting threads.
@@ -90,9 +90,9 @@ ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr a
90 // Determine the modified value depending on the waiting count. 90 // Determine the modified value depending on the waiting count.
91 s32 updated_value; 91 s32 updated_value;
92 if (waiting_threads.empty()) { 92 if (waiting_threads.empty()) {
93 updated_value = value - 1;
94 } else if (num_to_wake <= 0 || waiting_threads.size() <= static_cast<u32>(num_to_wake)) {
95 updated_value = value + 1; 93 updated_value = value + 1;
94 } else if (num_to_wake <= 0 || waiting_threads.size() <= static_cast<u32>(num_to_wake)) {
95 updated_value = value - 1;
96 } else { 96 } else {
97 updated_value = value; 97 updated_value = value;
98 } 98 }
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index a7e4ddc05..3b73be67b 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -62,7 +62,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
62 62
63 if (thread->GetMutexWaitAddress() != 0 || thread->GetCondVarWaitAddress() != 0 || 63 if (thread->GetMutexWaitAddress() != 0 || thread->GetCondVarWaitAddress() != 0 ||
64 thread->GetWaitHandle() != 0) { 64 thread->GetWaitHandle() != 0) {
65 ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex); 65 ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex ||
66 thread->GetStatus() == ThreadStatus::WaitCondVar);
66 thread->SetMutexWaitAddress(0); 67 thread->SetMutexWaitAddress(0);
67 thread->SetCondVarWaitAddress(0); 68 thread->SetCondVarWaitAddress(0);
68 thread->SetWaitHandle(0); 69 thread->SetWaitHandle(0);
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 09d1eadb6..11796e5e5 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1353,7 +1353,7 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
1353 current_thread->SetCondVarWaitAddress(condition_variable_addr); 1353 current_thread->SetCondVarWaitAddress(condition_variable_addr);
1354 current_thread->SetMutexWaitAddress(mutex_addr); 1354 current_thread->SetMutexWaitAddress(mutex_addr);
1355 current_thread->SetWaitHandle(thread_handle); 1355 current_thread->SetWaitHandle(thread_handle);
1356 current_thread->SetStatus(ThreadStatus::WaitMutex); 1356 current_thread->SetStatus(ThreadStatus::WaitCondVar);
1357 current_thread->InvalidateWakeupCallback(); 1357 current_thread->InvalidateWakeupCallback();
1358 1358
1359 current_thread->WakeAfterDelay(nano_seconds); 1359 current_thread->WakeAfterDelay(nano_seconds);
@@ -1397,10 +1397,10 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
1397 // them all. 1397 // them all.
1398 std::size_t last = waiting_threads.size(); 1398 std::size_t last = waiting_threads.size();
1399 if (target != -1) 1399 if (target != -1)
1400 last = target; 1400 last = std::min(waiting_threads.size(), static_cast<std::size_t>(target));
1401 1401
1402 // If there are no threads waiting on this condition variable, just exit 1402 // If there are no threads waiting on this condition variable, just exit
1403 if (last > waiting_threads.size()) 1403 if (last == 0)
1404 return RESULT_SUCCESS; 1404 return RESULT_SUCCESS;
1405 1405
1406 for (std::size_t index = 0; index < last; ++index) { 1406 for (std::size_t index = 0; index < last; ++index) {
@@ -1408,6 +1408,9 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
1408 1408
1409 ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); 1409 ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr);
1410 1410
1411 // liberate Cond Var Thread.
1412 thread->SetCondVarWaitAddress(0);
1413
1411 std::size_t current_core = Core::System::GetInstance().CurrentCoreIndex(); 1414 std::size_t current_core = Core::System::GetInstance().CurrentCoreIndex();
1412 1415
1413 auto& monitor = Core::System::GetInstance().Monitor(); 1416 auto& monitor = Core::System::GetInstance().Monitor();
@@ -1426,10 +1429,9 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
1426 } 1429 }
1427 } while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(), 1430 } while (!monitor.ExclusiveWrite32(current_core, thread->GetMutexWaitAddress(),
1428 thread->GetWaitHandle())); 1431 thread->GetWaitHandle()));
1429
1430 if (mutex_val == 0) { 1432 if (mutex_val == 0) {
1431 // We were able to acquire the mutex, resume this thread. 1433 // We were able to acquire the mutex, resume this thread.
1432 ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex); 1434 ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar);
1433 thread->ResumeFromWait(); 1435 thread->ResumeFromWait();
1434 1436
1435 auto* const lock_owner = thread->GetLockOwner(); 1437 auto* const lock_owner = thread->GetLockOwner();
@@ -1439,8 +1441,8 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
1439 1441
1440 thread->SetLockOwner(nullptr); 1442 thread->SetLockOwner(nullptr);
1441 thread->SetMutexWaitAddress(0); 1443 thread->SetMutexWaitAddress(0);
1442 thread->SetCondVarWaitAddress(0);
1443 thread->SetWaitHandle(0); 1444 thread->SetWaitHandle(0);
1445 Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
1444 } else { 1446 } else {
1445 // Atomically signal that the mutex now has a waiting thread. 1447 // Atomically signal that the mutex now has a waiting thread.
1446 do { 1448 do {
@@ -1459,12 +1461,11 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
1459 const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); 1461 const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
1460 auto owner = handle_table.Get<Thread>(owner_handle); 1462 auto owner = handle_table.Get<Thread>(owner_handle);
1461 ASSERT(owner); 1463 ASSERT(owner);
1462 ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex); 1464 ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar);
1463 thread->InvalidateWakeupCallback(); 1465 thread->InvalidateWakeupCallback();
1466 thread->SetStatus(ThreadStatus::WaitMutex);
1464 1467
1465 owner->AddMutexWaiter(thread); 1468 owner->AddMutexWaiter(thread);
1466
1467 Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
1468 } 1469 }
1469 } 1470 }
1470 1471
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 3b22e8e0d..e5853c46f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -105,6 +105,7 @@ void Thread::ResumeFromWait() {
105 case ThreadStatus::WaitSleep: 105 case ThreadStatus::WaitSleep:
106 case ThreadStatus::WaitIPC: 106 case ThreadStatus::WaitIPC:
107 case ThreadStatus::WaitMutex: 107 case ThreadStatus::WaitMutex:
108 case ThreadStatus::WaitCondVar:
108 case ThreadStatus::WaitArb: 109 case ThreadStatus::WaitArb:
109 break; 110 break;
110 111
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index faad5f391..9c684758c 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -51,7 +51,8 @@ enum class ThreadStatus {
51 WaitIPC, ///< Waiting for the reply from an IPC request 51 WaitIPC, ///< Waiting for the reply from an IPC request
52 WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false 52 WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
53 WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true 53 WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true
54 WaitMutex, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc 54 WaitMutex, ///< Waiting due to an ArbitrateLock svc
55 WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc
55 WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc 56 WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc
56 Dormant, ///< Created but not yet made ready 57 Dormant, ///< Created but not yet made ready
57 Dead ///< Run to completion, or forcefully terminated 58 Dead ///< Run to completion, or forcefully terminated
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 06ad74ffe..593bb681f 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -234,6 +234,9 @@ QString WaitTreeThread::GetText() const {
234 case Kernel::ThreadStatus::WaitMutex: 234 case Kernel::ThreadStatus::WaitMutex:
235 status = tr("waiting for mutex"); 235 status = tr("waiting for mutex");
236 break; 236 break;
237 case Kernel::ThreadStatus::WaitCondVar:
238 status = tr("waiting for condition variable");
239 break;
237 case Kernel::ThreadStatus::WaitArb: 240 case Kernel::ThreadStatus::WaitArb:
238 status = tr("waiting for address arbiter"); 241 status = tr("waiting for address arbiter");
239 break; 242 break;
@@ -269,6 +272,7 @@ QColor WaitTreeThread::GetColor() const {
269 case Kernel::ThreadStatus::WaitSynchAll: 272 case Kernel::ThreadStatus::WaitSynchAll:
270 case Kernel::ThreadStatus::WaitSynchAny: 273 case Kernel::ThreadStatus::WaitSynchAny:
271 case Kernel::ThreadStatus::WaitMutex: 274 case Kernel::ThreadStatus::WaitMutex:
275 case Kernel::ThreadStatus::WaitCondVar:
272 case Kernel::ThreadStatus::WaitArb: 276 case Kernel::ThreadStatus::WaitArb:
273 return QColor(Qt::GlobalColor::red); 277 return QColor(Qt::GlobalColor::red);
274 case Kernel::ThreadStatus::Dormant: 278 case Kernel::ThreadStatus::Dormant: