diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 59 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.h | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 49 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 |
6 files changed, 108 insertions, 37 deletions
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 8c79b4f0f..cd863e715 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -275,11 +275,15 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a | |||
| 275 | shmem->Close(); | 275 | shmem->Close(); |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | void KProcess::RegisterThread(const KThread* thread) { | 278 | void KProcess::RegisterThread(KThread* thread) { |
| 279 | KScopedLightLock lk{list_lock}; | ||
| 280 | |||
| 279 | thread_list.push_back(thread); | 281 | thread_list.push_back(thread); |
| 280 | } | 282 | } |
| 281 | 283 | ||
| 282 | void KProcess::UnregisterThread(const KThread* thread) { | 284 | void KProcess::UnregisterThread(KThread* thread) { |
| 285 | KScopedLightLock lk{list_lock}; | ||
| 286 | |||
| 283 | thread_list.remove(thread); | 287 | thread_list.remove(thread); |
| 284 | } | 288 | } |
| 285 | 289 | ||
| @@ -297,6 +301,50 @@ ResultCode KProcess::Reset() { | |||
| 297 | return ResultSuccess; | 301 | return ResultSuccess; |
| 298 | } | 302 | } |
| 299 | 303 | ||
| 304 | ResultCode KProcess::SetActivity(ProcessActivity activity) { | ||
| 305 | // Lock ourselves and the scheduler. | ||
| 306 | KScopedLightLock lk{state_lock}; | ||
| 307 | KScopedLightLock list_lk{list_lock}; | ||
| 308 | KScopedSchedulerLock sl{kernel}; | ||
| 309 | |||
| 310 | // Validate our state. | ||
| 311 | R_UNLESS(status != ProcessStatus::Exiting, ResultInvalidState); | ||
| 312 | R_UNLESS(status != ProcessStatus::Exited, ResultInvalidState); | ||
| 313 | |||
| 314 | // Either pause or resume. | ||
| 315 | if (activity == ProcessActivity::Paused) { | ||
| 316 | // Verify that we're not suspended. | ||
| 317 | if (is_suspended) { | ||
| 318 | return ResultInvalidState; | ||
| 319 | } | ||
| 320 | |||
| 321 | // Suspend all threads. | ||
| 322 | for (auto* thread : GetThreadList()) { | ||
| 323 | thread->RequestSuspend(SuspendType::Process); | ||
| 324 | } | ||
| 325 | |||
| 326 | // Set ourselves as suspended. | ||
| 327 | SetSuspended(true); | ||
| 328 | } else { | ||
| 329 | ASSERT(activity == ProcessActivity::Runnable); | ||
| 330 | |||
| 331 | // Verify that we're suspended. | ||
| 332 | if (!is_suspended) { | ||
| 333 | return ResultInvalidState; | ||
| 334 | } | ||
| 335 | |||
| 336 | // Resume all threads. | ||
| 337 | for (auto* thread : GetThreadList()) { | ||
| 338 | thread->Resume(SuspendType::Process); | ||
| 339 | } | ||
| 340 | |||
| 341 | // Set ourselves as resumed. | ||
| 342 | SetSuspended(false); | ||
| 343 | } | ||
| 344 | |||
| 345 | return ResultSuccess; | ||
| 346 | } | ||
| 347 | |||
| 300 | ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | 348 | ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, |
| 301 | std::size_t code_size) { | 349 | std::size_t code_size) { |
| 302 | program_id = metadata.GetTitleID(); | 350 | program_id = metadata.GetTitleID(); |
| @@ -556,9 +604,10 @@ bool KProcess::IsSignaled() const { | |||
| 556 | } | 604 | } |
| 557 | 605 | ||
| 558 | KProcess::KProcess(KernelCore& kernel_) | 606 | KProcess::KProcess(KernelCore& kernel_) |
| 559 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, | 607 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, page_table{std::make_unique<KPageTable>( |
| 560 | page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_}, | 608 | kernel_.System())}, |
| 561 | address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {} | 609 | handle_table{kernel_}, address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, |
| 610 | state_lock{kernel_}, list_lock{kernel_} {} | ||
| 562 | 611 | ||
| 563 | KProcess::~KProcess() = default; | 612 | KProcess::~KProcess() = default; |
| 564 | 613 | ||
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 9f171e3da..e562a79b8 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -63,6 +63,11 @@ enum class ProcessStatus { | |||
| 63 | DebugBreak, | 63 | DebugBreak, |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | enum class ProcessActivity : u32 { | ||
| 67 | Runnable, | ||
| 68 | Paused, | ||
| 69 | }; | ||
| 70 | |||
| 66 | class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { | 71 | class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { |
| 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); | 72 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); |
| 68 | 73 | ||
| @@ -282,17 +287,17 @@ public: | |||
| 282 | u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const; | 287 | u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const; |
| 283 | 288 | ||
| 284 | /// Gets the list of all threads created with this process as their owner. | 289 | /// Gets the list of all threads created with this process as their owner. |
| 285 | const std::list<const KThread*>& GetThreadList() const { | 290 | std::list<KThread*>& GetThreadList() { |
| 286 | return thread_list; | 291 | return thread_list; |
| 287 | } | 292 | } |
| 288 | 293 | ||
| 289 | /// Registers a thread as being created under this process, | 294 | /// Registers a thread as being created under this process, |
| 290 | /// adding it to this process' thread list. | 295 | /// adding it to this process' thread list. |
| 291 | void RegisterThread(const KThread* thread); | 296 | void RegisterThread(KThread* thread); |
| 292 | 297 | ||
| 293 | /// Unregisters a thread from this process, removing it | 298 | /// Unregisters a thread from this process, removing it |
| 294 | /// from this process' thread list. | 299 | /// from this process' thread list. |
| 295 | void UnregisterThread(const KThread* thread); | 300 | void UnregisterThread(KThread* thread); |
| 296 | 301 | ||
| 297 | /// Clears the signaled state of the process if and only if it's signaled. | 302 | /// Clears the signaled state of the process if and only if it's signaled. |
| 298 | /// | 303 | /// |
| @@ -347,6 +352,8 @@ public: | |||
| 347 | 352 | ||
| 348 | void DoWorkerTaskImpl(); | 353 | void DoWorkerTaskImpl(); |
| 349 | 354 | ||
| 355 | ResultCode SetActivity(ProcessActivity activity); | ||
| 356 | |||
| 350 | void PinCurrentThread(s32 core_id); | 357 | void PinCurrentThread(s32 core_id); |
| 351 | void UnpinCurrentThread(s32 core_id); | 358 | void UnpinCurrentThread(s32 core_id); |
| 352 | void UnpinThread(KThread* thread); | 359 | void UnpinThread(KThread* thread); |
| @@ -442,7 +449,7 @@ private: | |||
| 442 | std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; | 449 | std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; |
| 443 | 450 | ||
| 444 | /// List of threads that are running with this process as their owner. | 451 | /// List of threads that are running with this process as their owner. |
| 445 | std::list<const KThread*> thread_list; | 452 | std::list<KThread*> thread_list; |
| 446 | 453 | ||
| 447 | /// List of shared memory that are running with this process as their owner. | 454 | /// List of shared memory that are running with this process as their owner. |
| 448 | std::list<KSharedMemoryInfo*> shared_memory_list; | 455 | std::list<KSharedMemoryInfo*> shared_memory_list; |
| @@ -475,6 +482,7 @@ private: | |||
| 475 | KThread* exception_thread{}; | 482 | KThread* exception_thread{}; |
| 476 | 483 | ||
| 477 | KLightLock state_lock; | 484 | KLightLock state_lock; |
| 485 | KLightLock list_lock; | ||
| 478 | 486 | ||
| 479 | using TLPTree = | 487 | using TLPTree = |
| 480 | Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>; | 488 | Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>; |
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index ea2160099..8d48a7901 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -267,15 +267,15 @@ ResultCode KThread::InitializeDummyThread(KThread* thread) { | |||
| 267 | ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { | 267 | ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { |
| 268 | return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, | 268 | return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, |
| 269 | Core::CpuManager::GetIdleThreadStartFunc(), | 269 | Core::CpuManager::GetIdleThreadStartFunc(), |
| 270 | system.GetCpuManager().GetStartFuncParamater()); | 270 | system.GetCpuManager().GetStartFuncParameter()); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, | 273 | ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, |
| 274 | KThreadFunction func, uintptr_t arg, | 274 | KThreadFunction func, uintptr_t arg, |
| 275 | s32 virt_core) { | 275 | s32 virt_core) { |
| 276 | return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, | 276 | return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, |
| 277 | Core::CpuManager::GetSuspendThreadStartFunc(), | 277 | Core::CpuManager::GetShutdownThreadStartFunc(), |
| 278 | system.GetCpuManager().GetStartFuncParamater()); | 278 | system.GetCpuManager().GetStartFuncParameter()); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, | 281 | ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, |
| @@ -284,7 +284,7 @@ ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, | |||
| 284 | system.Kernel().GlobalSchedulerContext().AddThread(thread); | 284 | system.Kernel().GlobalSchedulerContext().AddThread(thread); |
| 285 | return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, | 285 | return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, |
| 286 | ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), | 286 | ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), |
| 287 | system.GetCpuManager().GetStartFuncParamater()); | 287 | system.GetCpuManager().GetStartFuncParameter()); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | void KThread::PostDestroy(uintptr_t arg) { | 290 | void KThread::PostDestroy(uintptr_t arg) { |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b2c4f12b4..73593c7a0 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -76,7 +76,7 @@ struct KernelCore::Impl { | |||
| 76 | InitializeMemoryLayout(); | 76 | InitializeMemoryLayout(); |
| 77 | Init::InitializeKPageBufferSlabHeap(system); | 77 | Init::InitializeKPageBufferSlabHeap(system); |
| 78 | InitializeSchedulers(); | 78 | InitializeSchedulers(); |
| 79 | InitializeSuspendThreads(); | 79 | InitializeShutdownThreads(); |
| 80 | InitializePreemption(kernel); | 80 | InitializePreemption(kernel); |
| 81 | 81 | ||
| 82 | RegisterHostThread(); | 82 | RegisterHostThread(); |
| @@ -143,9 +143,9 @@ struct KernelCore::Impl { | |||
| 143 | CleanupObject(system_resource_limit); | 143 | CleanupObject(system_resource_limit); |
| 144 | 144 | ||
| 145 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { | 145 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 146 | if (suspend_threads[core_id]) { | 146 | if (shutdown_threads[core_id]) { |
| 147 | suspend_threads[core_id]->Close(); | 147 | shutdown_threads[core_id]->Close(); |
| 148 | suspend_threads[core_id] = nullptr; | 148 | shutdown_threads[core_id] = nullptr; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | schedulers[core_id]->Finalize(); | 151 | schedulers[core_id]->Finalize(); |
| @@ -247,14 +247,14 @@ struct KernelCore::Impl { | |||
| 247 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | 247 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | void InitializeSuspendThreads() { | 250 | void InitializeShutdownThreads() { |
| 251 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { | 251 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { |
| 252 | suspend_threads[core_id] = KThread::Create(system.Kernel()); | 252 | shutdown_threads[core_id] = KThread::Create(system.Kernel()); |
| 253 | ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id], {}, {}, | 253 | ASSERT(KThread::InitializeHighPriorityThread(system, shutdown_threads[core_id], {}, {}, |
| 254 | core_id) | 254 | core_id) |
| 255 | .IsSuccess()); | 255 | .IsSuccess()); |
| 256 | suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id)); | 256 | shutdown_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id)); |
| 257 | suspend_threads[core_id]->DisableDispatch(); | 257 | shutdown_threads[core_id]->DisableDispatch(); |
| 258 | } | 258 | } |
| 259 | } | 259 | } |
| 260 | 260 | ||
| @@ -769,7 +769,7 @@ struct KernelCore::Impl { | |||
| 769 | std::weak_ptr<ServiceThread> default_service_thread; | 769 | std::weak_ptr<ServiceThread> default_service_thread; |
| 770 | Common::ThreadWorker service_threads_manager; | 770 | Common::ThreadWorker service_threads_manager; |
| 771 | 771 | ||
| 772 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; | 772 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; |
| 773 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; | 773 | std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; |
| 774 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; | 774 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; |
| 775 | 775 | ||
| @@ -920,6 +920,12 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const { | |||
| 920 | return *impl->global_object_list_container; | 920 | return *impl->global_object_list_container; |
| 921 | } | 921 | } |
| 922 | 922 | ||
| 923 | void KernelCore::InterruptAllPhysicalCores() { | ||
| 924 | for (auto& physical_core : impl->cores) { | ||
| 925 | physical_core.Interrupt(); | ||
| 926 | } | ||
| 927 | } | ||
| 928 | |||
| 923 | void KernelCore::InvalidateAllInstructionCaches() { | 929 | void KernelCore::InvalidateAllInstructionCaches() { |
| 924 | for (auto& physical_core : impl->cores) { | 930 | for (auto& physical_core : impl->cores) { |
| 925 | physical_core.ArmInterface().ClearInstructionCache(); | 931 | physical_core.ArmInterface().ClearInstructionCache(); |
| @@ -1067,17 +1073,20 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const { | |||
| 1067 | return *impl->hidbus_shared_mem; | 1073 | return *impl->hidbus_shared_mem; |
| 1068 | } | 1074 | } |
| 1069 | 1075 | ||
| 1070 | void KernelCore::Suspend(bool in_suspention) { | 1076 | void KernelCore::Suspend(bool suspended) { |
| 1071 | const bool should_suspend = exception_exited || in_suspention; | 1077 | const bool should_suspend{exception_exited || suspended}; |
| 1072 | { | 1078 | const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; |
| 1073 | KScopedSchedulerLock lock(*this); | 1079 | |
| 1074 | const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; | 1080 | for (auto* process : GetProcessList()) { |
| 1075 | for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { | 1081 | process->SetActivity(activity); |
| 1076 | impl->suspend_threads[core_id]->SetState(state); | 1082 | } |
| 1077 | impl->suspend_threads[core_id]->SetWaitReasonForDebugging( | 1083 | } |
| 1078 | ThreadWaitReasonForDebugging::Suspended); | 1084 | |
| 1079 | } | 1085 | void KernelCore::ShutdownCores() { |
| 1086 | for (auto* thread : impl->shutdown_threads) { | ||
| 1087 | void(thread->Run()); | ||
| 1080 | } | 1088 | } |
| 1089 | InterruptAllPhysicalCores(); | ||
| 1081 | } | 1090 | } |
| 1082 | 1091 | ||
| 1083 | bool KernelCore::IsMulticore() const { | 1092 | bool KernelCore::IsMulticore() const { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 926e14c6f..4e7beab0e 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -184,6 +184,8 @@ public: | |||
| 184 | 184 | ||
| 185 | const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; | 185 | const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; |
| 186 | 186 | ||
| 187 | void InterruptAllPhysicalCores(); | ||
| 188 | |||
| 187 | void InvalidateAllInstructionCaches(); | 189 | void InvalidateAllInstructionCaches(); |
| 188 | 190 | ||
| 189 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | 191 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); |
| @@ -269,12 +271,15 @@ public: | |||
| 269 | /// Gets the shared memory object for HIDBus services. | 271 | /// Gets the shared memory object for HIDBus services. |
| 270 | const Kernel::KSharedMemory& GetHidBusSharedMem() const; | 272 | const Kernel::KSharedMemory& GetHidBusSharedMem() const; |
| 271 | 273 | ||
| 272 | /// Suspend/unsuspend the OS. | 274 | /// Suspend/unsuspend all processes. |
| 273 | void Suspend(bool in_suspention); | 275 | void Suspend(bool suspend); |
| 274 | 276 | ||
| 275 | /// Exceptional exit the OS. | 277 | /// Exceptional exit all processes. |
| 276 | void ExceptionalExit(); | 278 | void ExceptionalExit(); |
| 277 | 279 | ||
| 280 | /// Notify emulated CPU cores to shut down. | ||
| 281 | void ShutdownCores(); | ||
| 282 | |||
| 278 | bool IsMulticore() const; | 283 | bool IsMulticore() const; |
| 279 | 284 | ||
| 280 | bool IsShuttingDown() const; | 285 | bool IsShuttingDown() const; |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4f0a44363..47db0bacf 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -2537,7 +2537,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd | |||
| 2537 | return ResultOutOfRange; | 2537 | return ResultOutOfRange; |
| 2538 | } | 2538 | } |
| 2539 | 2539 | ||
| 2540 | const auto* const current_process = system.Kernel().CurrentProcess(); | 2540 | auto* const current_process = system.Kernel().CurrentProcess(); |
| 2541 | const auto total_copy_size = out_thread_ids_size * sizeof(u64); | 2541 | const auto total_copy_size = out_thread_ids_size * sizeof(u64); |
| 2542 | 2542 | ||
| 2543 | if (out_thread_ids_size > 0 && | 2543 | if (out_thread_ids_size > 0 && |