diff options
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 149 |
1 files changed, 66 insertions, 83 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bafd1ced7..de3ed25da 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" |
| @@ -234,8 +235,7 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si | |||
| 234 | 235 | ||
| 235 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, | 236 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, |
| 236 | u32 attribute) { | 237 | u32 attribute) { |
| 237 | return SetMemoryAttribute(system, static_cast<VAddr>(address), static_cast<std::size_t>(size), | 238 | return SetMemoryAttribute(system, address, size, mask, attribute); |
| 238 | mask, attribute); | ||
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | /// Maps a memory range into a different range. | 241 | /// Maps a memory range into a different range. |
| @@ -255,8 +255,7 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr | |||
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { | 257 | static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { |
| 258 | return MapMemory(system, static_cast<VAddr>(dst_addr), static_cast<VAddr>(src_addr), | 258 | return MapMemory(system, dst_addr, src_addr, size); |
| 259 | static_cast<std::size_t>(size)); | ||
| 260 | } | 259 | } |
| 261 | 260 | ||
| 262 | /// Unmaps a region that was previously mapped with svcMapMemory | 261 | /// Unmaps a region that was previously mapped with svcMapMemory |
| @@ -276,8 +275,7 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad | |||
| 276 | } | 275 | } |
| 277 | 276 | ||
| 278 | static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { | 277 | static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { |
| 279 | return UnmapMemory(system, static_cast<VAddr>(dst_addr), static_cast<VAddr>(src_addr), | 278 | return UnmapMemory(system, dst_addr, src_addr, size); |
| 280 | static_cast<std::size_t>(size)); | ||
| 281 | } | 279 | } |
| 282 | 280 | ||
| 283 | /// Connect to an OS service given the port name, returns the handle to the port to out | 281 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| @@ -332,7 +330,8 @@ static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, | |||
| 332 | 330 | ||
| 333 | /// Makes a blocking IPC call to an OS service. | 331 | /// Makes a blocking IPC call to an OS service. |
| 334 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | 332 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { |
| 335 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 333 | auto& kernel = system.Kernel(); |
| 334 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | ||
| 336 | std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle); | 335 | std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle); |
| 337 | if (!session) { | 336 | if (!session) { |
| 338 | LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); | 337 | LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle); |
| @@ -341,9 +340,9 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 341 | 340 | ||
| 342 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | 341 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); |
| 343 | 342 | ||
| 344 | auto thread = system.CurrentScheduler().GetCurrentThread(); | 343 | auto thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 345 | { | 344 | { |
| 346 | SchedulerLock lock(system.Kernel()); | 345 | KScopedSchedulerLock lock(kernel); |
| 347 | thread->InvalidateHLECallback(); | 346 | thread->InvalidateHLECallback(); |
| 348 | thread->SetStatus(ThreadStatus::WaitIPC); | 347 | thread->SetStatus(ThreadStatus::WaitIPC); |
| 349 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); | 348 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); |
| @@ -352,12 +351,12 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 352 | if (thread->HasHLECallback()) { | 351 | if (thread->HasHLECallback()) { |
| 353 | Handle event_handle = thread->GetHLETimeEvent(); | 352 | Handle event_handle = thread->GetHLETimeEvent(); |
| 354 | if (event_handle != InvalidHandle) { | 353 | if (event_handle != InvalidHandle) { |
| 355 | auto& time_manager = system.Kernel().TimeManager(); | 354 | auto& time_manager = kernel.TimeManager(); |
| 356 | time_manager.UnscheduleTimeEvent(event_handle); | 355 | time_manager.UnscheduleTimeEvent(event_handle); |
| 357 | } | 356 | } |
| 358 | 357 | ||
| 359 | { | 358 | { |
| 360 | SchedulerLock lock(system.Kernel()); | 359 | KScopedSchedulerLock lock(kernel); |
| 361 | auto* sync_object = thread->GetHLESyncObject(); | 360 | auto* sync_object = thread->GetHLESyncObject(); |
| 362 | sync_object->RemoveWaitingThread(SharedFrom(thread)); | 361 | sync_object->RemoveWaitingThread(SharedFrom(thread)); |
| 363 | } | 362 | } |
| @@ -531,8 +530,7 @@ static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_hand | |||
| 531 | 530 | ||
| 532 | static ResultCode ArbitrateLock32(Core::System& system, Handle holding_thread_handle, | 531 | static ResultCode ArbitrateLock32(Core::System& system, Handle holding_thread_handle, |
| 533 | u32 mutex_addr, Handle requesting_thread_handle) { | 532 | u32 mutex_addr, Handle requesting_thread_handle) { |
| 534 | return ArbitrateLock(system, holding_thread_handle, static_cast<VAddr>(mutex_addr), | 533 | return ArbitrateLock(system, holding_thread_handle, mutex_addr, requesting_thread_handle); |
| 535 | requesting_thread_handle); | ||
| 536 | } | 534 | } |
| 537 | 535 | ||
| 538 | /// Unlock a mutex | 536 | /// Unlock a mutex |
| @@ -555,7 +553,7 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { | |||
| 555 | } | 553 | } |
| 556 | 554 | ||
| 557 | static ResultCode ArbitrateUnlock32(Core::System& system, u32 mutex_addr) { | 555 | static ResultCode ArbitrateUnlock32(Core::System& system, u32 mutex_addr) { |
| 558 | return ArbitrateUnlock(system, static_cast<VAddr>(mutex_addr)); | 556 | return ArbitrateUnlock(system, mutex_addr); |
| 559 | } | 557 | } |
| 560 | 558 | ||
| 561 | enum class BreakType : u32 { | 559 | enum class BreakType : u32 { |
| @@ -658,7 +656,6 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 658 | info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); | 656 | info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); |
| 659 | 657 | ||
| 660 | if (!break_reason.signal_debugger) { | 658 | if (!break_reason.signal_debugger) { |
| 661 | SchedulerLock lock(system.Kernel()); | ||
| 662 | LOG_CRITICAL( | 659 | LOG_CRITICAL( |
| 663 | Debug_Emulated, | 660 | Debug_Emulated, |
| 664 | "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}", |
| @@ -666,22 +663,18 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | |||
| 666 | 663 | ||
| 667 | handle_debug_buffer(info1, info2); | 664 | handle_debug_buffer(info1, info2); |
| 668 | 665 | ||
| 669 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); | 666 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 670 | const auto thread_processor_id = current_thread->GetProcessorID(); | 667 | const auto thread_processor_id = current_thread->GetProcessorID(); |
| 671 | system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); | 668 | system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); |
| 672 | |||
| 673 | // Kill the current thread | ||
| 674 | system.Kernel().ExceptionalExit(); | ||
| 675 | current_thread->Stop(); | ||
| 676 | } | 669 | } |
| 677 | } | 670 | } |
| 678 | 671 | ||
| 679 | static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { | 672 | static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { |
| 680 | Break(system, reason, static_cast<u64>(info1), static_cast<u64>(info2)); | 673 | Break(system, reason, info1, info2); |
| 681 | } | 674 | } |
| 682 | 675 | ||
| 683 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 676 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 684 | static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) { | 677 | static void OutputDebugString(Core::System& system, VAddr address, u64 len) { |
| 685 | if (len == 0) { | 678 | if (len == 0) { |
| 686 | return; | 679 | return; |
| 687 | } | 680 | } |
| @@ -922,7 +915,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 922 | } | 915 | } |
| 923 | 916 | ||
| 924 | const auto& core_timing = system.CoreTiming(); | 917 | const auto& core_timing = system.CoreTiming(); |
| 925 | const auto& scheduler = system.CurrentScheduler(); | 918 | const auto& scheduler = *system.Kernel().CurrentScheduler(); |
| 926 | const auto* const current_thread = scheduler.GetCurrentThread(); | 919 | const auto* const current_thread = scheduler.GetCurrentThread(); |
| 927 | const bool same_thread = current_thread == thread.get(); | 920 | const bool same_thread = current_thread == thread.get(); |
| 928 | 921 | ||
| @@ -948,7 +941,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 948 | 941 | ||
| 949 | static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low, | 942 | static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low, |
| 950 | u32 info_id, u32 handle, u32 sub_id_high) { | 943 | u32 info_id, u32 handle, u32 sub_id_high) { |
| 951 | const u64 sub_id{static_cast<u64>(sub_id_low | (static_cast<u64>(sub_id_high) << 32))}; | 944 | const u64 sub_id{u64{sub_id_low} | (u64{sub_id_high} << 32)}; |
| 952 | u64 res_value{}; | 945 | u64 res_value{}; |
| 953 | 946 | ||
| 954 | const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)}; | 947 | const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)}; |
| @@ -1009,7 +1002,7 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) | |||
| 1009 | } | 1002 | } |
| 1010 | 1003 | ||
| 1011 | static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { | 1004 | static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { |
| 1012 | return MapPhysicalMemory(system, static_cast<VAddr>(addr), static_cast<std::size_t>(size)); | 1005 | return MapPhysicalMemory(system, addr, size); |
| 1013 | } | 1006 | } |
| 1014 | 1007 | ||
| 1015 | /// Unmaps memory previously mapped via MapPhysicalMemory | 1008 | /// Unmaps memory previously mapped via MapPhysicalMemory |
| @@ -1063,7 +1056,7 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size | |||
| 1063 | } | 1056 | } |
| 1064 | 1057 | ||
| 1065 | static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { | 1058 | static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { |
| 1066 | return UnmapPhysicalMemory(system, static_cast<VAddr>(addr), static_cast<std::size_t>(size)); | 1059 | return UnmapPhysicalMemory(system, addr, size); |
| 1067 | } | 1060 | } |
| 1068 | 1061 | ||
| 1069 | /// Sets the thread activity | 1062 | /// Sets the thread activity |
| @@ -1090,7 +1083,7 @@ static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 act | |||
| 1090 | return ERR_INVALID_HANDLE; | 1083 | return ERR_INVALID_HANDLE; |
| 1091 | } | 1084 | } |
| 1092 | 1085 | ||
| 1093 | if (thread.get() == system.CurrentScheduler().GetCurrentThread()) { | 1086 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { |
| 1094 | 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"); |
| 1095 | return ERR_BUSY; | 1088 | return ERR_BUSY; |
| 1096 | } | 1089 | } |
| @@ -1123,7 +1116,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H | |||
| 1123 | return ERR_INVALID_HANDLE; | 1116 | return ERR_INVALID_HANDLE; |
| 1124 | } | 1117 | } |
| 1125 | 1118 | ||
| 1126 | if (thread.get() == system.CurrentScheduler().GetCurrentThread()) { | 1119 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { |
| 1127 | 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"); |
| 1128 | return ERR_BUSY; | 1121 | return ERR_BUSY; |
| 1129 | } | 1122 | } |
| @@ -1144,7 +1137,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H | |||
| 1144 | } | 1137 | } |
| 1145 | 1138 | ||
| 1146 | static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) { | 1139 | static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) { |
| 1147 | return GetThreadContext(system, static_cast<VAddr>(thread_context), handle); | 1140 | return GetThreadContext(system, thread_context, handle); |
| 1148 | } | 1141 | } |
| 1149 | 1142 | ||
| 1150 | /// Gets the priority for the specified thread | 1143 | /// Gets the priority for the specified thread |
| @@ -1281,8 +1274,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han | |||
| 1281 | 1274 | ||
| 1282 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, | 1275 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, |
| 1283 | u32 size, u32 permissions) { | 1276 | u32 size, u32 permissions) { |
| 1284 | return MapSharedMemory(system, shared_memory_handle, static_cast<VAddr>(addr), | 1277 | return MapSharedMemory(system, shared_memory_handle, addr, size, permissions); |
| 1285 | static_cast<std::size_t>(size), permissions); | ||
| 1286 | } | 1278 | } |
| 1287 | 1279 | ||
| 1288 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, | 1280 | static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, |
| @@ -1480,7 +1472,7 @@ static void ExitProcess(Core::System& system) { | |||
| 1480 | current_process->PrepareForTermination(); | 1472 | current_process->PrepareForTermination(); |
| 1481 | 1473 | ||
| 1482 | // Kill the current thread | 1474 | // Kill the current thread |
| 1483 | system.CurrentScheduler().GetCurrentThread()->Stop(); | 1475 | system.Kernel().CurrentScheduler()->GetCurrentThread()->Stop(); |
| 1484 | } | 1476 | } |
| 1485 | 1477 | ||
| 1486 | static void ExitProcess32(Core::System& system) { | 1478 | static void ExitProcess32(Core::System& system) { |
| @@ -1552,8 +1544,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1552 | 1544 | ||
| 1553 | static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 priority, | 1545 | static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 priority, |
| 1554 | u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { | 1546 | u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { |
| 1555 | return CreateThread(system, out_handle, static_cast<VAddr>(entry_point), static_cast<u64>(arg), | 1547 | return CreateThread(system, out_handle, entry_point, arg, stack_top, priority, processor_id); |
| 1556 | static_cast<VAddr>(stack_top), priority, processor_id); | ||
| 1557 | } | 1548 | } |
| 1558 | 1549 | ||
| 1559 | /// Starts the thread for the provided handle | 1550 | /// Starts the thread for the provided handle |
| @@ -1581,8 +1572,8 @@ static ResultCode StartThread32(Core::System& system, Handle thread_handle) { | |||
| 1581 | static void ExitThread(Core::System& system) { | 1572 | static void ExitThread(Core::System& system) { |
| 1582 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); | 1573 | LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); |
| 1583 | 1574 | ||
| 1584 | auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); | 1575 | auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |
| 1585 | system.GlobalScheduler().RemoveThread(SharedFrom(current_thread)); | 1576 | system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread)); |
| 1586 | current_thread->Stop(); | 1577 | current_thread->Stop(); |
| 1587 | } | 1578 | } |
| 1588 | 1579 | ||
| @@ -1592,53 +1583,39 @@ static void ExitThread32(Core::System& system) { | |||
| 1592 | 1583 | ||
| 1593 | /// Sleep the current thread | 1584 | /// Sleep the current thread |
| 1594 | static void SleepThread(Core::System& system, s64 nanoseconds) { | 1585 | static void SleepThread(Core::System& system, s64 nanoseconds) { |
| 1595 | LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds); | 1586 | LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); |
| 1596 | 1587 | ||
| 1597 | enum class SleepType : s64 { | 1588 | enum class SleepType : s64 { |
| 1598 | YieldWithoutLoadBalancing = 0, | 1589 | YieldWithoutCoreMigration = 0, |
| 1599 | YieldWithLoadBalancing = -1, | 1590 | YieldWithCoreMigration = -1, |
| 1600 | YieldAndWaitForLoadBalancing = -2, | 1591 | YieldAndWaitForLoadBalancing = -2, |
| 1601 | }; | 1592 | }; |
| 1602 | 1593 | ||
| 1603 | auto& scheduler = system.CurrentScheduler(); | 1594 | auto& scheduler = *system.Kernel().CurrentScheduler(); |
| 1604 | auto* const current_thread = scheduler.GetCurrentThread(); | ||
| 1605 | bool is_redundant = false; | ||
| 1606 | |||
| 1607 | if (nanoseconds <= 0) { | 1595 | if (nanoseconds <= 0) { |
| 1608 | switch (static_cast<SleepType>(nanoseconds)) { | 1596 | switch (static_cast<SleepType>(nanoseconds)) { |
| 1609 | case SleepType::YieldWithoutLoadBalancing: { | 1597 | case SleepType::YieldWithoutCoreMigration: { |
| 1610 | auto pair = current_thread->YieldSimple(); | 1598 | scheduler.YieldWithoutCoreMigration(); |
| 1611 | is_redundant = pair.second; | ||
| 1612 | break; | 1599 | break; |
| 1613 | } | 1600 | } |
| 1614 | case SleepType::YieldWithLoadBalancing: { | 1601 | case SleepType::YieldWithCoreMigration: { |
| 1615 | auto pair = current_thread->YieldAndBalanceLoad(); | 1602 | scheduler.YieldWithCoreMigration(); |
| 1616 | is_redundant = pair.second; | ||
| 1617 | break; | 1603 | break; |
| 1618 | } | 1604 | } |
| 1619 | case SleepType::YieldAndWaitForLoadBalancing: { | 1605 | case SleepType::YieldAndWaitForLoadBalancing: { |
| 1620 | auto pair = current_thread->YieldAndWaitForLoadBalancing(); | 1606 | scheduler.YieldToAnyThread(); |
| 1621 | is_redundant = pair.second; | ||
| 1622 | break; | 1607 | break; |
| 1623 | } | 1608 | } |
| 1624 | default: | 1609 | default: |
| 1625 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); | 1610 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); |
| 1626 | } | 1611 | } |
| 1627 | } else { | 1612 | } else { |
| 1628 | current_thread->Sleep(nanoseconds); | 1613 | scheduler.GetCurrentThread()->Sleep(nanoseconds); |
| 1629 | } | ||
| 1630 | |||
| 1631 | if (is_redundant && !system.Kernel().IsMulticore()) { | ||
| 1632 | system.Kernel().ExitSVCProfile(); | ||
| 1633 | system.CoreTiming().AddTicks(1000U); | ||
| 1634 | system.GetCpuManager().PreemptSingleCore(); | ||
| 1635 | system.Kernel().EnterSVCProfile(); | ||
| 1636 | } | 1614 | } |
| 1637 | } | 1615 | } |
| 1638 | 1616 | ||
| 1639 | static void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high) { | 1617 | static void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high) { |
| 1640 | const s64 nanoseconds = static_cast<s64>(static_cast<u64>(nanoseconds_low) | | 1618 | const auto nanoseconds = static_cast<s64>(u64{nanoseconds_low} | (u64{nanoseconds_high} << 32)); |
| 1641 | (static_cast<u64>(nanoseconds_high) << 32)); | ||
| 1642 | SleepThread(system, nanoseconds); | 1619 | SleepThread(system, nanoseconds); |
| 1643 | } | 1620 | } |
| 1644 | 1621 | ||
| @@ -1668,10 +1645,10 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1668 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); | 1645 | ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); |
| 1669 | auto& kernel = system.Kernel(); | 1646 | auto& kernel = system.Kernel(); |
| 1670 | Handle event_handle; | 1647 | Handle event_handle; |
| 1671 | Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); | 1648 | Thread* current_thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 1672 | auto* const current_process = system.Kernel().CurrentProcess(); | 1649 | auto* const current_process = kernel.CurrentProcess(); |
| 1673 | { | 1650 | { |
| 1674 | SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds); | 1651 | KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds); |
| 1675 | const auto& handle_table = current_process->GetHandleTable(); | 1652 | const auto& handle_table = current_process->GetHandleTable(); |
| 1676 | std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); | 1653 | std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); |
| 1677 | ASSERT(thread); | 1654 | ASSERT(thread); |
| @@ -1707,7 +1684,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1707 | } | 1684 | } |
| 1708 | 1685 | ||
| 1709 | { | 1686 | { |
| 1710 | SchedulerLock lock(kernel); | 1687 | KScopedSchedulerLock lock(kernel); |
| 1711 | 1688 | ||
| 1712 | auto* owner = current_thread->GetLockOwner(); | 1689 | auto* owner = current_thread->GetLockOwner(); |
| 1713 | if (owner != nullptr) { | 1690 | if (owner != nullptr) { |
| @@ -1724,10 +1701,8 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add | |||
| 1724 | static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 mutex_addr, | 1701 | static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 mutex_addr, |
| 1725 | u32 condition_variable_addr, Handle thread_handle, | 1702 | u32 condition_variable_addr, Handle thread_handle, |
| 1726 | u32 nanoseconds_low, u32 nanoseconds_high) { | 1703 | u32 nanoseconds_low, u32 nanoseconds_high) { |
| 1727 | const s64 nanoseconds = | 1704 | const auto nanoseconds = static_cast<s64>(nanoseconds_low | (u64{nanoseconds_high} << 32)); |
| 1728 | static_cast<s64>(nanoseconds_low | (static_cast<u64>(nanoseconds_high) << 32)); | 1705 | return WaitProcessWideKeyAtomic(system, mutex_addr, condition_variable_addr, thread_handle, |
| 1729 | return WaitProcessWideKeyAtomic(system, static_cast<VAddr>(mutex_addr), | ||
| 1730 | static_cast<VAddr>(condition_variable_addr), thread_handle, | ||
| 1731 | nanoseconds); | 1706 | nanoseconds); |
| 1732 | } | 1707 | } |
| 1733 | 1708 | ||
| @@ -1740,7 +1715,7 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ | |||
| 1740 | 1715 | ||
| 1741 | // 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. |
| 1742 | auto& kernel = system.Kernel(); | 1717 | auto& kernel = system.Kernel(); |
| 1743 | SchedulerLock lock(kernel); | 1718 | KScopedSchedulerLock lock(kernel); |
| 1744 | auto* const current_process = kernel.CurrentProcess(); | 1719 | auto* const current_process = kernel.CurrentProcess(); |
| 1745 | std::vector<std::shared_ptr<Thread>> waiting_threads = | 1720 | std::vector<std::shared_ptr<Thread>> waiting_threads = |
| 1746 | current_process->GetConditionVariableThreads(condition_variable_addr); | 1721 | current_process->GetConditionVariableThreads(condition_variable_addr); |
| @@ -1833,8 +1808,8 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, | |||
| 1833 | 1808 | ||
| 1834 | static ResultCode WaitForAddress32(Core::System& system, u32 address, u32 type, s32 value, | 1809 | static ResultCode WaitForAddress32(Core::System& system, u32 address, u32 type, s32 value, |
| 1835 | u32 timeout_low, u32 timeout_high) { | 1810 | u32 timeout_low, u32 timeout_high) { |
| 1836 | s64 timeout = static_cast<s64>(timeout_low | (static_cast<u64>(timeout_high) << 32)); | 1811 | const auto timeout = static_cast<s64>(timeout_low | (u64{timeout_high} << 32)); |
| 1837 | return WaitForAddress(system, static_cast<VAddr>(address), type, value, timeout); | 1812 | return WaitForAddress(system, address, type, value, timeout); |
| 1838 | } | 1813 | } |
| 1839 | 1814 | ||
| 1840 | // Signals to an address (via Address Arbiter) | 1815 | // Signals to an address (via Address Arbiter) |
| @@ -1862,7 +1837,7 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, | |||
| 1862 | 1837 | ||
| 1863 | static ResultCode SignalToAddress32(Core::System& system, u32 address, u32 type, s32 value, | 1838 | static ResultCode SignalToAddress32(Core::System& system, u32 address, u32 type, s32 value, |
| 1864 | s32 num_to_wake) { | 1839 | s32 num_to_wake) { |
| 1865 | return SignalToAddress(system, static_cast<VAddr>(address), type, value, num_to_wake); | 1840 | return SignalToAddress(system, address, type, value, num_to_wake); |
| 1866 | } | 1841 | } |
| 1867 | 1842 | ||
| 1868 | static void KernelDebug([[maybe_unused]] Core::System& system, | 1843 | static void KernelDebug([[maybe_unused]] Core::System& system, |
| @@ -1893,7 +1868,7 @@ static u64 GetSystemTick(Core::System& system) { | |||
| 1893 | } | 1868 | } |
| 1894 | 1869 | ||
| 1895 | static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) { | 1870 | static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) { |
| 1896 | u64 time = GetSystemTick(system); | 1871 | const auto time = GetSystemTick(system); |
| 1897 | *time_low = static_cast<u32>(time); | 1872 | *time_low = static_cast<u32>(time); |
| 1898 | *time_high = static_cast<u32>(time >> 32); | 1873 | *time_high = static_cast<u32>(time >> 32); |
| 1899 | } | 1874 | } |
| @@ -1984,8 +1959,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1984 | 1959 | ||
| 1985 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, | 1960 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, |
| 1986 | u32 permissions) { | 1961 | u32 permissions) { |
| 1987 | return CreateTransferMemory(system, handle, static_cast<VAddr>(addr), | 1962 | return CreateTransferMemory(system, handle, addr, size, permissions); |
| 1988 | static_cast<std::size_t>(size), permissions); | ||
| 1989 | } | 1963 | } |
| 1990 | 1964 | ||
| 1991 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, | 1965 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, |
| @@ -2003,7 +1977,7 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 2003 | } | 1977 | } |
| 2004 | 1978 | ||
| 2005 | *core = thread->GetIdealCore(); | 1979 | *core = thread->GetIdealCore(); |
| 2006 | *mask = thread->GetAffinityMask(); | 1980 | *mask = thread->GetAffinityMask().GetAffinityMask(); |
| 2007 | 1981 | ||
| 2008 | return RESULT_SUCCESS; | 1982 | return RESULT_SUCCESS; |
| 2009 | } | 1983 | } |
| @@ -2075,8 +2049,7 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 2075 | 2049 | ||
| 2076 | static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core, | 2050 | static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core, |
| 2077 | u32 affinity_mask_low, u32 affinity_mask_high) { | 2051 | u32 affinity_mask_low, u32 affinity_mask_high) { |
| 2078 | const u64 affinity_mask = | 2052 | const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32); |
| 2079 | static_cast<u64>(affinity_mask_low) | (static_cast<u64>(affinity_mask_high) << 32); | ||
| 2080 | return SetThreadCoreMask(system, thread_handle, core, affinity_mask); | 2053 | return SetThreadCoreMask(system, thread_handle, core, affinity_mask); |
| 2081 | } | 2054 | } |
| 2082 | 2055 | ||
| @@ -2341,9 +2314,10 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd | |||
| 2341 | return RESULT_SUCCESS; | 2314 | return RESULT_SUCCESS; |
| 2342 | } | 2315 | } |
| 2343 | 2316 | ||
| 2344 | static ResultCode FlushProcessDataCache32(Core::System& system, Handle handle, u32 address, | 2317 | static ResultCode FlushProcessDataCache32([[maybe_unused]] Core::System& system, |
| 2345 | u32 size) { | 2318 | [[maybe_unused]] Handle handle, |
| 2346 | // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a nope | 2319 | [[maybe_unused]] u32 address, [[maybe_unused]] u32 size) { |
| 2320 | // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a no-op, | ||
| 2347 | // as all emulation is done in the same cache level in host architecture, thus data cache | 2321 | // as all emulation is done in the same cache level in host architecture, thus data cache |
| 2348 | // does not need flushing. | 2322 | // does not need flushing. |
| 2349 | LOG_DEBUG(Kernel_SVC, "called"); | 2323 | LOG_DEBUG(Kernel_SVC, "called"); |
| @@ -2639,6 +2613,9 @@ void Call(Core::System& system, u32 immediate) { | |||
| 2639 | auto& kernel = system.Kernel(); | 2613 | auto& kernel = system.Kernel(); |
| 2640 | kernel.EnterSVCProfile(); | 2614 | kernel.EnterSVCProfile(); |
| 2641 | 2615 | ||
| 2616 | auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); | ||
| 2617 | thread->SetContinuousOnSVC(true); | ||
| 2618 | |||
| 2642 | const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) | 2619 | const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) |
| 2643 | : GetSVCInfo32(immediate); | 2620 | : GetSVCInfo32(immediate); |
| 2644 | if (info) { | 2621 | if (info) { |
| @@ -2652,6 +2629,12 @@ void Call(Core::System& system, u32 immediate) { | |||
| 2652 | } | 2629 | } |
| 2653 | 2630 | ||
| 2654 | kernel.ExitSVCProfile(); | 2631 | kernel.ExitSVCProfile(); |
| 2632 | |||
| 2633 | if (!thread->IsContinuousOnSVC()) { | ||
| 2634 | auto* host_context = thread->GetHostContext().get(); | ||
| 2635 | host_context->Rewind(); | ||
| 2636 | } | ||
| 2637 | |||
| 2655 | system.EnterDynarmicProfile(); | 2638 | system.EnterDynarmicProfile(); |
| 2656 | } | 2639 | } |
| 2657 | 2640 | ||