summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/k_process.cpp59
-rw-r--r--src/core/hle/kernel/k_process.h16
-rw-r--r--src/core/hle/kernel/k_thread.cpp8
-rw-r--r--src/core/hle/kernel/kernel.cpp49
-rw-r--r--src/core/hle/kernel/kernel.h11
-rw-r--r--src/core/hle/kernel/svc.cpp2
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
278void KProcess::RegisterThread(const KThread* thread) { 278void 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
282void KProcess::UnregisterThread(const KThread* thread) { 284void 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
304ResultCode 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
300ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, 348ResultCode 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
558KProcess::KProcess(KernelCore& kernel_) 606KProcess::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
563KProcess::~KProcess() = default; 612KProcess::~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
66enum class ProcessActivity : u32 {
67 Runnable,
68 Paused,
69};
70
66class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { 71class 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) {
267ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { 267ResultCode 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
273ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, 273ResultCode 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
281ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, 281ResultCode 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
290void KThread::PostDestroy(uintptr_t arg) { 290void 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
923void KernelCore::InterruptAllPhysicalCores() {
924 for (auto& physical_core : impl->cores) {
925 physical_core.Interrupt();
926 }
927}
928
923void KernelCore::InvalidateAllInstructionCaches() { 929void 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
1070void KernelCore::Suspend(bool in_suspention) { 1076void 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 } 1085void KernelCore::ShutdownCores() {
1086 for (auto* thread : impl->shutdown_threads) {
1087 void(thread->Run());
1080 } 1088 }
1089 InterruptAllPhysicalCores();
1081} 1090}
1082 1091
1083bool KernelCore::IsMulticore() const { 1092bool 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 &&