diff options
author | bunnei <bunneidev@gmail.com> | 2018-05-11 18:59:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-11 18:59:23 +0200 |
commit | 1b5c02fc37206bbd33715d2dde6258c3f835581c (patch) | |
tree | 1c33c66e734ff55228e4293cd2720070cd467080 /src/core/hle/kernel/svc.cpp | |
parent | Merge pull request #439 from ogniK5377/GetTPCMasks (diff) | |
parent | core: Add several missing docstrings. (diff) | |
download | yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.tar yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.tar.gz yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.tar.bz2 yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.tar.lz yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.tar.xz yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.tar.zst yuzu-1b5c02fc37206bbd33715d2dde6258c3f835581c.zip |
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 171 |
1 files changed, 97 insertions, 74 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 72b5c05f2..1ae530c90 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -401,8 +401,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) { /// Get which CPU core is executing the current thread static u32 GetCurrentProcessorNumber() { - NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0"); - return 0; + NGLOG_TRACE(Kernel_SVC, "called"); + return GetCurrentThread()->processor_id; } static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size, @@ -485,22 +485,28 @@ static void ExitProcess() { Core::CurrentProcess()->status = ProcessStatus::Exited; - // Stop all the process threads that are currently waiting for objects. - auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); - for (auto& thread : thread_list) { - if (thread->owner_process != Core::CurrentProcess()) - continue; + auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) { + for (auto& thread : thread_list) { + if (thread->owner_process != Core::CurrentProcess()) + continue; - if (thread == GetCurrentThread()) - continue; + if (thread == GetCurrentThread()) + continue; - // TODO(Subv): When are the other running/ready threads terminated? - ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || - thread->status == THREADSTATUS_WAIT_SYNCH_ALL, - "Exiting processes with non-waiting threads is currently unimplemented"); + // TODO(Subv): When are the other running/ready threads terminated? + ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || + thread->status == THREADSTATUS_WAIT_SYNCH_ALL, + "Exiting processes with non-waiting threads is currently unimplemented"); - thread->Stop(); - } + thread->Stop(); + } + }; + + auto& system = Core::System::GetInstance(); + stop_threads(system.Scheduler(0)->GetThreadList()); + stop_threads(system.Scheduler(1)->GetThreadList()); + stop_threads(system.Scheduler(2)->GetThreadList()); + stop_threads(system.Scheduler(3)->GetThreadList()); // Kill the current thread GetCurrentThread()->Stop(); @@ -530,14 +536,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V switch (processor_id) { case THREADPROCESSORID_0: - break; case THREADPROCESSORID_1: case THREADPROCESSORID_2: case THREADPROCESSORID_3: - // TODO(bunnei): Implement support for other processor IDs - NGLOG_ERROR(Kernel_SVC, - "Newly created thread must run in another thread ({}), unimplemented.", - processor_id); break; default: ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id); @@ -576,7 +577,7 @@ static ResultCode StartThread(Handle thread_handle) { /// Called when a thread exits static void ExitThread() { - NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CPU().GetPC()); + NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CurrentArmInterface().GetPC()); ExitCurrentThread(); Core::System::GetInstance().PrepareReschedule(); @@ -588,7 +589,7 @@ static void SleepThread(s64 nanoseconds) { // Don't attempt to yield execution if there are no available threads to run, // this way we avoid a useless reschedule to the idle thread. - if (nanoseconds == 0 && !Core::System::GetInstance().Scheduler().HaveReadyThreads()) + if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) return; // Sleep current thread and check for next thread to schedule @@ -624,7 +625,7 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var // Note: Deliberately don't attempt to inherit the lock owner's priority. - Core::System::GetInstance().PrepareReschedule(); + Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule(); return RESULT_SUCCESS; } @@ -634,53 +635,60 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target condition_variable_addr, target); u32 processed = 0; - auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); - - for (auto& thread : thread_list) { - if (thread->condvar_wait_address != condition_variable_addr) - continue; - - // Only process up to 'target' threads, unless 'target' is -1, in which case process - // them all. - if (target != -1 && processed >= target) - break; - - // If the mutex is not yet acquired, acquire it. - u32 mutex_val = Memory::Read32(thread->mutex_wait_address); - - if (mutex_val == 0) { - // We were able to acquire the mutex, resume this thread. - Memory::Write32(thread->mutex_wait_address, thread->wait_handle); - ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); - thread->ResumeFromWait(); - - auto lock_owner = thread->lock_owner; - if (lock_owner) - lock_owner->RemoveMutexWaiter(thread); - - thread->lock_owner = nullptr; - thread->mutex_wait_address = 0; - thread->condvar_wait_address = 0; - thread->wait_handle = 0; - } else { - // Couldn't acquire the mutex, block the thread. - Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); - auto owner = g_handle_table.Get<Thread>(owner_handle); - ASSERT(owner); - ASSERT(thread->status != THREADSTATUS_RUNNING); - thread->status = THREADSTATUS_WAIT_MUTEX; - thread->wakeup_callback = nullptr; - // Signal that the mutex now has a waiting thread. - Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag); - - owner->AddMutexWaiter(thread); - - Core::System::GetInstance().PrepareReschedule(); + auto signal_process_wide_key = [&](size_t core_index) { + const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); + for (auto& thread : scheduler->GetThreadList()) { + if (thread->condvar_wait_address != condition_variable_addr) + continue; + + // Only process up to 'target' threads, unless 'target' is -1, in which case process + // them all. + if (target != -1 && processed >= target) + break; + + // If the mutex is not yet acquired, acquire it. + u32 mutex_val = Memory::Read32(thread->mutex_wait_address); + + if (mutex_val == 0) { + // We were able to acquire the mutex, resume this thread. + Memory::Write32(thread->mutex_wait_address, thread->wait_handle); + ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX); + thread->ResumeFromWait(); + + auto lock_owner = thread->lock_owner; + if (lock_owner) + lock_owner->RemoveMutexWaiter(thread); + + thread->lock_owner = nullptr; + thread->mutex_wait_address = 0; + thread->condvar_wait_address = 0; + thread->wait_handle = 0; + } else { + // Couldn't acquire the mutex, block the thread. + Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); + auto owner = g_handle_table.Get<Thread>(owner_handle); + ASSERT(owner); + ASSERT(thread->status != THREADSTATUS_RUNNING); + thread->status = THREADSTATUS_WAIT_MUTEX; + thread->wakeup_callback = nullptr; + + // Signal that the mutex now has a waiting thread. + Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag); + + owner->AddMutexWaiter(thread); + + Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule(); + } + + ++processed; } + }; - ++processed; - } + signal_process_wide_key(0); + signal_process_wide_key(1); + signal_process_wide_key(2); + signal_process_wide_key(3); return RESULT_SUCCESS; } @@ -718,16 +726,31 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 return RESULT_SUCCESS; } -static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) { - NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}", handle); - *mask = 0x0; - *unknown = 0xf; +static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) { + NGLOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); + + const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); + if (!thread) { + return ERR_INVALID_HANDLE; + } + + *core = thread->ideal_core; + *mask = thread->affinity_mask; + return RESULT_SUCCESS; } -static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) { - NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, mask=0x{:08X}, unknown=0x{:X}", - handle, mask, unknown); +static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) { + NGLOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:08X}, core=0x{:X}", thread_handle, + mask, core); + + const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); + if (!thread) { + return ERR_INVALID_HANDLE; + } + + thread->ChangeCore(core, mask); + return RESULT_SUCCESS; } |