Fix license headers

This commit is contained in:
lizzie
2026-09-21 01:26:16 +00:00
parent 6acf3c496a
commit 4bb5ab4d83
7 changed files with 216 additions and 179 deletions
+1
View File
@@ -459,6 +459,7 @@ struct System::Impl {
fs_controller.Reset(); fs_controller.Reset();
cheat_engine.reset(); cheat_engine.reset();
core_timing.ClearPendingEvents(); core_timing.ClearPendingEvents();
core_timing.Reset();
app_loader.reset(); app_loader.reset();
audio_core.reset(); audio_core.reset();
gpu_core.reset(); gpu_core.reset();
+2 -2
View File
@@ -304,10 +304,10 @@ std::optional<s64> CoreTiming::Advance() {
void CoreTiming::Reset() { void CoreTiming::Reset() {
paused = true; paused = true;
pause_event.Set();
event.Set();
if (timer_thread.joinable()) { if (timer_thread.joinable()) {
timer_thread.request_stop(); timer_thread.request_stop();
pause_event.Set();
event.Set();
timer_thread.join(); timer_thread.join();
} }
has_started = false; has_started = false;
+35 -5
View File
@@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
#include "common/assert.h" #include "common/assert.h"
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
@@ -26,7 +27,15 @@ void KWorkerTask::DoWorkerTask(KernelCore& kernel) {
} }
} }
KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "KWorkerTaskManager") {} KWorkerTaskManager::KWorkerTaskManager() {}
KWorkerTaskManager::~KWorkerTaskManager() {
if (m_waiting_thread.joinable()) {
m_waiting_thread.request_stop();
m_task_cv.notify_one();
m_waiting_thread.join();
}
}
void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) { void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) {
ASSERT(type <= WorkerType::Count); ASSERT(type <= WorkerType::Count);
@@ -35,10 +44,31 @@ void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTas
void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) { void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) {
KScopedSchedulerLock sl(kernel); KScopedSchedulerLock sl(kernel);
m_waiting_thread.QueueWork([&kernel, task]() {
// Do the task. // spawn thread on demand
task->DoWorkerTask(kernel); if (!m_waiting_thread.joinable()) {
}); LOG_INFO(Kernel, "spawning KWorkerTaskManager thread");
m_waiting_thread = std::jthread([&kernel, this](std::stop_token stop_token) {
while (!stop_token.stop_requested()) {
KWorkerTask* t;
{
std::unique_lock lk{m_task_mutex};
m_task_cv.wait(lk);
if (stop_token.stop_requested())
break;
t = m_task_queue.back();
m_task_queue.pop_back();
}
t->DoWorkerTask(kernel);
}
});
}
{
std::scoped_lock lk{m_task_mutex};
m_task_queue.emplace_back(task);
}
m_task_cv.notify_one();
} }
} // namespace Kernel } // namespace Kernel
+10 -3
View File
@@ -1,8 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include <condition_variable>
#include <thread>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/thread_worker.h" #include "common/thread_worker.h"
@@ -19,14 +24,16 @@ public:
}; };
KWorkerTaskManager(); KWorkerTaskManager();
~KWorkerTaskManager();
static void AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task); static void AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task);
private: private:
void AddTask(KernelCore& kernel, KWorkerTask* task); void AddTask(KernelCore& kernel, KWorkerTask* task);
std::jthread m_waiting_thread;
private: std::mutex m_task_mutex;
Common::ThreadWorker m_waiting_thread; std::condition_variable m_task_cv;
std::vector<KWorkerTask*> m_task_queue;
}; };
} // namespace Kernel } // namespace Kernel
+150 -149
View File
@@ -20,15 +20,17 @@
namespace Service::Glue::Time { namespace Service::Glue::Time {
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, FileTimestampWorker& file_timestamp_worker)
FileTimestampWorker& file_timestamp_worker) : m_system{system}
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent( , m_ctx{m_system, "Glue:TimeWorker"}
"Glue:TimeWorker:Event")}, , m_event{m_ctx.CreateEvent("Glue:TimeWorker:Event")}
m_steady_clock_resource{steady_clock_resource}, , m_steady_clock_resource{steady_clock_resource}
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( , m_file_timestamp_worker{file_timestamp_worker}
"Glue:TimeWorker:SteadyClockTimerEvent")}, , m_timer_steady_clock{m_ctx.CreateEvent("Glue:TimeWorker:SteadyClockTimerEvent")}
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")}, , m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")}
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { , m_alarm_worker{m_system, m_steady_clock_resource}
, m_pm_state_change_handler{m_alarm_worker}
{
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent( m_timer_steady_clock_timing_event = Core::Timing::CreateEvent(
"Time::SteadyClockEvent", "Time::SteadyClockEvent",
[this](s64 time, [this](s64 time,
@@ -50,11 +52,12 @@ TimeWorker::~TimeWorker() {
m_local_clock_event->Signal(m_system.Kernel()); m_local_clock_event->Signal(m_system.Kernel());
m_network_clock_event->Signal(m_system.Kernel()); m_network_clock_event->Signal(m_system.Kernel());
m_ephemeral_clock_event->Signal(m_system.Kernel()); m_ephemeral_clock_event->Signal(m_system.Kernel());
std::this_thread::sleep_for(std::chrono::milliseconds(16));
m_thread.request_stop(); if (m_thread.joinable()) {
m_event->Signal(m_system.Kernel()); m_thread.request_stop();
m_thread.join(); m_event->Signal(m_system.Kernel());
m_thread.join();
}
m_ctx.CloseEvent(m_event); m_ctx.CloseEvent(m_event);
m_system.CoreTiming().UnscheduleEvent(m_timer_steady_clock_timing_event); m_system.CoreTiming().UnscheduleEvent(m_timer_steady_clock_timing_event);
@@ -122,166 +125,164 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
} }
void TimeWorker::StartThread() { void TimeWorker::StartThread() {
m_thread = std::jthread(std::bind_front(&TimeWorker::ThreadFunc, this)); m_thread = m_system.Kernel().RunOnHostCoreThread("TimeWorker", [this]() {
} auto const stop_token = m_thread.get_stop_token();
Common::SetCurrentThreadPriority(Common::ThreadPriority::Low);
while (!stop_token.stop_requested()) {
enum class EventType : s32 {
Exit = 0,
PowerStateChange = 1,
SignalAlarms = 2,
UpdateLocalSystemClock = 3,
UpdateNetworkSystemClock = 4,
UpdateEphemeralSystemClock = 5,
UpdateSteadyClock = 6,
UpdateFileTimestamp = 7,
AutoCorrect = 8,
};
void TimeWorker::ThreadFunc(std::stop_token stop_token) { s32 index{};
Common::SetCurrentThreadName("TimeWorker");
Common::SetCurrentThreadPriority(Common::ThreadPriority::Low);
while (!stop_token.stop_requested()) { if (m_pm_state_change_handler.m_priority != 0) {
enum class EventType : s32 { // TODO: gIPmModuleService::GetEvent() 1
Exit = 0, index = WaitAny(
PowerStateChange = 1, m_system.Kernel(),
SignalAlarms = 2, &m_event->GetReadableEvent(), // 0
UpdateLocalSystemClock = 3, &m_alarm_worker.GetEvent() // 1
UpdateNetworkSystemClock = 4, );
UpdateEphemeralSystemClock = 5, } else {
UpdateSteadyClock = 6, // TODO: gIPmModuleService::GetEvent() 1
UpdateFileTimestamp = 7, index = WaitAny(
AutoCorrect = 8, m_system.Kernel(),
}; &m_event->GetReadableEvent(), // 0
&m_alarm_worker.GetEvent(), // 1
s32 index{}; &m_alarm_worker.GetTimerEvent().GetReadableEvent(), // 2
m_local_clock_event, // 3
if (m_pm_state_change_handler.m_priority != 0) { m_network_clock_event, // 4
// TODO: gIPmModuleService::GetEvent() 1 m_ephemeral_clock_event, // 5
index = WaitAny(m_system.Kernel(), &m_timer_steady_clock->GetReadableEvent(), // 6
&m_event->GetReadableEvent(), // 0 &m_timer_file_system->GetReadableEvent(), // 7
&m_alarm_worker.GetEvent() // 1 m_standard_user_auto_correct_clock_event // 8
); );
} else {
// TODO: gIPmModuleService::GetEvent() 1
index = WaitAny(m_system.Kernel(),
&m_event->GetReadableEvent(), // 0
&m_alarm_worker.GetEvent(), // 1
&m_alarm_worker.GetTimerEvent().GetReadableEvent(), // 2
m_local_clock_event, // 3
m_network_clock_event, // 4
m_ephemeral_clock_event, // 5
&m_timer_steady_clock->GetReadableEvent(), // 6
&m_timer_file_system->GetReadableEvent(), // 7
m_standard_user_auto_correct_clock_event // 8
);
}
switch (static_cast<EventType>(index)) {
case EventType::Exit:
return;
case EventType::PowerStateChange:
m_alarm_worker.GetEvent().Clear(m_system.Kernel());
if (m_pm_state_change_handler.m_priority <= 1) {
m_alarm_worker.OnPowerStateChanged();
} }
break;
case EventType::SignalAlarms: if (stop_token.stop_requested())
m_alarm_worker.GetTimerEvent().Clear(m_system.Kernel()); break;
m_time_m->CheckAndSignalAlarms();
break;
case EventType::UpdateLocalSystemClock: { switch (EventType(index)) {
m_local_clock_event->Clear(m_system.Kernel()); case EventType::Exit:
return;
Service::PSC::Time::SystemClockContext context{}; case EventType::PowerStateChange:
R_ASSERT(m_local_clock->GetSystemClockContext(&context)); m_alarm_worker.GetEvent().Clear(m_system.Kernel());
if (m_pm_state_change_handler.m_priority <= 1) {
m_alarm_worker.OnPowerStateChanged();
}
break;
m_set_sys->SetUserSystemClockContext(context); case EventType::SignalAlarms:
m_file_timestamp_worker.SetFilesystemPosixTime(); m_alarm_worker.GetTimerEvent().Clear(m_system.Kernel());
break; m_time_m->CheckAndSignalAlarms();
} break;
case EventType::UpdateNetworkSystemClock: { case EventType::UpdateLocalSystemClock: {
m_network_clock_event->Clear(m_system.Kernel()); m_local_clock_event->Clear(m_system.Kernel());
Service::PSC::Time::SystemClockContext context{}; Service::PSC::Time::SystemClockContext context{};
R_ASSERT(m_network_clock->GetSystemClockContext(&context)); R_ASSERT(m_local_clock->GetSystemClockContext(&context));
m_set_sys->SetNetworkSystemClockContext(context); m_set_sys->SetUserSystemClockContext(context);
m_file_timestamp_worker.SetFilesystemPosixTime();
s64 time{};
if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) {
break; break;
} }
[[maybe_unused]] auto offset_before{ case EventType::UpdateNetworkSystemClock: {
m_ig_report_network_clock_context_set ? m_report_network_clock_context.offset : 0}; m_network_clock_event->Clear(m_system.Kernel());
// TODO system report "standard_netclock_operation"
// "clock_time" = time
// "context_offset_before" = offset_before
// "context_offset_after" = context.offset
m_report_network_clock_context = context;
if (!m_ig_report_network_clock_context_set) {
m_ig_report_network_clock_context_set = true;
}
m_file_timestamp_worker.SetFilesystemPosixTime(); Service::PSC::Time::SystemClockContext context{};
break; R_ASSERT(m_network_clock->GetSystemClockContext(&context));
}
case EventType::UpdateEphemeralSystemClock: { m_set_sys->SetNetworkSystemClockContext(context);
m_ephemeral_clock_event->Clear(m_system.Kernel());
Service::PSC::Time::SystemClockContext context{}; s64 time{};
auto res = m_ephemeral_clock->GetSystemClockContext(&context); if (m_network_clock->GetCurrentTime(&time) != ResultSuccess) {
if (res != ResultSuccess) { break;
}
[[maybe_unused]] auto offset_before{
m_ig_report_network_clock_context_set ? m_report_network_clock_context.offset : 0};
// TODO system report "standard_netclock_operation"
// "clock_time" = time
// "context_offset_before" = offset_before
// "context_offset_after" = context.offset
m_report_network_clock_context = context;
if (!m_ig_report_network_clock_context_set) {
m_ig_report_network_clock_context_set = true;
}
m_file_timestamp_worker.SetFilesystemPosixTime();
break; break;
} }
s64 time{}; case EventType::UpdateEphemeralSystemClock: {
res = m_ephemeral_clock->GetCurrentTime(&time); m_ephemeral_clock_event->Clear(m_system.Kernel());
if (res != ResultSuccess) {
Service::PSC::Time::SystemClockContext context{};
auto res = m_ephemeral_clock->GetSystemClockContext(&context);
if (res != ResultSuccess) {
break;
}
s64 time{};
res = m_ephemeral_clock->GetCurrentTime(&time);
if (res != ResultSuccess) {
break;
}
[[maybe_unused]] auto offset_before{m_ig_report_ephemeral_clock_context_set
? m_report_ephemeral_clock_context.offset
: 0};
// TODO system report "ephemeral_netclock_operation"
// "clock_time" = time
// "context_offset_before" = offset_before
// "context_offset_after" = context.offset
m_report_ephemeral_clock_context = context;
if (!m_ig_report_ephemeral_clock_context_set) {
m_ig_report_ephemeral_clock_context_set = true;
}
break; break;
} }
[[maybe_unused]] auto offset_before{m_ig_report_ephemeral_clock_context_set case EventType::UpdateSteadyClock:
? m_report_ephemeral_clock_context.offset m_timer_steady_clock->Clear(m_system.Kernel());
: 0};
// TODO system report "ephemeral_netclock_operation" m_steady_clock_resource.UpdateTime();
// "clock_time" = time m_time_m->SetStandardSteadyClockBaseTime(m_steady_clock_resource.GetTime());
// "context_offset_before" = offset_before break;
// "context_offset_after" = context.offset
m_report_ephemeral_clock_context = context; case EventType::UpdateFileTimestamp:
if (!m_ig_report_ephemeral_clock_context_set) { m_timer_file_system->Clear(m_system.Kernel());
m_ig_report_ephemeral_clock_context_set = true; m_file_timestamp_worker.SetFilesystemPosixTime();
break;
case EventType::AutoCorrect: {
m_standard_user_auto_correct_clock_event->Clear(m_system.Kernel());
bool automatic_correction{};
R_ASSERT(m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled(&automatic_correction));
Service::PSC::Time::SteadyClockTimePoint time_point{};
R_ASSERT(m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point));
m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
m_set_sys->SetUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
break;
}
default:
UNREACHABLE();
} }
break;
} }
});
case EventType::UpdateSteadyClock:
m_timer_steady_clock->Clear(m_system.Kernel());
m_steady_clock_resource.UpdateTime();
m_time_m->SetStandardSteadyClockBaseTime(m_steady_clock_resource.GetTime());
break;
case EventType::UpdateFileTimestamp:
m_timer_file_system->Clear(m_system.Kernel());
m_file_timestamp_worker.SetFilesystemPosixTime();
break;
case EventType::AutoCorrect: {
m_standard_user_auto_correct_clock_event->Clear(m_system.Kernel());
bool automatic_correction{};
R_ASSERT(m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled(
&automatic_correction));
Service::PSC::Time::SteadyClockTimePoint time_point{};
R_ASSERT(
m_time_sm->GetStandardUserSystemClockAutomaticCorrectionUpdatedTime(&time_point));
m_set_sys->SetUserSystemClockAutomaticCorrectionEnabled(automatic_correction);
m_set_sys->SetUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
break;
}
default:
UNREACHABLE();
}
}
} }
} // namespace Service::Glue::Time } // namespace Service::Glue::Time
+3 -1
View File
@@ -94,6 +94,9 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
{"ldn", &LDN::LoopProcess}, {"ldn", &LDN::LoopProcess},
{"nvservices", &Nvidia::LoopProcess}, {"nvservices", &Nvidia::LoopProcess},
{"bsdsocket", &Sockets::LoopProcess}, {"bsdsocket", &Sockets::LoopProcess},
// TODO: glue is only required here as otherwise the dummythread doesn't close
// TODO: rework sched so this isn't needed
{"glue", &Glue::LoopProcess},
}) })
kernel.RunOnHostCoreProcess(std::string(e.first), [&system, f = e.second] { f(system); }).detach(); kernel.RunOnHostCoreProcess(std::string(e.first), [&system, f = e.second] { f(system); }).detach();
kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach(); kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach();
@@ -117,7 +120,6 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
{"friends", &Friend::LoopProcess}, {"friends", &Friend::LoopProcess},
{"settings", &Set::LoopProcess}, {"settings", &Set::LoopProcess},
{"psc", &PSC::LoopProcess}, {"psc", &PSC::LoopProcess},
{"glue", &Glue::LoopProcess},
{"grc", &GRC::LoopProcess}, {"grc", &GRC::LoopProcess},
{"hid", &HID::LoopProcess}, {"hid", &HID::LoopProcess},
{"jit", &JIT::LoopProcess}, {"jit", &JIT::LoopProcess},
+15 -19
View File
@@ -11,6 +11,7 @@
#include "common/thread.h" #include "common/thread.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/vi/conductor.h" #include "core/hle/service/vi/conductor.h"
#include "core/hle/service/vi/container.h" #include "core/hle/service/vi/container.h"
#include "core/hle/service/vi/display_list.h" #include "core/hle/service/vi/display_list.h"
@@ -38,7 +39,18 @@ Conductor::Conductor(Core::System& system, Container& container, DisplayList& di
}); });
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); }); m_thread = system.Kernel().RunOnHostCoreThread("VSyncThread", [this]() {
auto const stop_token = m_thread.get_stop_token();
Common::SetCurrentThreadPriority(Common::ThreadPriority::VeryHigh);
Common::SetCurrentThreadToPerformanceCores();
while (!stop_token.stop_requested()) {
m_signal.Wait();
if (stop_token.stop_requested() || m_system.IsShuttingDown()) {
break;
}
this->ProcessVsync();
}
});
} else { } else {
m_event = Core::Timing::CreateEvent( m_event = Core::Timing::CreateEvent(
"ScreenComposition", "ScreenComposition",
@@ -54,10 +66,10 @@ Conductor::Conductor(Core::System& system, Container& container, DisplayList& di
Conductor::~Conductor() { Conductor::~Conductor() {
m_system.CoreTiming().UnscheduleEvent(m_event); m_system.CoreTiming().UnscheduleEvent(m_event);
if (m_thread.joinable()) {
if (m_system.IsMulticore()) {
m_thread.request_stop(); m_thread.request_stop();
m_signal.Set(); m_signal.Set();
m_thread.join();
} }
} }
@@ -83,22 +95,6 @@ void Conductor::ProcessVsync() {
} }
} }
void Conductor::VsyncThread(std::stop_token token) {
Common::SetCurrentThreadName("VSyncThread");
Common::SetCurrentThreadPriority(Common::ThreadPriority::VeryHigh);
Common::SetCurrentThreadToPerformanceCores();
while (!token.stop_requested()) {
m_signal.Wait();
if (m_system.IsShuttingDown()) {
return;
}
this->ProcessVsync();
}
}
s64 Conductor::GetNextTicks() const { s64 Conductor::GetNextTicks() const {
const auto& settings = Settings::values; const auto& settings = Settings::values;
auto speed_scale = 1.f; auto speed_scale = 1.f;