diff options
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 78 |
1 files changed, 31 insertions, 47 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c8060f179..2d225392f 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #include "core/hle/kernel/client_session.h" | 24 | #include "core/hle/kernel/client_session.h" |
| 25 | #include "core/hle/kernel/errors.h" | 25 | #include "core/hle/kernel/errors.h" |
| 26 | #include "core/hle/kernel/handle_table.h" | 26 | #include "core/hle/kernel/handle_table.h" |
| 27 | #include "core/hle/kernel/k_scheduler.h" | ||
| 28 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | ||
| 27 | #include "core/hle/kernel/kernel.h" | 29 | #include "core/hle/kernel/kernel.h" |
| 28 | #include "core/hle/kernel/memory/memory_block.h" | 30 | #include "core/hle/kernel/memory/memory_block.h" |
| 29 | #include "core/hle/kernel/memory/page_table.h" | 31 | #include "core/hle/kernel/memory/page_table.h" |
| @@ -32,7 +34,6 @@ | |||
| 32 | #include "core/hle/kernel/process.h" | 34 | #include "core/hle/kernel/process.h" |
| 33 | #include "core/hle/kernel/readable_event.h" | 35 | #include "core/hle/kernel/readable_event.h" |
| 34 | #include "core/hle/kernel/resource_limit.h" | 36 | #include "core/hle/kernel/resource_limit.h" |
| 35 | #include "core/hle/kernel/scheduler.h" | ||
| 36 | #include "core/hle/kernel/shared_memory.h" | 37 | #include "core/hle/kernel/shared_memory.h" |
| 37 | #include "core/hle/kernel/svc.h" | 38 | #include "core/hle/kernel/svc.h" |
| 38 | #include "core/hle/kernel/svc_types.h" | 39 | #include "core/hle/kernel/svc_types.h" |
| @@ -329,7 +330,8 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, | |||
| 329 | 330 | ||
| 330 | /// Makes a blocking IPC call to an OS service. | 331 | /// Makes a blocking IPC call to an OS service. |
| 331 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | 332 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { |
| 332 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 333 | auto& kernel = system.Kernel(); |
| 334 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | ||
| 333 | std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle); | 335 | std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle); |
| 334 | if (!session) { | 336 | if (!session) { |
| 335 | LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); | 337 | LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); |
| @@ -338,9 +340,9 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 338 | 340 | ||
| 339 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | 341 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); |
| 340 | 342 | ||
| 341 | auto thread = system.CurrentScheduler().GetCurrentThread(); | 343 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 342 | { | 344 | { |
| 343 | SchedulerLock lock(system.Kernel()); | 345 | KScopedSchedulerLock lock(kernel); |
| 344 | thread->InvalidateHLECallback(); | 346 | thread->InvalidateHLECallback(); |
| 345 | thread->SetStatus(ThreadStatus::WaitIPC); | 347 | thread->SetStatus(ThreadStatus::WaitIPC); |
| 346 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); | 348 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); |
| @@ -349,12 +351,12 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 349 | if (thread->HasHLECallback()) { | 351 | if (thread->HasHLECallback()) { |
| 350 | Handle event_handle = thread->GetHLETimeEvent(); | 352 | Handle event_handle = thread->GetHLETimeEvent(); |
| 351 | if (event_handle != InvalidHandle) { | 353 | if (event_handle != InvalidHandle) { |
| 352 | auto& time_manager = system.Kernel().TimeManager(); | 354 | auto& time_manager = kernel.TimeManager(); |
| 353 | time_manager.UnscheduleTimeEvent(event_handle); | 355 | time_manager.UnscheduleTimeEvent(event_handle); |
| 354 | } | 356 | } |
| 355 | 357 | ||
| 356 | { | 358 | { |
| 357 | SchedulerLock lock(system.Kernel()); | 359 | KScopedSchedulerLock lock(kernel); |
| 358 | auto* sync_object = thread->GetHLESyncObject(); | 360 | auto* sync_object = thread->GetHLESyncObject(); |
| 359 | sync_object->RemoveWaitingThread(SharedFrom(thread)); | 361 | sync_object->RemoveWaitingThread(SharedFrom(thread)); |
| 360 | } | 362 | } |
| @@ -654,7 +656,6 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 654 | info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); | 656 | info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); |
| 655 | 657 | ||
| 656 | if (!break_reason.signal_debugger) { | 658 | if (!break_reason.signal_debugger) { |
| 657 | SchedulerLock lock(system.Kernel()); | ||
| 658 | LOG_CRITICAL( | 659 | LOG_CRITICAL( |
| 659 | Debug_Emulated, | 660 | Debug_Emulated, |
| 660 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", | 661 | "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", |
| @@ -662,13 +663,9 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 662 | 663 | ||
| 663 | handle_debug_buffer(info1, info2); | 664 | handle_debug_buffer(info1, info2); |
| 664 | 665 | ||
| 665 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); | 666 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 666 | const auto thread_processor_id = current_thread->GetProcessorID(); | 667 | const auto thread_processor_id = current_thread->GetProcessorID(); |
| 667 | system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); | 668 | system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); |
| 668 | |||
| 669 | // Kill the current thread | ||
| 670 | system.Kernel().ExceptionalExit(); | ||
| 671 | current_thread->Stop(); | ||
| 672 | } | 669 | } |
| 673 | } | 670 | } |
| 674 | 671 | ||
| @@ -918,7 +915,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 918 | } | 915 | } |
| 919 | 916 | ||
| 920 | const auto& core_timing = system.CoreTiming(); | 917 | const auto& core_timing = system.CoreTiming(); |
| 921 | const auto& scheduler = system.CurrentScheduler(); | 918 | const auto& scheduler = *system.Kernel().CurrentScheduler(); |
| 922 | const auto* const current_thread = scheduler.GetCurrentThread(); | 919 | const auto* const current_thread = scheduler.GetCurrentThread(); |
| 923 | const bool same_thread = current_thread == thread.get(); | 920 | const bool same_thread = current_thread == thread.get(); |
| 924 | 921 | ||
| @@ -1086,7 +1083,7 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act | |||
| 1086 | return ERR_INVALID_HANDLE; | 1083 | return ERR_INVALID_HANDLE; |
| 1087 | } | 1084 | } |
| 1088 | 1085 | ||
| 1089 | if (thread.get() == system.CurrentScheduler().GetCurrentThread()) { | 1086 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { |
| 1090 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | 1087 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); |
| 1091 | return ERR_BUSY; | 1088 | return ERR_BUSY; |
| 1092 | } | 1089 | } |
| @@ -1119,7 +1116,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H | |||
| 1119 | return ERR_INVALID_HANDLE; | 1116 | return ERR_INVALID_HANDLE; |
| 1120 | } | 1117 | } |
| 1121 | 1118 | ||
| 1122 | if (thread.get() == system.CurrentScheduler().GetCurrentThread()) { | 1119 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { |
| 1123 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | 1120 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); |
| 1124 | return ERR_BUSY; | 1121 | return ERR_BUSY; |
| 1125 | } | 1122 | } |
| @@ -1475,7 +1472,7 @@ static void ExitProcess(Core::System& system) { | |||
| 1475 | current_process->PrepareForTermination(); | 1472 | current_process->PrepareForTermination(); |
| 1476 | 1473 | ||
| 1477 | // Kill the current thread | 1474 | // Kill the current thread |
| 1478 | system.CurrentScheduler().GetCurrentThread()->Stop(); | 1475 | system.Kernel().CurrentScheduler()->GetCurrentThread()->Stop(); |
| 1479 | } | 1476 | } |
| 1480 | 1477 | ||
| 1481 | static void ExitProcess32(Core::System& system) { | 1478 | static void ExitProcess32(Core::System& system) { |
| @@ -1575,8 +1572,8 @@ static ResultCode StartThread32(Core::System& system, Handle thread_handle) { | |||
| 1575 | static void ExitThread(Core::System& system) { | 1572 | static void ExitThread(Core::System& system) { |
| 1576 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); | 1573 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); |
| 1577 | 1574 | ||
| 1578 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); | 1575 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 1579 | system.GlobalScheduler().RemoveThread(SharedFrom(current_thread)); | 1576 | system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread)); |
| 1580 | current_thread->Stop(); | 1577 | current_thread->Stop(); |
| 1581 | } | 1578 | } |
| 1582 | 1579 | ||
| @@ -1589,44 +1586,31 @@ static void SleepThread(Core::System& system, s64 nanoseconds) { | |||
| 1589 | LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds); | 1586 | LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds); |
| 1590 | 1587 | ||
| 1591 | enum class SleepType : s64 { | 1588 | enum class SleepType : s64 { |
| 1592 | YieldWithoutLoadBalancing = 0, | 1589 | YieldWithoutCoreMigration = 0, |
| 1593 | YieldWithLoadBalancing = -1, | 1590 | YieldWithCoreMigration = -1, |
| 1594 | YieldAndWaitForLoadBalancing = -2, | 1591 | YieldAndWaitForLoadBalancing = -2, |
| 1595 | }; | 1592 | }; |
| 1596 | 1593 | ||
| 1597 | auto& scheduler = system.CurrentScheduler(); | 1594 | auto& scheduler = *system.Kernel().CurrentScheduler(); |
| 1598 | auto* const current_thread = scheduler.GetCurrentThread(); | ||
| 1599 | bool is_redundant = false; | ||
| 1600 | |||
| 1601 | if (nanoseconds <= 0) { | 1595 | if (nanoseconds <= 0) { |
| 1602 | switch (static_cast<SleepType>(nanoseconds)) { | 1596 | switch (static_cast<SleepType>(nanoseconds)) { |
| 1603 | case SleepType::YieldWithoutLoadBalancing: { | 1597 | case SleepType::YieldWithoutCoreMigration: { |
| 1604 | auto pair = current_thread->YieldSimple(); | 1598 | scheduler.YieldWithoutCoreMigration(); |
| 1605 | is_redundant = pair.second; | ||
| 1606 | break; | 1599 | break; |
| 1607 | } | 1600 | } |
| 1608 | case SleepType::YieldWithLoadBalancing: { | 1601 | case SleepType::YieldWithCoreMigration: { |
| 1609 | auto pair = current_thread->YieldAndBalanceLoad(); | 1602 | scheduler.YieldWithCoreMigration(); |
| 1610 | is_redundant = pair.second; | ||
| 1611 | break; | 1603 | break; |
| 1612 | } | 1604 | } |
| 1613 | case SleepType::YieldAndWaitForLoadBalancing: { | 1605 | case SleepType::YieldAndWaitForLoadBalancing: { |
| 1614 | auto pair = current_thread->YieldAndWaitForLoadBalancing(); | 1606 | scheduler.YieldToAnyThread(); |
| 1615 | is_redundant = pair.second; | ||
| 1616 | break; | 1607 | break; |
| 1617 | } | 1608 | } |
| 1618 | default: | 1609 | default: |
| 1619 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); | 1610 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); |
| 1620 | } | 1611 | } |
| 1621 | } else { | 1612 | } else { |
| 1622 | current_thread->Sleep(nanoseconds); | 1613 | scheduler.GetCurrentThread()->Sleep(nanoseconds); |
| 1623 | } | ||
| 1624 | |||
| 1625 | if (is_redundant && !system.Kernel().IsMulticore()) { | ||
| 1626 | system.Kernel().ExitSVCProfile(); | ||
| 1627 | system.CoreTiming().AddTicks(1000U); | ||
| 1628 | system.GetCpuManager().PreemptSingleCore(); | ||
| 1629 | system.Kernel().EnterSVCProfile(); | ||
| 1630 | } | 1614 | } |
| 1631 | } | 1615 | } |
| 1632 | 1616 | ||
| @@ -1661,10 +1645,10 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1661 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); | 1645 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); |
| 1662 | auto& kernel = system.Kernel(); | 1646 | auto& kernel = system.Kernel(); |
| 1663 | Handle event_handle; | 1647 | Handle event_handle; |
| 1664 | Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); | 1648 | Thread* current_thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 1665 | auto* const current_process = system.Kernel().CurrentProcess(); | 1649 | auto* const current_process = kernel.CurrentProcess(); |
| 1666 | { | 1650 | { |
| 1667 | SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds); | 1651 | KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds); |
| 1668 | const auto& handle_table = current_process->GetHandleTable(); | 1652 | const auto& handle_table = current_process->GetHandleTable(); |
| 1669 | std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); | 1653 | std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); |
| 1670 | ASSERT(thread); | 1654 | ASSERT(thread); |
| @@ -1700,7 +1684,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1700 | } | 1684 | } |
| 1701 | 1685 | ||
| 1702 | { | 1686 | { |
| 1703 | SchedulerLock lock(kernel); | 1687 | KScopedSchedulerLock lock(kernel); |
| 1704 | 1688 | ||
| 1705 | auto* owner = current_thread->GetLockOwner(); | 1689 | auto* owner = current_thread->GetLockOwner(); |
| 1706 | if (owner != nullptr) { | 1690 | if (owner != nullptr) { |
| @@ -1731,7 +1715,7 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1731 | 1715 | ||
| 1732 | // Retrieve a list of all threads that are waiting for this condition variable. | 1716 | // Retrieve a list of all threads that are waiting for this condition variable. |
| 1733 | auto& kernel = system.Kernel(); | 1717 | auto& kernel = system.Kernel(); |
| 1734 | SchedulerLock lock(kernel); | 1718 | KScopedSchedulerLock lock(kernel); |
| 1735 | auto* const current_process = kernel.CurrentProcess(); | 1719 | auto* const current_process = kernel.CurrentProcess(); |
| 1736 | std::vector<std::shared_ptr<Thread>> waiting_threads = | 1720 | std::vector<std::shared_ptr<Thread>> waiting_threads = |
| 1737 | current_process->GetConditionVariableThreads(condition_variable_addr); | 1721 | current_process->GetConditionVariableThreads(condition_variable_addr); |
| @@ -1993,7 +1977,7 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1993 | } | 1977 | } |
| 1994 | 1978 | ||
| 1995 | *core = thread->GetIdealCore(); | 1979 | *core = thread->GetIdealCore(); |
| 1996 | *mask = thread->GetAffinityMask(); | 1980 | *mask = thread->GetAffinityMask().GetAffinityMask(); |
| 1997 | 1981 | ||
| 1998 | return RESULT_SUCCESS; | 1982 | return RESULT_SUCCESS; |
| 1999 | } | 1983 | } |
| @@ -2629,7 +2613,7 @@ void Call(Core::System& system, u32 immediate) { | |||
| 2629 | auto& kernel = system.Kernel(); | 2613 | auto& kernel = system.Kernel(); |
| 2630 | kernel.EnterSVCProfile(); | 2614 | kernel.EnterSVCProfile(); |
| 2631 | 2615 | ||
| 2632 | auto* thread = system.CurrentScheduler().GetCurrentThread(); | 2616 | auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 2633 | thread->SetContinuousOnSVC(true); | 2617 | thread->SetContinuousOnSVC(true); |
| 2634 | 2618 | ||
| 2635 | const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) | 2619 | const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) |