mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-28 11:35:11 +00:00
Fix license headers
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user