summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2018-05-05 22:00:34 -0400
committerGravatar bunnei2018-05-10 19:34:49 -0400
commit1c36f2a798372b6bfc54e0e8bd6cf073bed83e6a (patch)
tree742fc5f84ee282645bed1b223237cb13146c1447 /src/core/hle/kernel/svc.cpp
parentsvc: Implement GetCurrentProcessorNumber. (diff)
downloadyuzu-1c36f2a798372b6bfc54e0e8bd6cf073bed83e6a.tar.gz
yuzu-1c36f2a798372b6bfc54e0e8bd6cf073bed83e6a.tar.xz
yuzu-1c36f2a798372b6bfc54e0e8bd6cf073bed83e6a.zip
svc: SignalProcessWideKey should apply to all cores.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp93
1 files changed, 50 insertions, 43 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index ec32432db..fdf9f9011 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -635,53 +635,60 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
635 condition_variable_addr, target); 635 condition_variable_addr, target);
636 636
637 u32 processed = 0; 637 u32 processed = 0;
638 auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList();
639
640 for (auto& thread : thread_list) {
641 if (thread->condvar_wait_address != condition_variable_addr)
642 continue;
643
644 // Only process up to 'target' threads, unless 'target' is -1, in which case process
645 // them all.
646 if (target != -1 && processed >= target)
647 break;
648
649 // If the mutex is not yet acquired, acquire it.
650 u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
651
652 if (mutex_val == 0) {
653 // We were able to acquire the mutex, resume this thread.
654 Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
655 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
656 thread->ResumeFromWait();
657
658 auto lock_owner = thread->lock_owner;
659 if (lock_owner)
660 lock_owner->RemoveMutexWaiter(thread);
661
662 thread->lock_owner = nullptr;
663 thread->mutex_wait_address = 0;
664 thread->condvar_wait_address = 0;
665 thread->wait_handle = 0;
666 } else {
667 // Couldn't acquire the mutex, block the thread.
668 Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
669 auto owner = g_handle_table.Get<Thread>(owner_handle);
670 ASSERT(owner);
671 ASSERT(thread->status != THREADSTATUS_RUNNING);
672 thread->status = THREADSTATUS_WAIT_MUTEX;
673 thread->wakeup_callback = nullptr;
674
675 // Signal that the mutex now has a waiting thread.
676 Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
677 638
678 owner->AddMutexWaiter(thread); 639 auto signal_process_wide_key = [&](size_t core_index) {
640 const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
641 for (auto& thread : scheduler->GetThreadList()) {
642 if (thread->condvar_wait_address != condition_variable_addr)
643 continue;
679 644
680 Core::System::GetInstance().PrepareReschedule(); 645 // Only process up to 'target' threads, unless 'target' is -1, in which case process
646 // them all.
647 if (target != -1 && processed >= target)
648 break;
649
650 // If the mutex is not yet acquired, acquire it.
651 u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
652
653 if (mutex_val == 0) {
654 // We were able to acquire the mutex, resume this thread.
655 Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
656 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
657 thread->ResumeFromWait();
658
659 auto lock_owner = thread->lock_owner;
660 if (lock_owner)
661 lock_owner->RemoveMutexWaiter(thread);
662
663 thread->lock_owner = nullptr;
664 thread->mutex_wait_address = 0;
665 thread->condvar_wait_address = 0;
666 thread->wait_handle = 0;
667 } else {
668 // Couldn't acquire the mutex, block the thread.
669 Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
670 auto owner = g_handle_table.Get<Thread>(owner_handle);
671 ASSERT(owner);
672 ASSERT(thread->status != THREADSTATUS_RUNNING);
673 thread->status = THREADSTATUS_WAIT_MUTEX;
674 thread->wakeup_callback = nullptr;
675
676 // Signal that the mutex now has a waiting thread.
677 Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
678
679 owner->AddMutexWaiter(thread);
680
681 Core::System::GetInstance().PrepareReschedule();
682 }
683
684 ++processed;
681 } 685 }
686 };
682 687
683 ++processed; 688 signal_process_wide_key(0);
684 } 689 signal_process_wide_key(1);
690 signal_process_wide_key(2);
691 signal_process_wide_key(3);
685 692
686 return RESULT_SUCCESS; 693 return RESULT_SUCCESS;
687} 694}