diff options
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 799e5e0d8..f94ac150d 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -12,12 +12,15 @@ | |||
| 12 | 12 | ||
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 15 | #include "core/core_timing_util.h" | ||
| 15 | #include "core/hle/kernel/address_arbiter.h" | 16 | #include "core/hle/kernel/address_arbiter.h" |
| 16 | #include "core/hle/kernel/client_port.h" | 17 | #include "core/hle/kernel/client_port.h" |
| 18 | #include "core/hle/kernel/errors.h" | ||
| 17 | #include "core/hle/kernel/handle_table.h" | 19 | #include "core/hle/kernel/handle_table.h" |
| 18 | #include "core/hle/kernel/kernel.h" | 20 | #include "core/hle/kernel/kernel.h" |
| 19 | #include "core/hle/kernel/process.h" | 21 | #include "core/hle/kernel/process.h" |
| 20 | #include "core/hle/kernel/resource_limit.h" | 22 | #include "core/hle/kernel/resource_limit.h" |
| 23 | #include "core/hle/kernel/scheduler.h" | ||
| 21 | #include "core/hle/kernel/thread.h" | 24 | #include "core/hle/kernel/thread.h" |
| 22 | #include "core/hle/lock.h" | 25 | #include "core/hle/lock.h" |
| 23 | #include "core/hle/result.h" | 26 | #include "core/hle/result.h" |
| @@ -58,12 +61,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 58 | if (thread->HasWakeupCallback()) { | 61 | if (thread->HasWakeupCallback()) { |
| 59 | resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0); | 62 | resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0); |
| 60 | } | 63 | } |
| 61 | } | 64 | } else if (thread->GetStatus() == ThreadStatus::WaitMutex || |
| 62 | 65 | thread->GetStatus() == ThreadStatus::WaitCondVar) { | |
| 63 | if (thread->GetMutexWaitAddress() != 0 || thread->GetCondVarWaitAddress() != 0 || | ||
| 64 | thread->GetWaitHandle() != 0) { | ||
| 65 | ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex || | ||
| 66 | thread->GetStatus() == ThreadStatus::WaitCondVar); | ||
| 67 | thread->SetMutexWaitAddress(0); | 66 | thread->SetMutexWaitAddress(0); |
| 68 | thread->SetCondVarWaitAddress(0); | 67 | thread->SetCondVarWaitAddress(0); |
| 69 | thread->SetWaitHandle(0); | 68 | thread->SetWaitHandle(0); |
| @@ -83,18 +82,23 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | if (resume) { | 84 | if (resume) { |
| 85 | if (thread->GetStatus() == ThreadStatus::WaitCondVar || | ||
| 86 | thread->GetStatus() == ThreadStatus::WaitArb) { | ||
| 87 | thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); | ||
| 88 | } | ||
| 86 | thread->ResumeFromWait(); | 89 | thread->ResumeFromWait(); |
| 87 | } | 90 | } |
| 88 | } | 91 | } |
| 89 | 92 | ||
| 90 | struct KernelCore::Impl { | 93 | struct KernelCore::Impl { |
| 91 | explicit Impl(Core::System& system) : system{system} {} | 94 | explicit Impl(Core::System& system) : system{system}, global_scheduler{system} {} |
| 92 | 95 | ||
| 93 | void Initialize(KernelCore& kernel) { | 96 | void Initialize(KernelCore& kernel) { |
| 94 | Shutdown(); | 97 | Shutdown(); |
| 95 | 98 | ||
| 96 | InitializeSystemResourceLimit(kernel); | 99 | InitializeSystemResourceLimit(kernel); |
| 97 | InitializeThreads(); | 100 | InitializeThreads(); |
| 101 | InitializePreemption(); | ||
| 98 | } | 102 | } |
| 99 | 103 | ||
| 100 | void Shutdown() { | 104 | void Shutdown() { |
| @@ -110,6 +114,9 @@ struct KernelCore::Impl { | |||
| 110 | 114 | ||
| 111 | thread_wakeup_callback_handle_table.Clear(); | 115 | thread_wakeup_callback_handle_table.Clear(); |
| 112 | thread_wakeup_event_type = nullptr; | 116 | thread_wakeup_event_type = nullptr; |
| 117 | preemption_event = nullptr; | ||
| 118 | |||
| 119 | global_scheduler.Shutdown(); | ||
| 113 | 120 | ||
| 114 | named_ports.clear(); | 121 | named_ports.clear(); |
| 115 | } | 122 | } |
| @@ -132,6 +139,18 @@ struct KernelCore::Impl { | |||
| 132 | system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); | 139 | system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); |
| 133 | } | 140 | } |
| 134 | 141 | ||
| 142 | void InitializePreemption() { | ||
| 143 | preemption_event = system.CoreTiming().RegisterEvent( | ||
| 144 | "PreemptionCallback", [this](u64 userdata, s64 cycles_late) { | ||
| 145 | global_scheduler.PreemptThreads(); | ||
| 146 | s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); | ||
| 147 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | ||
| 148 | }); | ||
| 149 | |||
| 150 | s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); | ||
| 151 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | ||
| 152 | } | ||
| 153 | |||
| 135 | std::atomic<u32> next_object_id{0}; | 154 | std::atomic<u32> next_object_id{0}; |
| 136 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; | 155 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; |
| 137 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; | 156 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; |
| @@ -140,10 +159,12 @@ struct KernelCore::Impl { | |||
| 140 | // Lists all processes that exist in the current session. | 159 | // Lists all processes that exist in the current session. |
| 141 | std::vector<SharedPtr<Process>> process_list; | 160 | std::vector<SharedPtr<Process>> process_list; |
| 142 | Process* current_process = nullptr; | 161 | Process* current_process = nullptr; |
| 162 | Kernel::GlobalScheduler global_scheduler; | ||
| 143 | 163 | ||
| 144 | SharedPtr<ResourceLimit> system_resource_limit; | 164 | SharedPtr<ResourceLimit> system_resource_limit; |
| 145 | 165 | ||
| 146 | Core::Timing::EventType* thread_wakeup_event_type = nullptr; | 166 | Core::Timing::EventType* thread_wakeup_event_type = nullptr; |
| 167 | Core::Timing::EventType* preemption_event = nullptr; | ||
| 147 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, | 168 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, |
| 148 | // allowing us to simply use a pool index or similar. | 169 | // allowing us to simply use a pool index or similar. |
| 149 | Kernel::HandleTable thread_wakeup_callback_handle_table; | 170 | Kernel::HandleTable thread_wakeup_callback_handle_table; |
| @@ -203,6 +224,14 @@ const std::vector<SharedPtr<Process>>& KernelCore::GetProcessList() const { | |||
| 203 | return impl->process_list; | 224 | return impl->process_list; |
| 204 | } | 225 | } |
| 205 | 226 | ||
| 227 | Kernel::GlobalScheduler& KernelCore::GlobalScheduler() { | ||
| 228 | return impl->global_scheduler; | ||
| 229 | } | ||
| 230 | |||
| 231 | const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const { | ||
| 232 | return impl->global_scheduler; | ||
| 233 | } | ||
| 234 | |||
| 206 | void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) { | 235 | void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) { |
| 207 | impl->named_ports.emplace(std::move(name), std::move(port)); | 236 | impl->named_ports.emplace(std::move(name), std::move(port)); |
| 208 | } | 237 | } |