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/address_arbiter.cpp6
-rw-r--r--src/core/hle/kernel/address_arbiter.h3
-rw-r--r--src/core/hle/kernel/kernel.cpp28
-rw-r--r--src/core/hle/kernel/kernel.h5
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp5
-rw-r--r--src/core/hle/kernel/physical_core.cpp38
-rw-r--r--src/core/hle/kernel/physical_core.h33
-rw-r--r--src/core/hle/kernel/scheduler.cpp66
-rw-r--r--src/core/hle/kernel/scheduler.h2
-rw-r--r--src/core/hle/kernel/svc.cpp9
-rw-r--r--src/core/hle/kernel/synchronization_object.h3
-rw-r--r--src/core/hle/kernel/thread.cpp32
-rw-r--r--src/core/hle/kernel/thread.h6
-rw-r--r--src/core/hle/kernel/time_manager.cpp9
-rw-r--r--src/core/hle/kernel/time_manager.h2
15 files changed, 132 insertions, 115 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index b882eaa0f..048acd30e 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -275,12 +275,6 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
275 return current_thread->GetSignalingResult(); 275 return current_thread->GetSignalingResult();
276} 276}
277 277
278void AddressArbiter::HandleWakeupThread(std::shared_ptr<Thread> thread) {
279 ASSERT(thread->GetStatus() == ThreadStatus::WaitArb);
280 RemoveThread(thread);
281 thread->SetArbiterWaitAddress(0);
282}
283
284void AddressArbiter::InsertThread(std::shared_ptr<Thread> thread) { 278void AddressArbiter::InsertThread(std::shared_ptr<Thread> thread) {
285 const VAddr arb_addr = thread->GetArbiterWaitAddress(); 279 const VAddr arb_addr = thread->GetArbiterWaitAddress();
286 std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr]; 280 std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr];
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 0b05d533c..b91edc67d 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -50,9 +50,6 @@ public:
50 /// Waits on an address with a particular arbitration type. 50 /// Waits on an address with a particular arbitration type.
51 ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns); 51 ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns);
52 52
53 /// Removes a thread from the container and resets its address arbiter adress to 0
54 void HandleWakeupThread(std::shared_ptr<Thread> thread);
55
56private: 53private:
57 /// Signals an address being waited on. 54 /// Signals an address being waited on.
58 ResultCode SignalToAddressOnly(VAddr address, s32 num_to_wake); 55 ResultCode SignalToAddressOnly(VAddr address, s32 num_to_wake);
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index bb3e312a7..929db696d 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -68,6 +68,12 @@ struct KernelCore::Impl {
68 InitializeSuspendThreads(); 68 InitializeSuspendThreads();
69 } 69 }
70 70
71 void InitializeCores() {
72 for (auto& core : cores) {
73 core.Initialize(current_process->Is64BitProcess());
74 }
75 }
76
71 void Shutdown() { 77 void Shutdown() {
72 next_object_id = 0; 78 next_object_id = 0;
73 next_kernel_process_id = Process::InitialKIPIDMin; 79 next_kernel_process_id = Process::InitialKIPIDMin;
@@ -116,7 +122,7 @@ struct KernelCore::Impl {
116 Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES); 122 Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
117 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 123 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
118 schedulers[i] = std::make_unique<Kernel::Scheduler>(system, i); 124 schedulers[i] = std::make_unique<Kernel::Scheduler>(system, i);
119 cores.emplace_back(system, i, *schedulers[i], interrupts[i]); 125 cores.emplace_back(i, system, *schedulers[i], interrupts);
120 } 126 }
121 } 127 }
122 128
@@ -181,6 +187,7 @@ struct KernelCore::Impl {
181 if (process == nullptr) { 187 if (process == nullptr) {
182 return; 188 return;
183 } 189 }
190
184 const u32 core_id = GetCurrentHostThreadID(); 191 const u32 core_id = GetCurrentHostThreadID();
185 if (core_id < Core::Hardware::NUM_CPU_CORES) { 192 if (core_id < Core::Hardware::NUM_CPU_CORES) {
186 system.Memory().SetCurrentPageTable(*process, core_id); 193 system.Memory().SetCurrentPageTable(*process, core_id);
@@ -372,6 +379,10 @@ void KernelCore::Initialize() {
372 impl->Initialize(*this); 379 impl->Initialize(*this);
373} 380}
374 381
382void KernelCore::InitializeCores() {
383 impl->InitializeCores();
384}
385
375void KernelCore::Shutdown() { 386void KernelCore::Shutdown() {
376 impl->Shutdown(); 387 impl->Shutdown();
377} 388}
@@ -486,12 +497,17 @@ const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
486} 497}
487 498
488void KernelCore::InvalidateAllInstructionCaches() { 499void KernelCore::InvalidateAllInstructionCaches() {
489 auto& threads = GlobalScheduler().GetThreadList(); 500 for (auto& physical_core : impl->cores) {
490 for (auto& thread : threads) { 501 physical_core.ArmInterface().ClearInstructionCache();
491 if (!thread->IsHLEThread()) { 502 }
492 auto& arm_interface = thread->ArmInterface(); 503}
493 arm_interface.ClearInstructionCache(); 504
505void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
506 for (auto& physical_core : impl->cores) {
507 if (!physical_core.IsInitialized()) {
508 continue;
494 } 509 }
510 physical_core.ArmInterface().InvalidateCacheRange(addr, size);
495 } 511 }
496} 512}
497 513
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 16285c3f0..a73a93039 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -74,6 +74,9 @@ public:
74 /// Resets the kernel to a clean slate for use. 74 /// Resets the kernel to a clean slate for use.
75 void Initialize(); 75 void Initialize();
76 76
77 /// Initializes the CPU cores.
78 void InitializeCores();
79
77 /// Clears all resources in use by the kernel instance. 80 /// Clears all resources in use by the kernel instance.
78 void Shutdown(); 81 void Shutdown();
79 82
@@ -153,6 +156,8 @@ public:
153 156
154 void InvalidateAllInstructionCaches(); 157 void InvalidateAllInstructionCaches();
155 158
159 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
160
156 /// Adds a port to the named port table 161 /// Adds a port to the named port table
157 void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); 162 void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
158 163
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
index a3fadb533..f53a7be82 100644
--- a/src/core/hle/kernel/memory/page_table.cpp
+++ b/src/core/hle/kernel/memory/page_table.cpp
@@ -670,6 +670,11 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo
670 return RESULT_SUCCESS; 670 return RESULT_SUCCESS;
671 } 671 }
672 672
673 if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) {
674 // Memory execution state is changing, invalidate CPU cache range
675 system.InvalidateCpuInstructionCacheRange(addr, size);
676 }
677
673 const std::size_t num_pages{size / PageSize}; 678 const std::size_t num_pages{size / PageSize};
674 const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None 679 const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
675 ? OperationType::ChangePermissionsAndRefresh 680 ? OperationType::ChangePermissionsAndRefresh
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index 6e04d025f..50aca5752 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -4,21 +4,43 @@
4 4
5#include "common/spin_lock.h" 5#include "common/spin_lock.h"
6#include "core/arm/cpu_interrupt_handler.h" 6#include "core/arm/cpu_interrupt_handler.h"
7#include "core/arm/dynarmic/arm_dynarmic_32.h"
8#include "core/arm/dynarmic/arm_dynarmic_64.h"
7#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/physical_core.h" 11#include "core/hle/kernel/physical_core.h"
9#include "core/hle/kernel/scheduler.h" 12#include "core/hle/kernel/scheduler.h"
10 13
11namespace Kernel { 14namespace Kernel {
12 15
13PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler, 16PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system,
14 Core::CPUInterruptHandler& interrupt_handler) 17 Kernel::Scheduler& scheduler, Core::CPUInterrupts& interrupts)
15 : interrupt_handler{interrupt_handler}, 18 : core_index{core_index}, system{system}, scheduler{scheduler},
16 core_index{id}, scheduler{scheduler}, guard{std::make_unique<Common::SpinLock>()} {} 19 interrupts{interrupts}, guard{std::make_unique<Common::SpinLock>()} {}
17 20
18PhysicalCore::~PhysicalCore() = default; 21PhysicalCore::~PhysicalCore() = default;
19 22
23void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) {
24#ifdef ARCHITECTURE_x86_64
25 auto& kernel = system.Kernel();
26 if (is_64_bit) {
27 arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
28 system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
29 } else {
30 arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
31 system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
32 }
33#else
34#error Platform not supported yet.
35#endif
36}
37
38void PhysicalCore::Run() {
39 arm_interface->Run();
40}
41
20void PhysicalCore::Idle() { 42void PhysicalCore::Idle() {
21 interrupt_handler.AwaitInterrupt(); 43 interrupts[core_index].AwaitInterrupt();
22} 44}
23 45
24void PhysicalCore::Shutdown() { 46void PhysicalCore::Shutdown() {
@@ -26,18 +48,18 @@ void PhysicalCore::Shutdown() {
26} 48}
27 49
28bool PhysicalCore::IsInterrupted() const { 50bool PhysicalCore::IsInterrupted() const {
29 return interrupt_handler.IsInterrupted(); 51 return interrupts[core_index].IsInterrupted();
30} 52}
31 53
32void PhysicalCore::Interrupt() { 54void PhysicalCore::Interrupt() {
33 guard->lock(); 55 guard->lock();
34 interrupt_handler.SetInterrupt(true); 56 interrupts[core_index].SetInterrupt(true);
35 guard->unlock(); 57 guard->unlock();
36} 58}
37 59
38void PhysicalCore::ClearInterrupt() { 60void PhysicalCore::ClearInterrupt() {
39 guard->lock(); 61 guard->lock();
40 interrupt_handler.SetInterrupt(false); 62 interrupts[core_index].SetInterrupt(false);
41 guard->unlock(); 63 guard->unlock();
42} 64}
43 65
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h
index d7a7a951c..37513130a 100644
--- a/src/core/hle/kernel/physical_core.h
+++ b/src/core/hle/kernel/physical_core.h
@@ -4,9 +4,12 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <cstddef> 8#include <cstddef>
8#include <memory> 9#include <memory>
9 10
11#include "core/arm/arm_interface.h"
12
10namespace Common { 13namespace Common {
11class SpinLock; 14class SpinLock;
12} 15}
@@ -16,7 +19,6 @@ class Scheduler;
16} // namespace Kernel 19} // namespace Kernel
17 20
18namespace Core { 21namespace Core {
19class ARM_Interface;
20class CPUInterruptHandler; 22class CPUInterruptHandler;
21class ExclusiveMonitor; 23class ExclusiveMonitor;
22class System; 24class System;
@@ -26,8 +28,8 @@ namespace Kernel {
26 28
27class PhysicalCore { 29class PhysicalCore {
28public: 30public:
29 PhysicalCore(Core::System& system, std::size_t id, Kernel::Scheduler& scheduler, 31 PhysicalCore(std::size_t core_index, Core::System& system, Kernel::Scheduler& scheduler,
30 Core::CPUInterruptHandler& interrupt_handler); 32 Core::CPUInterrupts& interrupts);
31 ~PhysicalCore(); 33 ~PhysicalCore();
32 34
33 PhysicalCore(const PhysicalCore&) = delete; 35 PhysicalCore(const PhysicalCore&) = delete;
@@ -36,7 +38,14 @@ public:
36 PhysicalCore(PhysicalCore&&) = default; 38 PhysicalCore(PhysicalCore&&) = default;
37 PhysicalCore& operator=(PhysicalCore&&) = default; 39 PhysicalCore& operator=(PhysicalCore&&) = default;
38 40
41 /// Initialize the core for the specified parameters.
42 void Initialize(bool is_64_bit);
43
44 /// Execute current jit state
45 void Run();
46
39 void Idle(); 47 void Idle();
48
40 /// Interrupt this physical core. 49 /// Interrupt this physical core.
41 void Interrupt(); 50 void Interrupt();
42 51
@@ -49,6 +58,18 @@ public:
49 // Shutdown this physical core. 58 // Shutdown this physical core.
50 void Shutdown(); 59 void Shutdown();
51 60
61 bool IsInitialized() const {
62 return arm_interface != nullptr;
63 }
64
65 Core::ARM_Interface& ArmInterface() {
66 return *arm_interface;
67 }
68
69 const Core::ARM_Interface& ArmInterface() const {
70 return *arm_interface;
71 }
72
52 bool IsMainCore() const { 73 bool IsMainCore() const {
53 return core_index == 0; 74 return core_index == 0;
54 } 75 }
@@ -70,10 +91,12 @@ public:
70 } 91 }
71 92
72private: 93private:
73 Core::CPUInterruptHandler& interrupt_handler; 94 const std::size_t core_index;
74 std::size_t core_index; 95 Core::System& system;
75 Kernel::Scheduler& scheduler; 96 Kernel::Scheduler& scheduler;
97 Core::CPUInterrupts& interrupts;
76 std::unique_ptr<Common::SpinLock> guard; 98 std::unique_ptr<Common::SpinLock> guard;
99 std::unique_ptr<Core::ARM_Interface> arm_interface;
77}; 100};
78 101
79} // namespace Kernel 102} // namespace Kernel
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 6b7db5372..5c63b0b4a 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -618,14 +618,16 @@ void Scheduler::OnThreadStart() {
618 SwitchContextStep2(); 618 SwitchContextStep2();
619} 619}
620 620
621void Scheduler::Unload() { 621void Scheduler::Unload(Thread* thread) {
622 Thread* thread = current_thread.get();
623 if (thread) { 622 if (thread) {
624 thread->SetContinuousOnSVC(false);
625 thread->last_running_ticks = system.CoreTiming().GetCPUTicks(); 623 thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
626 thread->SetIsRunning(false); 624 thread->SetIsRunning(false);
625 if (thread->IsContinuousOnSVC() && !thread->IsHLEThread()) {
626 system.ArmInterface(core_id).ExceptionalExit();
627 thread->SetContinuousOnSVC(false);
628 }
627 if (!thread->IsHLEThread() && !thread->HasExited()) { 629 if (!thread->IsHLEThread() && !thread->HasExited()) {
628 Core::ARM_Interface& cpu_core = thread->ArmInterface(); 630 Core::ARM_Interface& cpu_core = system.ArmInterface(core_id);
629 cpu_core.SaveContext(thread->GetContext32()); 631 cpu_core.SaveContext(thread->GetContext32());
630 cpu_core.SaveContext(thread->GetContext64()); 632 cpu_core.SaveContext(thread->GetContext64());
631 // Save the TPIDR_EL0 system register in case it was modified. 633 // Save the TPIDR_EL0 system register in case it was modified.
@@ -636,8 +638,11 @@ void Scheduler::Unload() {
636 } 638 }
637} 639}
638 640
639void Scheduler::Reload() { 641void Scheduler::Unload() {
640 Thread* thread = current_thread.get(); 642 Unload(current_thread.get());
643}
644
645void Scheduler::Reload(Thread* thread) {
641 if (thread) { 646 if (thread) {
642 ASSERT_MSG(thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable, 647 ASSERT_MSG(thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable,
643 "Thread must be runnable."); 648 "Thread must be runnable.");
@@ -652,42 +657,23 @@ void Scheduler::Reload() {
652 system.Kernel().MakeCurrentProcess(thread_owner_process); 657 system.Kernel().MakeCurrentProcess(thread_owner_process);
653 } 658 }
654 if (!thread->IsHLEThread()) { 659 if (!thread->IsHLEThread()) {
655 Core::ARM_Interface& cpu_core = thread->ArmInterface(); 660 Core::ARM_Interface& cpu_core = system.ArmInterface(core_id);
656 cpu_core.LoadContext(thread->GetContext32()); 661 cpu_core.LoadContext(thread->GetContext32());
657 cpu_core.LoadContext(thread->GetContext64()); 662 cpu_core.LoadContext(thread->GetContext64());
658 cpu_core.SetTlsAddress(thread->GetTLSAddress()); 663 cpu_core.SetTlsAddress(thread->GetTLSAddress());
659 cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0()); 664 cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0());
660 cpu_core.ChangeProcessorID(this->core_id);
661 cpu_core.ClearExclusiveState(); 665 cpu_core.ClearExclusiveState();
662 } 666 }
663 } 667 }
664} 668}
665 669
670void Scheduler::Reload() {
671 Reload(current_thread.get());
672}
673
666void Scheduler::SwitchContextStep2() { 674void Scheduler::SwitchContextStep2() {
667 // Load context of new thread 675 // Load context of new thread
668 if (selected_thread) { 676 Reload(selected_thread.get());
669 ASSERT_MSG(selected_thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable,
670 "Thread must be runnable.");
671
672 // Cancel any outstanding wakeup events for this thread
673 selected_thread->SetIsRunning(true);
674 selected_thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
675 selected_thread->SetWasRunning(false);
676
677 auto* const thread_owner_process = current_thread->GetOwnerProcess();
678 if (thread_owner_process != nullptr) {
679 system.Kernel().MakeCurrentProcess(thread_owner_process);
680 }
681 if (!selected_thread->IsHLEThread()) {
682 Core::ARM_Interface& cpu_core = selected_thread->ArmInterface();
683 cpu_core.LoadContext(selected_thread->GetContext32());
684 cpu_core.LoadContext(selected_thread->GetContext64());
685 cpu_core.SetTlsAddress(selected_thread->GetTLSAddress());
686 cpu_core.SetTPIDR_EL0(selected_thread->GetTPIDR_EL0());
687 cpu_core.ChangeProcessorID(this->core_id);
688 cpu_core.ClearExclusiveState();
689 }
690 }
691 677
692 TryDoContextSwitch(); 678 TryDoContextSwitch();
693} 679}
@@ -711,23 +697,7 @@ void Scheduler::SwitchContext() {
711 UpdateLastContextSwitchTime(previous_thread, previous_process); 697 UpdateLastContextSwitchTime(previous_thread, previous_process);
712 698
713 // Save context for previous thread 699 // Save context for previous thread
714 if (previous_thread) { 700 Unload(previous_thread);
715 if (new_thread != nullptr && new_thread->IsSuspendThread()) {
716 previous_thread->SetWasRunning(true);
717 }
718 previous_thread->SetContinuousOnSVC(false);
719 previous_thread->last_running_ticks = system.CoreTiming().GetCPUTicks();
720 previous_thread->SetIsRunning(false);
721 if (!previous_thread->IsHLEThread() && !previous_thread->HasExited()) {
722 Core::ARM_Interface& cpu_core = previous_thread->ArmInterface();
723 cpu_core.SaveContext(previous_thread->GetContext32());
724 cpu_core.SaveContext(previous_thread->GetContext64());
725 // Save the TPIDR_EL0 system register in case it was modified.
726 previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0());
727 cpu_core.ClearExclusiveState();
728 }
729 previous_thread->context_guard.unlock();
730 }
731 701
732 std::shared_ptr<Common::Fiber>* old_context; 702 std::shared_ptr<Common::Fiber>* old_context;
733 if (previous_thread != nullptr) { 703 if (previous_thread != nullptr) {
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index b6f04dcea..68db4a5ef 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -212,8 +212,10 @@ public:
212 212
213 /// The next two are for SingleCore Only. 213 /// The next two are for SingleCore Only.
214 /// Unload current thread before preempting core. 214 /// Unload current thread before preempting core.
215 void Unload(Thread* thread);
215 void Unload(); 216 void Unload();
216 /// Reload current thread after core preemption. 217 /// Reload current thread after core preemption.
218 void Reload(Thread* thread);
217 void Reload(); 219 void Reload();
218 220
219 /// Gets the current running thread 221 /// Gets the current running thread
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index e3b770d66..95d6e2b4d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -2639,6 +2639,9 @@ void Call(Core::System& system, u32 immediate) {
2639 auto& kernel = system.Kernel(); 2639 auto& kernel = system.Kernel();
2640 kernel.EnterSVCProfile(); 2640 kernel.EnterSVCProfile();
2641 2641
2642 auto* thread = system.CurrentScheduler().GetCurrentThread();
2643 thread->SetContinuousOnSVC(true);
2644
2642 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) 2645 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
2643 : GetSVCInfo32(immediate); 2646 : GetSVCInfo32(immediate);
2644 if (info) { 2647 if (info) {
@@ -2652,6 +2655,12 @@ void Call(Core::System& system, u32 immediate) {
2652 } 2655 }
2653 2656
2654 kernel.ExitSVCProfile(); 2657 kernel.ExitSVCProfile();
2658
2659 if (!thread->IsContinuousOnSVC()) {
2660 auto* host_context = thread->GetHostContext().get();
2661 host_context->Rewind();
2662 }
2663
2655 system.EnterDynarmicProfile(); 2664 system.EnterDynarmicProfile();
2656} 2665}
2657 2666
diff --git a/src/core/hle/kernel/synchronization_object.h b/src/core/hle/kernel/synchronization_object.h
index f89b24204..7408ed51f 100644
--- a/src/core/hle/kernel/synchronization_object.h
+++ b/src/core/hle/kernel/synchronization_object.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
7#include <memory> 8#include <memory>
8#include <vector> 9#include <vector>
9 10
@@ -56,7 +57,7 @@ public:
56 void ClearWaitingThreads(); 57 void ClearWaitingThreads();
57 58
58protected: 59protected:
59 bool is_signaled{}; // Tells if this sync object is signalled; 60 std::atomic_bool is_signaled{}; // Tells if this sync object is signaled
60 61
61private: 62private:
62 /// Threads waiting for this object to become available 63 /// Threads waiting for this object to become available
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index da0cb26b6..7d1eb2c6e 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -12,7 +12,6 @@
12#include "common/fiber.h" 12#include "common/fiber.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/thread_queue_list.h" 14#include "common/thread_queue_list.h"
15#include "core/arm/arm_interface.h"
16#include "core/core.h" 15#include "core/core.h"
17#include "core/cpu_manager.h" 16#include "core/cpu_manager.h"
18#include "core/hardware_properties.h" 17#include "core/hardware_properties.h"
@@ -62,7 +61,6 @@ void Thread::Stop() {
62 // Mark the TLS slot in the thread's page as free. 61 // Mark the TLS slot in the thread's page as free.
63 owner_process->FreeTLSRegion(tls_address); 62 owner_process->FreeTLSRegion(tls_address);
64 } 63 }
65 arm_interface.reset();
66 has_exited = true; 64 has_exited = true;
67 } 65 }
68 global_handle = 0; 66 global_handle = 0;
@@ -90,10 +88,6 @@ void Thread::ResumeFromWait() {
90 // before actually resuming. We can ignore subsequent wakeups if the thread status has 88 // before actually resuming. We can ignore subsequent wakeups if the thread status has
91 // already been set to ThreadStatus::Ready. 89 // already been set to ThreadStatus::Ready.
92 return; 90 return;
93
94 case ThreadStatus::Running:
95 DEBUG_ASSERT_MSG(false, "Thread with object id {} has already resumed.", GetObjectId());
96 return;
97 case ThreadStatus::Dead: 91 case ThreadStatus::Dead:
98 // This should never happen, as threads must complete before being stopped. 92 // This should never happen, as threads must complete before being stopped.
99 DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.", 93 DEBUG_ASSERT_MSG(false, "Thread with object id {} cannot be resumed because it's DEAD.",
@@ -217,22 +211,9 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(Core::System& system, ThreadTy
217 thread->tls_address = 0; 211 thread->tls_address = 0;
218 } 212 }
219 213
220 thread->arm_interface.reset(); 214 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
215 // to initialize the context
221 if ((type_flags & THREADTYPE_HLE) == 0) { 216 if ((type_flags & THREADTYPE_HLE) == 0) {
222#ifdef ARCHITECTURE_x86_64
223 if (owner_process && !owner_process->Is64BitProcess()) {
224 thread->arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
225 system, kernel.Interrupts(), kernel.IsMulticore(), kernel.GetExclusiveMonitor(),
226 processor_id);
227 } else {
228 thread->arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
229 system, kernel.Interrupts(), kernel.IsMulticore(), kernel.GetExclusiveMonitor(),
230 processor_id);
231 }
232#else
233#error Platform not supported yet.
234#endif
235
236 ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top), 217 ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top),
237 static_cast<u32>(entry_point), static_cast<u32>(arg)); 218 static_cast<u32>(entry_point), static_cast<u32>(arg));
238 ResetThreadContext64(thread->context_64, stack_top, entry_point, arg); 219 ResetThreadContext64(thread->context_64, stack_top, entry_point, arg);
@@ -268,14 +249,6 @@ VAddr Thread::GetCommandBufferAddress() const {
268 return GetTLSAddress() + command_header_offset; 249 return GetTLSAddress() + command_header_offset;
269} 250}
270 251
271Core::ARM_Interface& Thread::ArmInterface() {
272 return *arm_interface;
273}
274
275const Core::ARM_Interface& Thread::ArmInterface() const {
276 return *arm_interface;
277}
278
279void Thread::SetStatus(ThreadStatus new_status) { 252void Thread::SetStatus(ThreadStatus new_status) {
280 if (new_status == status) { 253 if (new_status == status) {
281 return; 254 return;
@@ -283,7 +256,6 @@ void Thread::SetStatus(ThreadStatus new_status) {
283 256
284 switch (new_status) { 257 switch (new_status) {
285 case ThreadStatus::Ready: 258 case ThreadStatus::Ready:
286 case ThreadStatus::Running:
287 SetSchedulingStatus(ThreadSchedStatus::Runnable); 259 SetSchedulingStatus(ThreadSchedStatus::Runnable);
288 break; 260 break;
289 case ThreadStatus::Dormant: 261 case ThreadStatus::Dormant:
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 8daf79fac..a75071e9b 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -72,7 +72,6 @@ enum ThreadProcessorId : s32 {
72}; 72};
73 73
74enum class ThreadStatus { 74enum class ThreadStatus {
75 Running, ///< Currently running
76 Ready, ///< Ready to run 75 Ready, ///< Ready to run
77 Paused, ///< Paused by SetThreadActivity or debug 76 Paused, ///< Paused by SetThreadActivity or debug
78 WaitHLEEvent, ///< Waiting for hle event to finish 77 WaitHLEEvent, ///< Waiting for hle event to finish
@@ -248,10 +247,6 @@ public:
248 247
249 void SetSynchronizationResults(SynchronizationObject* object, ResultCode result); 248 void SetSynchronizationResults(SynchronizationObject* object, ResultCode result);
250 249
251 Core::ARM_Interface& ArmInterface();
252
253 const Core::ARM_Interface& ArmInterface() const;
254
255 SynchronizationObject* GetSignalingObject() const { 250 SynchronizationObject* GetSignalingObject() const {
256 return signaling_object; 251 return signaling_object;
257 } 252 }
@@ -586,7 +581,6 @@ private:
586 Common::SpinLock context_guard{}; 581 Common::SpinLock context_guard{};
587 ThreadContext32 context_32{}; 582 ThreadContext32 context_32{};
588 ThreadContext64 context_64{}; 583 ThreadContext64 context_64{};
589 std::unique_ptr<Core::ARM_Interface> arm_interface{};
590 std::shared_ptr<Common::Fiber> host_context{}; 584 std::shared_ptr<Common::Fiber> host_context{};
591 585
592 u64 thread_id = 0; 586 u64 thread_id = 0;
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp
index 95f2446c9..caf329bfb 100644
--- a/src/core/hle/kernel/time_manager.cpp
+++ b/src/core/hle/kernel/time_manager.cpp
@@ -24,11 +24,15 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} {
24 return; 24 return;
25 } 25 }
26 auto thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); 26 auto thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
27 thread->OnWakeUp(); 27 if (thread) {
28 // Thread can be null if process has exited
29 thread->OnWakeUp();
30 }
28 }); 31 });
29} 32}
30 33
31void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds) { 34void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds) {
35 std::lock_guard lock{mutex};
32 event_handle = timetask->GetGlobalHandle(); 36 event_handle = timetask->GetGlobalHandle();
33 if (nanoseconds > 0) { 37 if (nanoseconds > 0) {
34 ASSERT(timetask); 38 ASSERT(timetask);
@@ -43,6 +47,7 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64
43} 47}
44 48
45void TimeManager::UnscheduleTimeEvent(Handle event_handle) { 49void TimeManager::UnscheduleTimeEvent(Handle event_handle) {
50 std::lock_guard lock{mutex};
46 if (event_handle == InvalidHandle) { 51 if (event_handle == InvalidHandle) {
47 return; 52 return;
48 } 53 }
@@ -51,7 +56,7 @@ void TimeManager::UnscheduleTimeEvent(Handle event_handle) {
51} 56}
52 57
53void TimeManager::CancelTimeEvent(Thread* time_task) { 58void TimeManager::CancelTimeEvent(Thread* time_task) {
54 Handle event_handle = time_task->GetGlobalHandle(); 59 const Handle event_handle = time_task->GetGlobalHandle();
55 UnscheduleTimeEvent(event_handle); 60 UnscheduleTimeEvent(event_handle);
56} 61}
57 62
diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h
index 307a18765..f39df39a0 100644
--- a/src/core/hle/kernel/time_manager.h
+++ b/src/core/hle/kernel/time_manager.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <mutex>
8#include <unordered_map> 9#include <unordered_map>
9 10
10#include "core/hle/kernel/object.h" 11#include "core/hle/kernel/object.h"
@@ -42,6 +43,7 @@ private:
42 Core::System& system; 43 Core::System& system;
43 std::shared_ptr<Core::Timing::EventType> time_manager_event_type; 44 std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
44 std::unordered_map<Handle, bool> cancelled_events; 45 std::unordered_map<Handle, bool> cancelled_events;
46 std::mutex mutex;
45}; 47};
46 48
47} // namespace Kernel 49} // namespace Kernel