From 3aa0d462598beb2021308eee1d757d74fe33b312 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 23 Jun 2026 06:31:25 +0200 Subject: [PATCH] [video_core, hle] remove redundant parent references in system structs (#3908) reworked a bit to remove references of parent objects and instead pass as arguments to methods to prevent useless reloads Signed-off-by: lizzie Co-authored-by: maufeat Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3908 Reviewed-by: Maufeat Reviewed-by: crueter --- .gitignore | 1 - src/audio_core/audio_core.cpp | 8 +- src/audio_core/audio_core.h | 23 +- src/audio_core/audio_in_manager.cpp | 6 +- src/audio_core/audio_manager.cpp | 100 ++-- src/audio_core/audio_manager.h | 10 +- src/audio_core/audio_out_manager.cpp | 6 +- src/audio_core/device/device_session.cpp | 7 +- src/audio_core/in/audio_in_system.cpp | 6 +- src/audio_core/out/audio_out_system.cpp | 6 +- src/audio_core/renderer/system.cpp | 6 +- src/core/core.cpp | 16 +- src/core/core.h | 1 - src/core/cpu_manager.cpp | 85 ++-- src/core/cpu_manager.h | 59 +-- src/core/debugger/debugger.cpp | 41 +- src/core/debugger/gdbstub.cpp | 12 +- .../hle/kernel/global_scheduler_context.cpp | 15 +- .../hle/kernel/global_scheduler_context.h | 7 +- src/core/hle/kernel/init/init_slab_setup.cpp | 5 +- src/core/hle/kernel/k_address_arbiter.cpp | 52 ++- src/core/hle/kernel/k_address_arbiter.h | 6 +- src/core/hle/kernel/k_auto_object.cpp | 6 +- src/core/hle/kernel/k_auto_object.h | 81 ++-- src/core/hle/kernel/k_client_port.cpp | 64 +-- src/core/hle/kernel/k_client_port.h | 21 +- src/core/hle/kernel/k_client_session.cpp | 29 +- src/core/hle/kernel/k_client_session.h | 9 +- src/core/hle/kernel/k_code_memory.cpp | 30 +- src/core/hle/kernel/k_code_memory.h | 17 +- src/core/hle/kernel/k_condition_variable.cpp | 100 ++-- src/core/hle/kernel/k_condition_variable.h | 9 +- src/core/hle/kernel/k_debug.h | 5 +- .../hle/kernel/k_device_address_space.cpp | 9 +- src/core/hle/kernel/k_device_address_space.h | 11 +- src/core/hle/kernel/k_event.cpp | 35 +- src/core/hle/kernel/k_event.h | 13 +- src/core/hle/kernel/k_handle_table.cpp | 53 +-- src/core/hle/kernel/k_handle_table.h | 83 ++-- src/core/hle/kernel/k_hardware_timer_base.h | 5 +- src/core/hle/kernel/k_interrupt_manager.cpp | 11 +- .../hle/kernel/k_light_client_session.cpp | 15 +- src/core/hle/kernel/k_light_client_session.h | 9 +- .../hle/kernel/k_light_condition_variable.cpp | 19 +- src/core/hle/kernel/k_light_lock.cpp | 43 +- .../hle/kernel/k_light_server_session.cpp | 102 ++-- src/core/hle/kernel/k_light_server_session.h | 12 +- src/core/hle/kernel/k_light_session.cpp | 44 +- src/core/hle/kernel/k_light_session.h | 19 +- src/core/hle/kernel/k_object_name.cpp | 23 +- src/core/hle/kernel/k_object_name.h | 9 +- src/core/hle/kernel/k_page_group.cpp | 31 +- src/core/hle/kernel/k_page_group.h | 34 +- src/core/hle/kernel/k_page_table_base.cpp | 196 ++++---- src/core/hle/kernel/k_page_table_base.h | 31 +- src/core/hle/kernel/k_port.cpp | 40 +- src/core/hle/kernel/k_port.h | 17 +- src/core/hle/kernel/k_process.cpp | 370 +++++++-------- src/core/hle/kernel/k_process.h | 123 +++-- src/core/hle/kernel/k_readable_event.cpp | 36 +- src/core/hle/kernel/k_readable_event.h | 17 +- src/core/hle/kernel/k_resource_limit.cpp | 23 +- src/core/hle/kernel/k_resource_limit.h | 15 +- src/core/hle/kernel/k_scheduler.cpp | 152 +++--- src/core/hle/kernel/k_scheduler.h | 39 +- .../kernel/k_scoped_resource_reservation.h | 34 +- src/core/hle/kernel/k_server_port.cpp | 59 +-- src/core/hle/kernel/k_server_port.h | 21 +- src/core/hle/kernel/k_server_session.cpp | 140 +++--- src/core/hle/kernel/k_server_session.h | 25 +- src/core/hle/kernel/k_session.cpp | 33 +- src/core/hle/kernel/k_session.h | 19 +- src/core/hle/kernel/k_session_request.cpp | 7 +- src/core/hle/kernel/k_session_request.h | 36 +- src/core/hle/kernel/k_shared_memory.cpp | 25 +- src/core/hle/kernel/k_shared_memory.h | 9 +- .../hle/kernel/k_synchronization_object.cpp | 35 +- .../hle/kernel/k_synchronization_object.h | 18 +- src/core/hle/kernel/k_system_resource.cpp | 30 +- src/core/hle/kernel/k_system_resource.h | 11 +- src/core/hle/kernel/k_thread.cpp | 438 +++++++++--------- src/core/hle/kernel/k_thread.h | 141 +++--- src/core/hle/kernel/k_thread_queue.cpp | 16 +- src/core/hle/kernel/k_thread_queue.h | 16 +- src/core/hle/kernel/k_timer_task.h | 6 +- src/core/hle/kernel/k_trace.h | 5 + src/core/hle/kernel/k_transfer_memory.cpp | 30 +- src/core/hle/kernel/k_transfer_memory.h | 13 +- src/core/hle/kernel/k_worker_task.h | 6 +- src/core/hle/kernel/k_worker_task_manager.cpp | 13 +- src/core/hle/kernel/kernel.cpp | 95 ++-- src/core/hle/kernel/physical_core.cpp | 19 +- src/core/hle/kernel/physical_core.h | 9 +- src/core/hle/kernel/slab_helpers.h | 32 +- src/core/hle/kernel/svc/svc_activity.cpp | 11 +- src/core/hle/kernel/svc/svc_cache.cpp | 6 +- src/core/hle/kernel/svc/svc_code_memory.cpp | 40 +- .../kernel/svc/svc_device_address_space.cpp | 36 +- src/core/hle/kernel/svc/svc_event.cpp | 37 +- src/core/hle/kernel/svc/svc_exception.cpp | 4 +- src/core/hle/kernel/svc/svc_info.cpp | 20 +- src/core/hle/kernel/svc/svc_ipc.cpp | 45 +- src/core/hle/kernel/svc/svc_light_ipc.cpp | 15 +- src/core/hle/kernel/svc/svc_port.cpp | 56 +-- src/core/hle/kernel/svc/svc_process.cpp | 8 +- .../hle/kernel/svc/svc_process_memory.cpp | 12 +- src/core/hle/kernel/svc/svc_query_memory.cpp | 5 +- .../hle/kernel/svc/svc_resource_limit.cpp | 17 +- src/core/hle/kernel/svc/svc_session.cpp | 33 +- src/core/hle/kernel/svc/svc_shared_memory.cpp | 12 +- .../hle/kernel/svc/svc_synchronization.cpp | 52 +-- src/core/hle/kernel/svc/svc_thread.cpp | 52 +-- .../hle/kernel/svc/svc_transfer_memory.cpp | 20 +- src/core/hle/service/acc/async_context.cpp | 5 +- src/core/hle/service/am/applet.cpp | 6 +- .../hle/service/am/applet_data_broker.cpp | 14 +- src/core/hle/service/am/applet_data_broker.h | 7 +- src/core/hle/service/am/applet_manager.cpp | 31 +- src/core/hle/service/am/button_poller.cpp | 71 ++- src/core/hle/service/am/button_poller.h | 32 +- src/core/hle/service/am/event_observer.cpp | 42 +- src/core/hle/service/am/event_observer.h | 6 +- .../service/am/frontend/applet_general.cpp | 12 +- src/core/hle/service/am/frontend/applets.cpp | 12 +- .../hle/service/am/library_applet_storage.cpp | 38 +- .../hle/service/am/library_applet_storage.h | 11 +- src/core/hle/service/am/lifecycle_manager.cpp | 20 +- src/core/hle/service/am/lifecycle_manager.h | 31 +- src/core/hle/service/am/process_creation.cpp | 99 ++-- src/core/hle/service/am/process_creation.h | 12 +- .../am/service/application_accessor.cpp | 4 +- .../am/service/application_creator.cpp | 24 +- .../am/service/common_state_getter.cpp | 16 +- .../am/service/library_applet_accessor.cpp | 14 +- .../am/service/library_applet_creator.cpp | 43 +- .../service/library_applet_self_accessor.cpp | 8 +- .../hle/service/am/service/lock_accessor.cpp | 7 +- .../service/am/service/self_controller.cpp | 8 +- src/core/hle/service/am/window_system.cpp | 13 +- src/core/hle/service/audio/audio_device.cpp | 4 +- src/core/hle/service/audio/audio_in.cpp | 7 +- src/core/hle/service/audio/audio_out.cpp | 7 +- .../hle/service/audio/audio_out_manager.cpp | 6 +- .../hle/service/audio/audio_out_manager.h | 4 +- src/core/hle/service/audio/audio_renderer.cpp | 6 +- .../service/audio/audio_renderer_manager.cpp | 7 +- .../service/audio/audio_renderer_manager.h | 5 +- src/core/hle/service/bcat/backend/backend.cpp | 83 ++-- src/core/hle/service/bcat/backend/backend.h | 54 +-- src/core/hle/service/bcat/bcat_service.cpp | 10 +- src/core/hle/service/friend/friend.cpp | 2 +- .../hle/service/glue/time/alarm_worker.cpp | 9 +- src/core/hle/service/glue/time/time_zone.cpp | 2 +- src/core/hle/service/glue/time/worker.cpp | 31 +- src/core/hle/service/hid/hid_server.cpp | 77 +-- .../hle/service/hid/hid_system_server.cpp | 16 +- src/core/hle/service/hle_ipc.cpp | 11 +- src/core/hle/service/hle_ipc.h | 9 +- src/core/hle/service/ipc_helpers.h | 5 +- src/core/hle/service/jit/jit.cpp | 29 +- src/core/hle/service/jit/jit_code_memory.cpp | 20 +- src/core/hle/service/jit/jit_code_memory.h | 29 +- src/core/hle/service/kernel_helpers.cpp | 22 +- src/core/hle/service/kernel_helpers.h | 4 +- .../ldn/user_local_communication_service.cpp | 4 +- src/core/hle/service/nfc/common/device.cpp | 12 +- src/core/hle/service/nifm/nifm.cpp | 6 +- src/core/hle/service/nim/nim.cpp | 6 +- .../ns/application_manager_interface.cpp | 6 +- ...nly_application_control_data_interface.cpp | 2 +- .../service/nvdrv/devices/nvhost_as_gpu.cpp | 5 +- .../hle/service/nvdrv/devices/nvhost_as_gpu.h | 2 +- .../hle/service/nvdrv/devices/nvhost_ctrl.cpp | 4 +- .../nvnflinger/buffer_queue_producer.cpp | 8 +- .../hle/service/olsc/native_handle_holder.cpp | 2 +- src/core/hle/service/os/event.cpp | 23 +- src/core/hle/service/os/event.h | 12 +- src/core/hle/service/os/mutex.cpp | 15 +- src/core/hle/service/os/process.cpp | 27 +- src/core/hle/service/os/process.h | 9 +- src/core/hle/service/pm/pm.cpp | 33 +- src/core/hle/service/psc/ovln/receiver.cpp | 4 +- src/core/hle/service/psc/time/alarms.cpp | 41 +- src/core/hle/service/psc/time/alarms.h | 19 +- .../psc/time/clocks/context_writers.cpp | 13 +- .../service/psc/time/clocks/context_writers.h | 8 +- .../standard_user_system_clock_core.cpp | 5 +- .../psc/time/power_state_request_manager.cpp | 6 +- .../hle/service/psc/time/service_manager.cpp | 5 +- src/core/hle/service/psc/time/static.cpp | 5 +- src/core/hle/service/ptm/psm.cpp | 6 +- src/core/hle/service/ro/ro.cpp | 38 +- src/core/hle/service/server_manager.cpp | 65 +-- src/core/hle/service/sm/sm.cpp | 10 +- src/core/hle/service/sm/sm_controller.cpp | 5 +- src/core/hle/service/vi/conductor.cpp | 2 +- src/core/hle/service/vi/vsync_manager.cpp | 15 +- src/core/hle/service/vi/vsync_manager.h | 17 +- .../loader/deconstructed_rom_directory.cpp | 2 +- src/core/loader/kip.cpp | 4 +- src/core/loader/nro.cpp | 17 +- src/core/loader/nso.cpp | 2 +- src/core/memory/cheat_engine.cpp | 12 +- src/hid_core/hid_core.cpp | 29 +- src/hid_core/hid_core.h | 11 +- src/hid_core/hidbus/ringcon.cpp | 10 +- src/hid_core/resource_manager.cpp | 4 +- .../abstract_battery_handler.cpp | 6 +- .../abstracted_pad/abstract_battery_handler.h | 10 +- .../abstract_button_handler.cpp | 6 +- .../abstracted_pad/abstract_button_handler.h | 10 +- .../abstract_ir_sensor_handler.cpp | 14 +- .../abstract_ir_sensor_handler.h | 7 +- .../abstracted_pad/abstract_led_handler.cpp | 6 +- .../abstracted_pad/abstract_led_handler.h | 10 +- .../abstracted_pad/abstract_mcu_handler.cpp | 6 +- .../abstracted_pad/abstract_mcu_handler.h | 10 +- .../abstracted_pad/abstract_nfc_handler.cpp | 19 +- .../abstracted_pad/abstract_nfc_handler.h | 8 +- .../resources/abstracted_pad/abstract_pad.cpp | 17 +- .../resources/abstracted_pad/abstract_pad.h | 32 +- .../abstracted_pad/abstract_palma_handler.cpp | 6 +- .../abstracted_pad/abstract_palma_handler.h | 10 +- .../abstract_properties_handler.cpp | 6 +- .../abstract_properties_handler.h | 10 +- .../abstract_sixaxis_handler.cpp | 6 +- .../abstracted_pad/abstract_sixaxis_handler.h | 11 +- .../abstract_vibration_handler.cpp | 6 +- .../abstract_vibration_handler.h | 10 +- src/hid_core/resources/applet_resource.cpp | 11 +- src/hid_core/resources/npad/npad.cpp | 155 ++++--- src/hid_core/resources/npad/npad.h | 54 +-- src/hid_core/resources/npad/npad_resource.cpp | 26 +- src/hid_core/resources/npad/npad_resource.h | 40 +- src/hid_core/resources/palma/palma.cpp | 18 +- .../resources/shared_memory_holder.cpp | 16 +- src/hid_core/resources/shared_memory_holder.h | 9 +- .../touch_screen/touch_screen_resource.cpp | 2 +- src/input_common/drivers/udp_client.cpp | 76 +-- src/video_core/CMakeLists.txt | 2 +- src/video_core/cdma_pusher.cpp | 5 +- src/video_core/control/channel_state.cpp | 36 +- src/video_core/control/channel_state.h | 38 +- .../control/channel_state_cache.cpp | 10 +- .../control/channel_state_cache.inc | 5 +- src/video_core/control/scheduler.cpp | 11 +- src/video_core/control/scheduler.h | 6 +- src/video_core/dma_pusher.cpp | 46 +- src/video_core/dma_pusher.h | 55 +-- src/video_core/engines/engine_interface.h | 23 +- src/video_core/engines/fermi_2d.cpp | 14 +- src/video_core/engines/fermi_2d.h | 10 +- src/video_core/engines/kepler_compute.cpp | 18 +- src/video_core/engines/kepler_compute.h | 13 +- src/video_core/engines/kepler_memory.cpp | 17 +- src/video_core/engines/kepler_memory.h | 14 +- src/video_core/engines/maxwell_3d.cpp | 31 +- src/video_core/engines/maxwell_3d.h | 16 +- src/video_core/engines/maxwell_dma.cpp | 17 +- src/video_core/engines/maxwell_dma.h | 14 +- src/video_core/engines/nv01_timer.h | 13 +- src/video_core/engines/puller.cpp | 139 +++--- src/video_core/engines/puller.h | 46 +- src/video_core/gpu.cpp | 182 +++----- src/video_core/gpu_thread.cpp | 28 +- src/video_core/gpu_thread.h | 15 +- src/video_core/host1x/control.cpp | 14 +- src/video_core/host1x/control.h | 13 +- src/video_core/host1x/host1x.cpp | 8 +- src/video_core/host1x/host1x.h | 138 +++--- src/video_core/host1x/vic.cpp | 20 +- src/video_core/host1x/vic.h | 107 +++-- src/video_core/macro.cpp | 338 +++++++------- src/video_core/macro.h | 50 +- .../renderer_opengl/gl_state_tracker.cpp | 7 +- src/video_core/renderer_vulkan/blit_image.cpp | 4 +- .../renderer_vulkan/pipeline_statistics.cpp | 9 +- .../renderer_vulkan/pipeline_statistics.h | 9 +- .../renderer_vulkan/present/anti_alias_pass.h | 4 +- .../renderer_vulkan/present/fsr.cpp | 92 ++-- src/video_core/renderer_vulkan/present/fsr.h | 31 +- .../renderer_vulkan/present/fxaa.cpp | 87 ++-- src/video_core/renderer_vulkan/present/fxaa.h | 56 ++- .../renderer_vulkan/present/layer.cpp | 71 ++- .../renderer_vulkan/present/layer.h | 22 +- .../renderer_vulkan/present/sgsr.cpp | 37 +- src/video_core/renderer_vulkan/present/sgsr.h | 9 +- .../renderer_vulkan/present/smaa.cpp | 101 ++-- src/video_core/renderer_vulkan/present/smaa.h | 31 +- .../present/window_adapt_pass.cpp | 34 +- .../present/window_adapt_pass.h | 17 +- .../renderer_vulkan/renderer_vulkan.cpp | 10 +- .../renderer_vulkan/vk_blit_screen.cpp | 39 +- .../renderer_vulkan/vk_blit_screen.h | 14 +- .../renderer_vulkan/vk_compute_pass.cpp | 18 +- .../renderer_vulkan/vk_compute_pass.h | 4 +- .../renderer_vulkan/vk_compute_pipeline.cpp | 8 +- .../renderer_vulkan/vk_compute_pipeline.h | 2 +- .../renderer_vulkan/vk_descriptor_pool.cpp | 23 +- .../renderer_vulkan/vk_descriptor_pool.h | 16 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 4 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 2 +- .../renderer_vulkan/vk_query_cache.cpp | 64 +-- .../renderer_vulkan/vk_state_tracker.cpp | 4 +- .../renderer_vulkan/vk_update_descriptor.h | 20 +- src/video_core/video_core.cpp | 8 +- src/video_core/video_core.h | 8 +- 307 files changed, 4419 insertions(+), 4477 deletions(-) diff --git a/.gitignore b/.gitignore index 67bdd8adf4..75e728babe 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ # Build directory /[Bb]uild*/ doc-build/ -out/ AppDir/ uruntime diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index fcaab2b320..234c831ac0 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,10 +11,11 @@ namespace AudioCore { -AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique()} { +AudioCore::AudioCore(Core::System& system) { + audio_manager.emplace(); CreateSinks(); // Must be created after the sinks - adsp = std::make_unique(system, *output_sink); + adsp.emplace(system, *output_sink); } AudioCore ::~AudioCore() { diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h index e4e27fc661..ababd780b1 100644 --- a/src/audio_core/audio_core.h +++ b/src/audio_core/audio_core.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,10 +18,7 @@ class System; namespace AudioCore { -class AudioManager; -/** - * Main audio class, stored inside the core, and holding the audio manager, all sinks, and the ADSP. - */ +/// @brief Main audio class, stored inside the core, and holding the audio manager, all sinks, and the ADSP. class AudioCore { public: explicit AudioCore(Core::System& system); @@ -50,27 +50,22 @@ public: */ Sink::Sink& GetInputSink(); - /** - * Get the ADSP. - * - * @return Ref to the ADSP. - */ + /// @brief Get the ADSP. + /// @return Ref to the ADSP. ADSP::ADSP& ADSP(); private: - /** - * Create the sinks on startup. - */ + /// @brief Create the sinks on startup. void CreateSinks(); /// Main audio manager for audio in/out - std::unique_ptr audio_manager; + std::optional audio_manager; /// Sink used for audio renderer and audio out std::unique_ptr output_sink; /// Sink used for audio input std::unique_ptr input_sink; /// The ADSP in the sysmodule - std::unique_ptr adsp; + std::optional adsp; }; } // namespace AudioCore diff --git a/src/audio_core/audio_in_manager.cpp b/src/audio_core/audio_in_manager.cpp index 63b064922a..6b528e9db0 100644 --- a/src/audio_core/audio_in_manager.cpp +++ b/src/audio_core/audio_in_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,8 +44,7 @@ void Manager::ReleaseSessionId(const size_t session_id) { Result Manager::LinkToManager() { std::scoped_lock l{mutex}; if (!linked_to_manager) { - AudioManager& manager{system.AudioCore().GetAudioManager()}; - manager.SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this)); + system.AudioCore().GetAudioManager().SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this)); linked_to_manager = true; } diff --git a/src/audio_core/audio_manager.cpp b/src/audio_core/audio_manager.cpp index 10b56f2140..93142a53fb 100644 --- a/src/audio_core/audio_manager.cpp +++ b/src/audio_core/audio_manager.cpp @@ -1,81 +1,77 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "audio_core/audio_manager.h" +#include "common/thread.h" #include "core/core.h" #include "core/hle/service/audio/errors.h" namespace AudioCore { AudioManager::AudioManager() { - thread = std::jthread([this]() { ThreadFunc(); }); + thread = std::jthread([this](std::stop_token stop_token) { + Common::SetCurrentThreadName("AudioManager"); + std::unique_lock l{events.GetAudioEventLock()}; + events.ClearEvents(); + while (!stop_token.stop_requested()) { + const auto timed_out{events.Wait(l, std::chrono::seconds(2))}; + if (events.CheckAudioEventSet(Event::Type::Max)) { + break; + } + for (size_t i = 0; i < buffer_events.size(); i++) { + const auto event_type = Event::Type(i); + if (events.CheckAudioEventSet(event_type) || timed_out) { + if (buffer_events[i]) { + buffer_events[i](); + } + } + events.SetAudioEvent(event_type, false); + } + } + }); } void AudioManager::Shutdown() { - running = false; events.SetAudioEvent(Event::Type::Max, true); - thread.join(); + if (thread.joinable()) { + thread.request_stop(); + thread.join(); + } } Result AudioManager::SetOutManager(BufferEventFunc buffer_func) { - if (!running) { - return Service::Audio::ResultOperationFailed; + if (thread.joinable()) { + std::scoped_lock l{lock}; + const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)}; + if (buffer_events[index] == nullptr) { + buffer_events[index] = std::move(buffer_func); + needs_update = true; + events.SetAudioEvent(Event::Type::AudioOutManager, true); + } + return ResultSuccess; } - - std::scoped_lock l{lock}; - - const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)}; - if (buffer_events[index] == nullptr) { - buffer_events[index] = std::move(buffer_func); - needs_update = true; - events.SetAudioEvent(Event::Type::AudioOutManager, true); - } - return ResultSuccess; + return Service::Audio::ResultOperationFailed; } Result AudioManager::SetInManager(BufferEventFunc buffer_func) { - if (!running) { - return Service::Audio::ResultOperationFailed; + if (thread.joinable()) { + std::scoped_lock l{lock}; + const auto index{events.GetManagerIndex(Event::Type::AudioInManager)}; + if (buffer_events[index] == nullptr) { + buffer_events[index] = std::move(buffer_func); + needs_update = true; + events.SetAudioEvent(Event::Type::AudioInManager, true); + } + return ResultSuccess; } - - std::scoped_lock l{lock}; - - const auto index{events.GetManagerIndex(Event::Type::AudioInManager)}; - if (buffer_events[index] == nullptr) { - buffer_events[index] = std::move(buffer_func); - needs_update = true; - events.SetAudioEvent(Event::Type::AudioInManager, true); - } - return ResultSuccess; + return Service::Audio::ResultOperationFailed; } void AudioManager::SetEvent(const Event::Type type, const bool signalled) { events.SetAudioEvent(type, signalled); } -void AudioManager::ThreadFunc() { - std::unique_lock l{events.GetAudioEventLock()}; - events.ClearEvents(); - running = true; - - while (running) { - const auto timed_out{events.Wait(l, std::chrono::seconds(2))}; - - if (events.CheckAudioEventSet(Event::Type::Max)) { - break; - } - - for (size_t i = 0; i < buffer_events.size(); i++) { - const auto event_type = static_cast(i); - - if (events.CheckAudioEventSet(event_type) || timed_out) { - if (buffer_events[i]) { - buffer_events[i](); - } - } - events.SetAudioEvent(event_type, false); - } - } -} - } // namespace AudioCore diff --git a/src/audio_core/audio_manager.h b/src/audio_core/audio_manager.h index 02270242ac..0194aa16db 100644 --- a/src/audio_core/audio_manager.h +++ b/src/audio_core/audio_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -66,13 +69,6 @@ public: void SetEvent(Event::Type type, bool signalled); private: - /** - * Main thread, waiting on a manager signal and calling the registered function. - */ - void ThreadFunc(); - - /// Is the main thread running? - std::atomic running{}; /// Unused bool needs_update{}; /// Events to be set and signalled diff --git a/src/audio_core/audio_out_manager.cpp b/src/audio_core/audio_out_manager.cpp index 316ea7c817..569df8d1e0 100644 --- a/src/audio_core/audio_out_manager.cpp +++ b/src/audio_core/audio_out_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -40,8 +43,7 @@ void Manager::ReleaseSessionId(const size_t session_id) { Result Manager::LinkToManager() { std::scoped_lock l{mutex}; if (!linked_to_manager) { - AudioManager& manager{system.AudioCore().GetAudioManager()}; - manager.SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this)); + system.AudioCore().GetAudioManager().SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this)); linked_to_manager = true; } diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp index 2a1ae1bb3f..2e9da7876f 100644 --- a/src/audio_core/device/device_session.cpp +++ b/src/audio_core/device/device_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -39,7 +42,7 @@ Result DeviceSession::Initialize(std::string_view name_, SampleFormat sample_for channel_count = channel_count_; session_id = session_id_; handle = handle_; - handle->Open(); + handle->Open(system.Kernel()); applet_resource_user_id = applet_resource_user_id_; if (type == Sink::StreamType::In) { @@ -60,7 +63,7 @@ void DeviceSession::Finalize() { } if (handle) { - handle->Close(); + handle->Close(system.Kernel()); handle = nullptr; } } diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp index ec1f565736..f71a2df6be 100644 --- a/src/audio_core/in/audio_in_system.cpp +++ b/src/audio_core/in/audio_in_system.cpp @@ -122,7 +122,7 @@ Result System::Stop() { session->SetVolume(0.0f); session->ClearBuffers(); if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) { - buffer_event->Signal(); + buffer_event->Signal(system.Kernel()); } state = State::Stopped; } @@ -164,7 +164,7 @@ void System::ReleaseBuffers() { if (signal) { // Signal if any buffer was released, or if none are registered, we need more. - buffer_event->Signal(); + buffer_event->Signal(system.Kernel()); } } @@ -181,7 +181,7 @@ bool System::FlushAudioInBuffers() { buffers.FlushBuffers(buffers_released); if (buffers_released > 0) { - buffer_event->Signal(); + buffer_event->Signal(system.Kernel()); } return true; } diff --git a/src/audio_core/out/audio_out_system.cpp b/src/audio_core/out/audio_out_system.cpp index dcb0d0694e..46f30f19c6 100644 --- a/src/audio_core/out/audio_out_system.cpp +++ b/src/audio_core/out/audio_out_system.cpp @@ -121,7 +121,7 @@ Result System::Stop() { session->SetVolume(0.0f); session->ClearBuffers(); if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) { - buffer_event->Signal(); + buffer_event->Signal(system.Kernel()); } state = State::Stopped; } @@ -162,7 +162,7 @@ void System::ReleaseBuffers() { bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)}; if (signal) { // Signal if any buffer was released, or if none are registered, we need more. - buffer_event->Signal(); + buffer_event->Signal(system.Kernel()); } } @@ -179,7 +179,7 @@ bool System::FlushAudioOutBuffers() { buffers.FlushBuffers(buffers_released); if (buffers_released > 0) { - buffer_event->Signal(); + buffer_event->Signal(system.Kernel()); } return true; } diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp index 2053ec6dd4..b7675ff5de 100644 --- a/src/audio_core/renderer/system.cpp +++ b/src/audio_core/renderer/system.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -540,7 +540,7 @@ Result System::Update(std::span input, std::span performance, std: return result; } - adsp_rendered_event->Clear(); + adsp_rendered_event->Clear(core.Kernel()); num_times_updated++; const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()}; @@ -624,7 +624,7 @@ void System::SendCommandToDsp() { reset_command_buffers = false; command_buffer_size = command_size; if (remaining_command_count == 0) { - adsp_rendered_event->Signal(); + adsp_rendered_event->Signal(core.Kernel()); } } else { audio_renderer.ClearRemainCommandCount(session_id); diff --git a/src/core/core.cpp b/src/core/core.cpp index e730b808e0..33fece39f6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -108,7 +108,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, hid_core{}, cpu_manager{system}, + : kernel{system}, fs_controller{system}, hid_core{system.Kernel()}, cpu_manager{system}, reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {} u64 program_id; @@ -271,7 +271,7 @@ struct System::Impl { SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { host1x_core.emplace(system); - gpu_core = VideoCore::CreateGPU(emu_window, system); + VideoCore::CreateGPU(gpu_core, emu_window, system); if (!gpu_core) return SystemResultStatus::ErrorVideoCore; @@ -347,7 +347,7 @@ struct System::Impl { // Register with applet manager // All threads are started, begin main process execution, now that we're in the clear - applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params); + applet_manager.CreateAndInsertByFrontendAppletParameters(std::make_unique(*std::move(process)), params); if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_current_game) { @@ -391,10 +391,8 @@ struct System::Impl { is_powered_on = false; exit_locked = false; exit_requested = false; - - if (gpu_core != nullptr) { + if (gpu_core) gpu_core->NotifyShutdown(); - } stop_event.request_stop(); core_timing.SyncPause(false); @@ -478,6 +476,7 @@ struct System::Impl { std::optional cheat_engine; std::optional memory_freezer; std::optional renderdoc_api; + std::optional gpu_core; std::array gpu_dirty_memory_managers; std::vector> user_channel; @@ -492,7 +491,6 @@ struct System::Impl { std::unique_ptr content_provider; /// AppLoader used to load the current executing application std::unique_ptr app_loader; - std::unique_ptr gpu_core; std::stop_source stop_event; mutable std::mutex suspend_guard; @@ -925,7 +923,7 @@ void System::PushGeneralChannelData(std::vector&& data) { const bool was_empty = impl->general_channel.empty(); impl->general_channel.push_back(std::move(data)); if (was_empty) { - impl->general_channel_event->Signal(); + impl->general_channel_event->Signal(impl->kernel); } } @@ -937,7 +935,7 @@ bool System::TryPopGeneralChannel(std::vector& out_data) { out_data = std::move(impl->general_channel.back()); impl->general_channel.pop_back(); if (impl->general_channel.empty()) { - impl->general_channel_event->Clear(); + impl->general_channel_event->Clear(impl->kernel); } return true; } diff --git a/src/core/core.h b/src/core/core.h index 012533c1fa..93f7b057f7 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -438,7 +438,6 @@ public: /// Applies any changes to settings to this core instance. void ApplySettings(); -private: struct Impl; std::unique_ptr impl; }; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 10fdcdf8a2..7194fa5022 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -25,9 +25,11 @@ CpuManager::~CpuManager() = default; void CpuManager::Initialize() { num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1; - gpu_barrier = std::make_unique(num_cores + 1); + gpu_barrier.emplace(num_cores + 1); for (std::size_t core = 0; core < num_cores; core++) - core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { RunThread(token, core); }); + core_data[core].host_thread = std::jthread([this, core](std::stop_token token) { + RunThread(token, core); + }); } void CpuManager::Shutdown() { @@ -39,69 +41,61 @@ void CpuManager::Shutdown() { } } -void CpuManager::GuestThreadFunction() { +void CpuManager::GuestThreadFunction(Kernel::KernelCore& kernel) { if (is_multicore) { - MultiCoreRunGuestThread(); + MultiCoreRunGuestThread(kernel); } else { - SingleCoreRunGuestThread(); + SingleCoreRunGuestThread(kernel); } } -void CpuManager::IdleThreadFunction() { +void CpuManager::IdleThreadFunction(Kernel::KernelCore& kernel) { if (is_multicore) { - MultiCoreRunIdleThread(); + MultiCoreRunIdleThread(kernel); } else { - SingleCoreRunIdleThread(); + SingleCoreRunIdleThread(kernel); } } -void CpuManager::ShutdownThreadFunction() { - ShutdownThread(); +void CpuManager::ShutdownThreadFunction(Kernel::KernelCore& kernel) { + ShutdownThread(kernel); } -void CpuManager::HandleInterrupt() { - auto& kernel = system.Kernel(); +void CpuManager::HandleInterrupt(Kernel::KernelCore& kernel) { auto core_index = kernel.CurrentPhysicalCoreIndex(); - - Kernel::KInterruptManager::HandleInterrupt(kernel, static_cast(core_index)); + Kernel::KInterruptManager::HandleInterrupt(kernel, s32(core_index)); } /////////////////////////////////////////////////////////////////////////////// /// MultiCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::MultiCoreRunGuestThread() { +void CpuManager::MultiCoreRunGuestThread(Kernel::KernelCore& kernel) { // Similar to UserModeThreadStarter in HOS - auto& kernel = system.Kernel(); auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(); + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); while (!physical_core->IsInterrupted()) { - physical_core->RunThread(thread); + physical_core->RunThread(kernel, thread); physical_core = &kernel.CurrentPhysicalCore(); } - - HandleInterrupt(); + HandleInterrupt(kernel); } } -void CpuManager::MultiCoreRunIdleThread() { +void CpuManager::MultiCoreRunIdleThread(Kernel::KernelCore& kernel) { // Not accurate to HOS. Remove this entire method when singlecore is removed. // See notes in KScheduler::ScheduleImpl for more information about why this // is inaccurate. - - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto& physical_core = kernel.CurrentPhysicalCore(); if (!physical_core.IsInterrupted()) { physical_core.Idle(); } - - HandleInterrupt(); + HandleInterrupt(kernel); } } @@ -109,15 +103,14 @@ void CpuManager::MultiCoreRunIdleThread() { /// SingleCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::SingleCoreRunGuestThread() { - auto& kernel = system.Kernel(); +void CpuManager::SingleCoreRunGuestThread(Kernel::KernelCore& kernel) { auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(); + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); if (!physical_core->IsInterrupted()) { - physical_core->RunThread(thread); + physical_core->RunThread(kernel, thread); physical_core = &kernel.CurrentPhysicalCore(); } @@ -125,26 +118,22 @@ void CpuManager::SingleCoreRunGuestThread() { system.CoreTiming().Advance(); kernel.SetIsPhantomModeForSingleCore(false); - PreemptSingleCore(); - HandleInterrupt(); + PreemptSingleCore(kernel); + HandleInterrupt(kernel); } } -void CpuManager::SingleCoreRunIdleThread() { - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - +void CpuManager::SingleCoreRunIdleThread(Kernel::KernelCore& kernel) { + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { - PreemptSingleCore(false); + PreemptSingleCore(kernel, false); system.CoreTiming().AddTicks(1000U); idle_count++; - HandleInterrupt(); + HandleInterrupt(kernel); } } -void CpuManager::PreemptSingleCore(bool from_running_environment) { - auto& kernel = system.Kernel(); - +void CpuManager::PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment) { if (idle_count >= 4 || from_running_environment) { if (!from_running_environment) { system.CoreTiming().Idle(); @@ -156,7 +145,7 @@ void CpuManager::PreemptSingleCore(bool from_running_environment) { } current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); system.CoreTiming().ResetTicks(); - kernel.Scheduler(current_core).PreemptSingleCore(); + kernel.Scheduler(current_core).PreemptSingleCore(kernel); // We've now been scheduled again, and we may have exchanged schedulers. // Reload the scheduler in case it's different. @@ -165,20 +154,16 @@ void CpuManager::PreemptSingleCore(bool from_running_environment) { } } -void CpuManager::GuestActivate() { +void CpuManager::GuestActivate(Kernel::KernelCore& kernel) { // Similar to the HorizonKernelMain callback in HOS - auto& kernel = system.Kernel(); auto* scheduler = kernel.CurrentScheduler(); - - scheduler->Activate(); + scheduler->Activate(kernel); UNREACHABLE(); } -void CpuManager::ShutdownThread() { - auto& kernel = system.Kernel(); +void CpuManager::ShutdownThread(Kernel::KernelCore& kernel) { auto* thread = kernel.GetCurrentEmuThread(); auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0; - Common::Fiber::YieldTo(thread->GetHostContext(), *core_data[core].host_context); UNREACHABLE(); } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index a249dc5f76..5e97f51bfb 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,6 +17,10 @@ #include "common/thread.h" #include "core/hardware_properties.h" +namespace Kernel { +class KernelCore; +} + namespace Common { class Event; class Fiber; @@ -51,57 +58,55 @@ public: void Initialize(); void Shutdown(); - std::function GetGuestActivateFunc() { - return [this] { GuestActivate(); }; + std::function GetGuestActivateFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { GuestActivate(kernel); }; } - std::function GetGuestThreadFunc() { - return [this] { GuestThreadFunction(); }; + std::function GetGuestThreadFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { GuestThreadFunction(kernel); }; } - std::function GetIdleThreadStartFunc() { - return [this] { IdleThreadFunction(); }; + std::function GetIdleThreadStartFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { IdleThreadFunction(kernel); }; } - std::function GetShutdownThreadStartFunc() { - return [this] { ShutdownThreadFunction(); }; + std::function GetShutdownThreadStartFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { ShutdownThreadFunction(kernel); }; } - void PreemptSingleCore(bool from_running_environment = true); + void PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment = true); std::size_t CurrentCore() const { return current_core.load(); } private: - void GuestThreadFunction(); - void IdleThreadFunction(); - void ShutdownThreadFunction(); + void GuestThreadFunction(Kernel::KernelCore& kernel); + void IdleThreadFunction(Kernel::KernelCore& kernel); + void ShutdownThreadFunction(Kernel::KernelCore& kernel); - void MultiCoreRunGuestThread(); - void MultiCoreRunIdleThread(); + void MultiCoreRunGuestThread(Kernel::KernelCore& kernel); + void MultiCoreRunIdleThread(Kernel::KernelCore& kernel); - void SingleCoreRunGuestThread(); - void SingleCoreRunIdleThread(); + void SingleCoreRunGuestThread(Kernel::KernelCore& kernel); + void SingleCoreRunIdleThread(Kernel::KernelCore& kernel); - void GuestActivate(); - void HandleInterrupt(); - void ShutdownThread(); + void GuestActivate(Kernel::KernelCore& kernel); + void HandleInterrupt(Kernel::KernelCore& kernel); + void ShutdownThread(Kernel::KernelCore& kernel); void RunThread(std::stop_token stop_token, std::size_t core); + static constexpr std::size_t max_cycle_runs = 5; + + std::optional gpu_barrier{}; struct CoreData { std::shared_ptr host_context; std::jthread host_thread; }; - - std::unique_ptr gpu_barrier{}; std::array core_data{}; - - bool is_async_gpu{}; - bool is_multicore{}; + Core::System& system; std::atomic current_core{}; std::size_t idle_count{}; std::size_t num_cores{}; - static constexpr std::size_t max_cycle_runs = 5; - - System& system; + bool is_async_gpu{}; + bool is_multicore{}; }; } // namespace Core diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index f90e78f959..d1c767721b 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -81,7 +81,10 @@ namespace Core { class DebuggerImpl : public DebuggerBackend { public: - explicit DebuggerImpl(Core::System& system_, u16 port) : system{system_} { + explicit DebuggerImpl(Core::System& system_, u16 port) + : system{system_} + , debug_process{system_.Kernel()} + { InitializeServer(port); } @@ -121,7 +124,7 @@ public: } void SetActiveThread(Kernel::KThread* thread) override { - state->active_thread = thread; + state->active_thread = {system.Kernel(), thread}; } Kernel::KThread* GetActiveThread() override { @@ -168,14 +171,7 @@ private: frontend = std::make_unique(*this, system, debug_process.GetPointerUnsafe()); // Set the new state. This will tear down any existing state. - state = ConnectionState{ - .client_socket{std::move(peer)}, - .signal_pipe{io_context}, - .info{}, - .active_thread{}, - .client_data{}, - .pipe_data{}, - }; + state.emplace(std::move(peer), io_context, system.Kernel()); // Set up the client signals for new data. AsyncReceiveInto(state->signal_pipe, state->pipe_data, [&](auto d) { PipeData(d); }); @@ -204,7 +200,7 @@ private: PauseEmulation(); // Notify the client. - state->active_thread = state->info.thread; + state->active_thread = {system.Kernel(), state->info.thread}; UpdateActiveThread(); if (state->info.type == SignalType::Watchpoint) { @@ -258,7 +254,7 @@ private: auto* gdb = static_cast(frontend.get()); MarkResumed([this, threads = std::move(gdb->resume_threads)] { state->active_thread->SetStepState(Kernel::StepState::StepPending); - state->active_thread->Resume(Kernel::SuspendType::Debug); + state->active_thread->Resume(system.Kernel(), Kernel::SuspendType::Debug); ResumeThreads(threads, state->active_thread.GetPointerUnsafe()); }); break; @@ -281,7 +277,7 @@ private: // Put all threads to sleep on next scheduler round. for (auto& thread : ThreadList()) { - thread.RequestSuspend(Kernel::SuspendType::Debug); + thread.RequestSuspend(system.Kernel(), Kernel::SuspendType::Debug); } } @@ -296,7 +292,7 @@ private: } thread.SetStepState(Kernel::StepState::NotStepping); - thread.Resume(Kernel::SuspendType::Debug); + thread.Resume(system.Kernel(), Kernel::SuspendType::Debug); } } @@ -312,7 +308,7 @@ private: } thread->SetStepState(Kernel::StepState::NotStepping); - thread->Resume(Kernel::SuspendType::Debug); + thread->Resume(system.Kernel(), Kernel::SuspendType::Debug); } } @@ -332,7 +328,7 @@ private: return; } } - state->active_thread = std::addressof(threads.front()); + state->active_thread = {system.Kernel(), std::addressof(threads.front())}; } private: @@ -354,13 +350,20 @@ private: std::mutex connection_lock; struct ConnectionState { - boost::asio::ip::tcp::socket client_socket; #ifdef USE_BOOST_v1 - boost::process::v1::async_pipe signal_pipe; + using async_pipe = boost::process::v1::async_pipe; #else - boost::process::async_pipe signal_pipe; + using async_pipe = boost::process::async_pipe; #endif + ConnectionState(boost::asio::ip::tcp::socket&& client_socket_, async_pipe signal_pipe_, Kernel::KernelCore& kernel) + : client_socket{std::move(client_socket_)} + , signal_pipe{signal_pipe_} + , active_thread{kernel, nullptr} + {} + + boost::asio::ip::tcp::socket client_socket; + async_pipe signal_pipe; SignalInfo info; Kernel::KScopedAutoObject active_thread; std::array client_data; diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 5d61c819f8..44ddf11c39 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -323,13 +323,13 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) { success = true; break; case BreakpointType::WriteWatch: - success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); + success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); + success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = debug_process->InsertWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = debug_process->InsertWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: @@ -368,13 +368,13 @@ void GDBStub::HandleBreakpointRemove(std::string_view sv) { break; } case BreakpointType::WriteWatch: - success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Write); + success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Write); break; case BreakpointType::ReadWatch: - success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::Read); + success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::Read); break; case BreakpointType::AccessWatch: - success = debug_process->RemoveWatchpoint(addr, size, Kernel::DebugWatchpointType::ReadOrWrite); + success = debug_process->RemoveWatchpoint(system.Kernel(), addr, size, Kernel::DebugWatchpointType::ReadOrWrite); break; case BreakpointType::Hardware: default: diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp index 855a8226ef..6d1cd030e0 100644 --- a/src/core/hle/kernel/global_scheduler_context.cpp +++ b/src/core/hle/kernel/global_scheduler_context.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -17,7 +17,8 @@ namespace Kernel { GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel) - : m_kernel{kernel}, m_scheduler_lock{kernel} {} + : m_scheduler_lock{kernel} +{} GlobalSchedulerContext::~GlobalSchedulerContext() = default; @@ -37,7 +38,7 @@ void GlobalSchedulerContext::RemoveThread(KThread* thread) noexcept { /// and then does some core rebalancing. Preemption priorities can be found /// in the array 'preemption_priorities'. /// @note This operation happens every 10ms. -void GlobalSchedulerContext::PreemptThreads() noexcept { +void GlobalSchedulerContext::PreemptThreads(KernelCore& kernel) noexcept { // The priority levels at which the global scheduler preempts threads every 10 ms. They are // ordered from Core 0 to Core 3. static constexpr std::array per_core{ @@ -46,9 +47,9 @@ void GlobalSchedulerContext::PreemptThreads() noexcept { 59, 63, }; - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); for (u32 core_id = 0; core_id < per_core.size(); core_id++) - KScheduler::RotateScheduledQueue(m_kernel, core_id, per_core[core_id]); + KScheduler::RotateScheduledQueue(kernel, core_id, per_core[core_id]); } /// @brief Returns true if the global scheduler lock is acquired @@ -69,11 +70,11 @@ void GlobalSchedulerContext::UnregisterDummyThreadForWakeup(KThread* thread) noe } } -void GlobalSchedulerContext::WakeupWaitingDummyThreads() noexcept { +void GlobalSchedulerContext::WakeupWaitingDummyThreads(KernelCore& kernel) noexcept { ASSERT(this->IsLocked()); if (m_woken_dummy_threads.size() > 0) { for (auto* thread : m_woken_dummy_threads) - thread->DummyThreadEndWait(); + thread->DummyThreadEndWait(kernel); m_woken_dummy_threads.clear(); } } diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h index 64aee86af8..dd53477d2d 100644 --- a/src/core/hle/kernel/global_scheduler_context.h +++ b/src/core/hle/kernel/global_scheduler_context.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -50,17 +50,16 @@ public: } void AddThread(KThread* thread) noexcept; void RemoveThread(KThread* thread) noexcept; - void PreemptThreads() noexcept; + void PreemptThreads(KernelCore& kernel) noexcept; bool IsLocked() const noexcept; void UnregisterDummyThreadForWakeup(KThread* thread) noexcept; void RegisterDummyThreadForWakeup(KThread* thread) noexcept; - void WakeupWaitingDummyThreads() noexcept; + void WakeupWaitingDummyThreads(KernelCore& kernel) noexcept; private: friend class KScopedSchedulerLock; friend class KScopedSchedulerLockAndSleep; - KernelCore& m_kernel; std::atomic_bool m_scheduler_update_needed{}; KSchedulerPriorityQueue m_priority_queue; LockType m_scheduler_lock; diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index a0e20bbbb4..5dd8afaf96 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -281,7 +284,7 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) { // Reserve memory from the system resource limit. ASSERT( - kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, slab_size)); + kernel.GetSystemResourceLimit()->Reserve(kernel, LimitableResource::PhysicalMemoryMax, slab_size)); // Allocate memory for the slab. constexpr auto AllocateOption = KMemoryManager::EncodeOption( diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 48889253dc..02634f8721 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,8 +19,9 @@ namespace Kernel { -KAddressArbiter::KAddressArbiter(Core::System& system) - : m_system{system}, m_kernel{system.Kernel()} {} +KAddressArbiter::KAddressArbiter(Core::System& system_) + : system{system_} +{} KAddressArbiter::~KAddressArbiter() = default; namespace { @@ -112,7 +116,7 @@ public: explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel, KAddressArbiter::ThreadTree* t) : KThreadQueue(kernel), m_tree(t) {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // If the thread is waiting on an address arbiter, remove it from the tree. if (waiting_thread->IsWaitingForAddressArbiter()) { m_tree->erase(m_tree->iterator_to(*waiting_thread)); @@ -120,7 +124,7 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -133,14 +137,14 @@ Result KAddressArbiter::Signal(uint64_t addr, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(system.Kernel()); auto it = m_tree.nfind_key({addr, -1}); while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(ResultSuccess); + target_thread->EndWait(system.Kernel(), ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -156,11 +160,11 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(system.Kernel()); // Check the userspace value. s32 user_value{}; - R_UNLESS(UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, value + 1), + R_UNLESS(UpdateIfEqual(system.Kernel(), std::addressof(user_value), addr, value, value + 1), ResultInvalidCurrentMemory); R_UNLESS(user_value == value, ResultInvalidState); @@ -169,7 +173,7 @@ Result KAddressArbiter::SignalAndIncrementIfEqual(uint64_t addr, s32 value, s32 (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(ResultSuccess); + target_thread->EndWait(system.Kernel(), ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -185,7 +189,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(system.Kernel()); auto it = m_tree.nfind_key({addr, -1}); // Determine the updated value. @@ -220,9 +224,9 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 s32 user_value{}; bool succeeded{}; if (value != new_value) { - succeeded = UpdateIfEqual(m_kernel, std::addressof(user_value), addr, value, new_value); + succeeded = UpdateIfEqual(system.Kernel(), std::addressof(user_value), addr, value, new_value); } else { - succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); + succeeded = ReadFromUser(system.Kernel(), std::addressof(user_value), addr); } R_UNLESS(succeeded, ResultInvalidCurrentMemory); @@ -232,7 +236,7 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 (it->GetAddressArbiterKey() == addr)) { // End the thread's wait. KThread* target_thread = std::addressof(*it); - target_thread->EndWait(ResultSuccess); + target_thread->EndWait(system.Kernel(), ResultSuccess); ASSERT(target_thread->IsWaitingForAddressArbiter()); target_thread->ClearAddressArbiter(); @@ -246,12 +250,12 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(uint64_t addr, s32 Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKAddressArbiter wait_queue(m_kernel, std::addressof(m_tree)); + ThreadQueueImplForKAddressArbiter wait_queue(system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp{m_kernel, std::addressof(timer), cur_thread, timeout}; + KScopedSchedulerLockAndSleep slp{system.Kernel(), std::addressof(timer), cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -263,9 +267,9 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, s32 user_value{}; bool succeeded{}; if (decrement) { - succeeded = DecrementIfLessThan(m_kernel, std::addressof(user_value), addr, value); + succeeded = DecrementIfLessThan(system.Kernel(), std::addressof(user_value), addr, value); } else { - succeeded = ReadFromUser(m_kernel, std::addressof(user_value), addr); + succeeded = ReadFromUser(system.Kernel(), std::addressof(user_value), addr); } if (!succeeded) { @@ -291,7 +295,7 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, // Wait for the thread to finish. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } @@ -301,12 +305,12 @@ Result KAddressArbiter::WaitIfLessThan(uint64_t addr, s32 value, bool decrement, Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKAddressArbiter wait_queue(m_kernel, std::addressof(m_tree)); + ThreadQueueImplForKAddressArbiter wait_queue(system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp{m_kernel, std::addressof(timer), cur_thread, timeout}; + KScopedSchedulerLockAndSleep slp{system.Kernel(), std::addressof(timer), cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -316,7 +320,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Read the value from userspace. s32 user_value{}; - if (!ReadFromUser(m_kernel, std::addressof(user_value), addr)) { + if (!ReadFromUser(system.Kernel(), std::addressof(user_value), addr)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -339,7 +343,7 @@ Result KAddressArbiter::WaitIfEqual(uint64_t addr, s32 value, s64 timeout) { // Wait for the thread to finish. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } diff --git a/src/core/hle/kernel/k_address_arbiter.h b/src/core/hle/kernel/k_address_arbiter.h index 3b70e1ab28..b3afe19476 100644 --- a/src/core/hle/kernel/k_address_arbiter.h +++ b/src/core/hle/kernel/k_address_arbiter.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -60,8 +63,7 @@ private: private: ThreadTree m_tree; - Core::System& m_system; - KernelCore& m_kernel; + Core::System& system; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp index a7a46d29bb..14d1c4624d 100644 --- a/src/core/hle/kernel/k_auto_object.cpp +++ b/src/core/hle/kernel/k_auto_object.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -15,8 +15,8 @@ KAutoObject* KAutoObject::Create(KAutoObject* obj) { return obj; } -void KAutoObject::RegisterWithKernel() { - m_kernel.RegisterKernelObject(this); +void KAutoObject::RegisterWithKernel(KernelCore& kernel) { + kernel.RegisterKernelObject(this); } void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) { diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 5e8c0030ce..392b9c9f1d 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -87,21 +87,21 @@ private: KERNEL_AUTOOBJECT_TRAITS_IMPL(KAutoObject, KAutoObject, const); public: - explicit KAutoObject(KernelCore& kernel) : m_kernel(kernel) { + explicit KAutoObject(KernelCore& kernel) { m_class_token = GetStaticTypeObj().GetClassToken(); - RegisterWithKernel(); + RegisterWithKernel(kernel); } virtual ~KAutoObject() = default; static KAutoObject* Create(KAutoObject* ptr); // Destroy is responsible for destroying the auto object's resources when ref_count hits zero. - virtual void Destroy() { + virtual void Destroy(KernelCore& kernel) { UNIMPLEMENTED(); } // Finalize is responsible for cleaning up resource, but does not destroy the object. - virtual void Finalize() {} + virtual void Finalize(KernelCore& kernel) {} virtual KProcess* GetOwner() const { return nullptr; @@ -123,67 +123,50 @@ public: Derived DynamicCast() { static_assert(std::is_pointer_v); using DerivedType = std::remove_pointer_t; - - if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { - return static_cast(this); - } else { - return nullptr; - } + if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) + return Derived(this); + return nullptr; } template const Derived DynamicCast() const { static_assert(std::is_pointer_v); using DerivedType = std::remove_pointer_t; - - if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) { - return static_cast(this); - } else { - return nullptr; - } + if (this->IsDerivedFrom(DerivedType::GetStaticTypeObj())) + return Derived(this); + return nullptr; } - bool Open() { + bool Open(KernelCore& kernel) { // Atomically increment the reference count, only if it's positive. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { - if (cur_ref_count == 0) { + if (cur_ref_count == 0) return false; - } ASSERT(cur_ref_count < cur_ref_count + 1); - } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, - std::memory_order_relaxed)); - + } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count + 1, std::memory_order_relaxed)); return true; } - void Close() { + void Close(KernelCore& kernel) { // Atomically decrement the reference count, not allowing it to become negative. u32 cur_ref_count = m_ref_count.load(std::memory_order_acquire); do { - if (cur_ref_count == 0) { + if (cur_ref_count == 0) return; - } ASSERT(cur_ref_count > 0); - } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, - std::memory_order_acq_rel)); - + } while (!m_ref_count.compare_exchange_weak(cur_ref_count, cur_ref_count - 1, std::memory_order_acq_rel)); // If ref count hits 1, destroy the object. if (cur_ref_count == 1) { - KernelCore& kernel = m_kernel; - this->Destroy(); + this->Destroy(kernel); KAutoObject::UnregisterWithKernel(kernel, this); } } private: - void RegisterWithKernel(); + void RegisterWithKernel(KernelCore& kernel); static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self); -protected: - KernelCore& m_kernel; - -private: std::atomic m_ref_count{}; ClassTokenType m_class_token{}; }; @@ -225,17 +208,22 @@ class KScopedAutoObject { public: YUZU_NON_COPYABLE(KScopedAutoObject); - constexpr KScopedAutoObject() = default; + constexpr KScopedAutoObject(KernelCore& kernel_) + : kernel{kernel_} + {} - constexpr KScopedAutoObject(T* o) : m_obj(o) { + constexpr KScopedAutoObject(KernelCore& kernel_, T* o) + : kernel{kernel_} + , m_obj(o) + { if (m_obj != nullptr) { - m_obj->Open(); + m_obj->Open(kernel); } } ~KScopedAutoObject() { if (m_obj != nullptr) { - m_obj->Close(); + m_obj->Close(kernel); } m_obj = nullptr; } @@ -253,7 +241,7 @@ public: if (rhs.m_obj != nullptr) { derived = rhs.m_obj->template DynamicCast(); if (derived == nullptr) { - rhs.m_obj->Close(); + rhs.m_obj->Close(rhs.kernel); } } @@ -274,8 +262,16 @@ public: return *m_obj; } + constexpr void SetObject(T* o) { + if (m_obj) + m_obj->Close(kernel); + m_obj = o; + if (m_obj) + m_obj->Open(kernel); + } + constexpr void Reset(T* o) { - KScopedAutoObject(o).Swap(*this); + KScopedAutoObject(kernel, o).Swap(*this); } constexpr T* GetPointerUnsafe() { @@ -304,6 +300,7 @@ private: friend class KScopedAutoObject; private: + KernelCore& kernel; T* m_obj{}; private: diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index 68cea978a0..d13995988c 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,7 +18,7 @@ namespace Kernel { KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KClientPort::~KClientPort() = default; -void KClientPort::Initialize(KPort* parent, s32 max_sessions) { +void KClientPort::Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions) { // Set member variables. m_num_sessions = 0; m_peak_sessions = 0; @@ -23,48 +26,48 @@ void KClientPort::Initialize(KPort* parent, s32 max_sessions) { m_max_sessions = max_sessions; } -void KClientPort::OnSessionFinalized() { - KScopedSchedulerLock sl{m_kernel}; +void KClientPort::OnSessionFinalized(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; if (const auto prev = m_num_sessions--; prev == m_max_sessions) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } -void KClientPort::OnServerClosed() {} +void KClientPort::OnServerClosed(KernelCore& kernel) {} -bool KClientPort::IsLight() const { +bool KClientPort::IsLight(KernelCore& kernel) const { return this->GetParent()->IsLight(); } -bool KClientPort::IsServerClosed() const { - return this->GetParent()->IsServerClosed(); +bool KClientPort::IsServerClosed(KernelCore& kernel) const { + return this->GetParent()->IsServerClosed(kernel); } -void KClientPort::Destroy() { +void KClientPort::Destroy(KernelCore& kernel) { // Note with our parent that we're closed. - m_parent->OnClientClosed(); + m_parent->OnClientClosed(kernel); // Close our reference to our parent. - m_parent->Close(); + m_parent->Close(kernel); } -bool KClientPort::IsSignaled() const { +bool KClientPort::IsSignaled(KernelCore& kernel) const { return m_num_sessions.load() < m_max_sessions; } -Result KClientPort::CreateSession(KClientSession** out) { +Result KClientPort::CreateSession(KernelCore& kernel, KClientSession** out) { // Declare the session we're going to allocate. KSession* session{}; // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel), + KScopedResourceReservation session_reservation(kernel, GetCurrentProcessPointer(kernel), LimitableResource::SessionCountMax); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); // Allocate a session normally. // TODO: Dynamic resource limits - session = KSession::Create(m_kernel); + session = KSession::Create(kernel); // Check that we successfully created a session. R_UNLESS(session != nullptr, ResultOutOfResource); @@ -72,7 +75,7 @@ Result KClientPort::CreateSession(KClientSession** out) { // Update the session counts. { ON_RESULT_FAILURE { - session->Close(); + session->Close(kernel); }; // Atomically increment the number of sessions. @@ -100,38 +103,37 @@ Result KClientPort::CreateSession(KClientSession** out) { } // Initialize the session. - session->Initialize(this, m_parent->GetName()); + session->Initialize(kernel, this, m_parent->GetName()); // Commit the session reservation. session_reservation.Commit(); // Register the session. - KSession::Register(m_kernel, session); + KSession::Register(kernel, session); ON_RESULT_FAILURE { - session->GetClientSession().Close(); - session->GetServerSession().Close(); + session->GetClientSession().Close(kernel); + session->GetServerSession().Close(kernel); }; // Enqueue the session with our parent. - R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession()))); + R_TRY(m_parent->EnqueueSession(kernel, std::addressof(session->GetServerSession()))); // We succeeded, so set the output. *out = std::addressof(session->GetClientSession()); R_SUCCEED(); } -Result KClientPort::CreateLightSession(KLightClientSession** out) { +Result KClientPort::CreateLightSession(KernelCore& kernel, KLightClientSession** out) { // Declare the session we're going to allocate. KLightSession* session{}; // Reserve a new session from the resource limit. - KScopedResourceReservation session_reservation(GetCurrentProcessPointer(m_kernel), - Svc::LimitableResource::SessionCountMax); + KScopedResourceReservation session_reservation(kernel, GetCurrentProcessPointer(kernel), Svc::LimitableResource::SessionCountMax); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); // Allocate a session normally. // TODO: Dynamic resource limits - session = KLightSession::Create(m_kernel); + session = KLightSession::Create(kernel); // Check that we successfully created a session. R_UNLESS(session != nullptr, ResultOutOfResource); @@ -139,7 +141,7 @@ Result KClientPort::CreateLightSession(KLightClientSession** out) { // Update the session counts. { ON_RESULT_FAILURE { - session->Close(); + session->Close(kernel); }; // Atomically increment the number of sessions. @@ -167,20 +169,20 @@ Result KClientPort::CreateLightSession(KLightClientSession** out) { } // Initialize the session. - session->Initialize(this, m_parent->GetName()); + session->Initialize(kernel, this, m_parent->GetName()); // Commit the session reservation. session_reservation.Commit(); // Register the session. - KLightSession::Register(m_kernel, session); + KLightSession::Register(kernel, session); ON_RESULT_FAILURE { - session->GetClientSession().Close(); - session->GetServerSession().Close(); + session->GetClientSession().Close(kernel); + session->GetServerSession().Close(kernel); }; // Enqueue the session with our parent. - R_TRY(m_parent->EnqueueSession(std::addressof(session->GetServerSession()))); + R_TRY(m_parent->EnqueueSession(kernel, std::addressof(session->GetServerSession()))); // We succeeded, so set the output. *out = std::addressof(session->GetClientSession()); diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index 28b3326081..3e48eeaa00 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,9 +26,9 @@ public: explicit KClientPort(KernelCore& kernel); ~KClientPort() override; - void Initialize(KPort* parent, s32 max_sessions); - void OnSessionFinalized(); - void OnServerClosed(); + void Initialize(KernelCore& kernel, KPort* parent, s32 max_sessions); + void OnSessionFinalized(KernelCore& kernel); + void OnServerClosed(KernelCore& kernel); const KPort* GetParent() const { return m_parent; @@ -44,15 +47,15 @@ public: return m_max_sessions; } - bool IsLight() const; - bool IsServerClosed() const; + bool IsLight(KernelCore& kernel) const; + bool IsServerClosed(KernelCore& kernel) const; // Overridden virtual functions. - void Destroy() override; - bool IsSignaled() const override; + void Destroy(KernelCore& kernel) override; + bool IsSignaled(KernelCore& kernel) const override; - Result CreateSession(KClientSession** out); - Result CreateLightSession(KLightClientSession** out); + Result CreateSession(KernelCore& kernel, KClientSession** out); + Result CreateLightSession(KernelCore& kernel, KLightClientSession** out); private: std::atomic m_num_sessions{}; diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 3e01e3b67f..95cb9896b9 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,41 +16,41 @@ namespace Kernel { KClientSession::KClientSession(KernelCore& kernel) : KAutoObject{kernel} {} KClientSession::~KClientSession() = default; -void KClientSession::Destroy() { - m_parent->OnClientClosed(); - m_parent->Close(); +void KClientSession::Destroy(KernelCore& kernel) { + m_parent->OnClientClosed(kernel); + m_parent->Close(kernel); } void KClientSession::OnServerClosed() {} -Result KClientSession::SendSyncRequest(uintptr_t address, size_t size) { +Result KClientSession::SendSyncRequest(KernelCore& kernel, uintptr_t address, size_t size) { // Create a session request. - KSessionRequest* request = KSessionRequest::Create(m_kernel); + KSessionRequest* request = KSessionRequest::Create(kernel); R_UNLESS(request != nullptr, ResultOutOfResource); SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Initialize the request. - request->Initialize(nullptr, address, size); + request->Initialize(kernel, nullptr, address, size); // Send the request. - R_RETURN(m_parent->OnRequest(request)); + R_RETURN(m_parent->OnRequest(kernel, request)); } -Result KClientSession::SendAsyncRequest(KEvent* event, uintptr_t address, size_t size) { +Result KClientSession::SendAsyncRequest(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size) { // Create a session request. - KSessionRequest* request = KSessionRequest::Create(m_kernel); + KSessionRequest* request = KSessionRequest::Create(kernel); R_UNLESS(request != nullptr, ResultOutOfResource); SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Initialize the request. - request->Initialize(event, address, size); + request->Initialize(kernel, event, address, size); // Send the request. - R_RETURN(m_parent->OnRequest(request)); + R_RETURN(m_parent->OnRequest(kernel, request)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index a39213e17f..876c3fc789 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,14 +29,14 @@ public: m_parent = parent; } - void Destroy() override; + void Destroy(KernelCore& kernel) override; KSession* GetParent() const { return m_parent; } - Result SendSyncRequest(uintptr_t address, size_t size); - Result SendAsyncRequest(KEvent* event, uintptr_t address, size_t size); + Result SendSyncRequest(KernelCore& kernel, uintptr_t address, size_t size); + Result SendAsyncRequest(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size); void OnServerClosed(); diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index 7454be55c9..aa8edce832 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,16 +22,15 @@ namespace Kernel { KCodeMemory::KCodeMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock(kernel) {} -Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddress addr, - size_t size) { +Result KCodeMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcessAddress addr, size_t size) { // Set members. - m_owner = GetCurrentProcessPointer(m_kernel); + m_owner = GetCurrentProcessPointer(kernel); // Get the owner page table. auto& page_table = m_owner->GetPageTable(); // Construct the page group. - m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); + m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); // Lock the memory. R_TRY(page_table.LockForCodeMemory(std::addressof(*m_page_group), addr, size)) @@ -39,7 +41,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres } // Set remaining tracking members. - m_owner->Open(); + m_owner->Open(kernel); m_address = addr; m_is_initialized = true; m_is_owner_mapped = false; @@ -49,7 +51,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres R_SUCCEED(); } -void KCodeMemory::Finalize() { +void KCodeMemory::Finalize(KernelCore& kernel) { // Unlock. if (!m_is_mapped && !m_is_owner_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; @@ -57,14 +59,14 @@ void KCodeMemory::Finalize() { } // Close the page group. - m_page_group->Close(); + m_page_group->Close(kernel); m_page_group->Finalize(); // Close our reference to our owner. - m_owner->Close(); + m_owner->Close(kernel); } -Result KCodeMemory::Map(KProcessAddress address, size_t size) { +Result KCodeMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -75,7 +77,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) { R_UNLESS(!m_is_mapped, ResultInvalidState); // Map the memory. - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( + R_TRY(GetCurrentProcess(kernel).GetPageTable().MapPageGroup( address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -84,7 +86,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) { R_SUCCEED(); } -Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { +Result KCodeMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -92,7 +94,7 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, + R_TRY(GetCurrentProcess(kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::CodeOut)); // Mark ourselves as unmapped. @@ -101,7 +103,7 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { R_SUCCEED(); } -Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm) { +Result KCodeMemory::MapToOwner(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission perm) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -135,7 +137,7 @@ Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::Memory R_SUCCEED(); } -Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) { +Result KCodeMemory::UnmapFromOwner(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 26fe6b3dc6..4f3aab6b4f 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -31,18 +34,18 @@ class KCodeMemory final public: explicit KCodeMemory(KernelCore& kernel); - Result Initialize(Core::DeviceMemory& device_memory, KProcessAddress address, size_t size); - void Finalize() override; + Result Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcessAddress address, size_t size); + void Finalize(KernelCore& kernel) override; - Result Map(KProcessAddress address, size_t size); - Result Unmap(KProcessAddress address, size_t size); - Result MapToOwner(KProcessAddress address, size_t size, Svc::MemoryPermission perm); - Result UnmapFromOwner(KProcessAddress address, size_t size); + Result Map(KernelCore& kernel, KProcessAddress address, size_t size); + Result Unmap(KernelCore& kernel, KProcessAddress address, size_t size); + Result MapToOwner(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission perm); + Result UnmapFromOwner(KernelCore& kernel, KProcessAddress address, size_t size); bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} KProcess* GetOwner() const override { return m_owner; diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 1a7431df07..3cf8b28e17 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -66,14 +66,15 @@ bool UpdateLockAtomic(KernelCore& kernel, u32* out, KProcessAddress address, u32 class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue { public: explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel) - : KThreadQueue(kernel) {} + : KThreadQueue(kernel) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -82,14 +83,15 @@ private: KConditionVariable::ThreadTree* m_tree; public: - explicit ThreadQueueImplForKConditionVariableWaitConditionVariable( - KernelCore& kernel, KConditionVariable::ThreadTree* t) - : KThreadQueue(kernel), m_tree(t) {} + explicit ThreadQueueImplForKConditionVariableWaitConditionVariable(KernelCore& kernel, KConditionVariable::ThreadTree* t) + : KThreadQueue(kernel) + , m_tree(t) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { - owner->RemoveWaiter(waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { + owner->RemoveWaiter(kernel, waiting_thread); } // If the thread is waiting on a condvar, remove it from the tree. @@ -99,14 +101,15 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; } // namespace KConditionVariable::KConditionVariable(Core::System& system) - : m_system{system}, m_kernel{system.Kernel()} {} + : m_system{system} +{} KConditionVariable::~KConditionVariable() = default; @@ -119,8 +122,7 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // Remove waiter thread. bool has_waiters{}; - KThread* const next_owner_thread = - owner_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); + KThread* const next_owner_thread = owner_thread->RemoveUserWaiterByKey(kernel, std::addressof(has_waiters), addr); // Determine the next tag. u32 next_value{}; @@ -144,15 +146,14 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // If necessary, signal the next owner thread. if (next_owner_thread != nullptr) { - next_owner_thread->EndWait(result); + next_owner_thread->EndWait(kernel, result); } R_RETURN(result); } } -Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, - u32 value) { +Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value) { KThread* cur_thread = GetCurrentThreadPointer(kernel); ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); @@ -173,30 +174,30 @@ Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KPr // Get the lock owner thread. owner_thread = GetCurrentProcess(kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle(handle) - .ReleasePointerUnsafe(); + .GetHandleTable() + .GetObjectWithoutPseudoHandle(kernel, handle) + .ReleasePointerUnsafe(); R_UNLESS(owner_thread != nullptr, ResultInvalidHandle); // Update the lock. cur_thread->SetUserAddressKey(addr, value); - owner_thread->AddWaiter(cur_thread); + owner_thread->AddWaiter(kernel, cur_thread); // Begin waiting. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(kernel, std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } // Close our reference to the owner thread, now that the wait is over. - owner_thread->Close(); + owner_thread->Close(kernel); // Get the wait result. R_RETURN(cur_thread->GetWaitResult()); } -void KConditionVariable::SignalImpl(KThread* thread) { +void KConditionVariable::SignalImpl(KernelCore& kernel, KThread* thread) { // Check pre-conditions. - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Update the tag. KProcessAddress address = thread->GetAddressKey(); @@ -211,35 +212,33 @@ void KConditionVariable::SignalImpl(KThread* thread) { // TODO(bunnei): We should call CanAccessAtomic(..) here. can_access = true; if (can_access) { - UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, - Svc::HandleWaitMask); + UpdateLockAtomic(kernel, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask); } } if (can_access) { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. - thread->EndWait(ResultSuccess); + thread->EndWait(kernel, ResultSuccess); } else { // Get the previous owner. - KThread* owner_thread = GetCurrentProcess(m_kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle( - static_cast(prev_tag & ~Svc::HandleWaitMask)) - .ReleasePointerUnsafe(); + KThread* owner_thread = GetCurrentProcess(kernel) + .GetHandleTable() + .GetObjectWithoutPseudoHandle(kernel, Handle(prev_tag & ~Svc::HandleWaitMask)) + .ReleasePointerUnsafe(); if (owner_thread) { // Add the thread as a waiter on the owner. - owner_thread->AddWaiter(thread); - owner_thread->Close(); + owner_thread->AddWaiter(kernel, thread); + owner_thread->Close(kernel); } else { // The lock was tagged with a thread that doesn't exist. - thread->EndWait(ResultInvalidState); + thread->EndWait(kernel, ResultInvalidState); } } } else { // If the address wasn't accessible, note so. - thread->EndWait(ResultInvalidCurrentMemory); + thread->EndWait(kernel, ResultInvalidCurrentMemory); } } @@ -247,17 +246,16 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(m_system.Kernel()); auto it = m_tree.nfind_key({cv_key, -1}); - while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && - (it->GetConditionVariableKey() == cv_key)) { + while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) { KThread* target_thread = std::addressof(*it); it = m_tree.erase(it); target_thread->ClearConditionVariable(); - this->SignalImpl(target_thread); + this->SignalImpl(m_system.Kernel(), target_thread); ++num_waiters; } @@ -265,20 +263,20 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // If we have no waiters, clear the has waiter flag. if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { constexpr u32 HasNoWaiterFlag = 0; - WriteToUser(m_kernel, cv_key, HasNoWaiterFlag); + WriteToUser(m_system.Kernel(), cv_key, HasNoWaiterFlag); } } } Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_kernel, + ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), cur_thread, timeout); + KScopedSchedulerLockAndSleep slp(m_system.Kernel(), std::addressof(timer), cur_thread, timeout); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -291,7 +289,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Remove waiter thread. bool has_waiters{}; KThread* next_owner_thread = - cur_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); + cur_thread->RemoveUserWaiterByKey(m_system.Kernel(), std::addressof(has_waiters), addr); // Update for the next owner thread. u32 next_value{}; @@ -303,18 +301,18 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti } // Wake up the next owner. - next_owner_thread->EndWait(ResultSuccess); + next_owner_thread->EndWait(m_system.Kernel(), ResultSuccess); } // Write to the cv key. { constexpr u32 HasWaiterFlag = 1; - WriteToUser(m_kernel, key, HasWaiterFlag); + WriteToUser(m_system.Kernel(), key, HasWaiterFlag); std::atomic_thread_fence(std::memory_order_seq_cst); } // Write the value to userspace. - if (!WriteToUser(m_kernel, addr, next_value)) { + if (!WriteToUser(m_system.Kernel(), addr, next_value)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -329,7 +327,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Begin waiting. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(m_system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h index 2620c8e39e..ca80de8837 100644 --- a/src/core/hle/kernel/k_condition_variable.h +++ b/src/core/hle/kernel/k_condition_variable.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,19 +29,17 @@ public: // Arbitration. static Result SignalToAddress(KernelCore& kernel, KProcessAddress addr); - static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, - u32 value); + static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value); // Condition variable. void Signal(u64 cv_key, s32 count); Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout); private: - void SignalImpl(KThread* thread); + void SignalImpl(KernelCore& kernel, KThread* thread); private: Core::System& m_system; - KernelCore& m_kernel; ThreadTree m_tree{}; }; diff --git a/src/core/hle/kernel/k_debug.h b/src/core/hle/kernel/k_debug.h index 2290e3bcab..92ff70df74 100644 --- a/src/core/hle/kernel/k_debug.h +++ b/src/core/hle/kernel/k_debug.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,7 +17,7 @@ class KDebug final : public KAutoObjectWithSlabHeapAndContainerOpen(); + m_owner->Open(kernel); } // Mark initialized. m_initialized = true; } -void KEvent::Finalize() { - KAutoObjectWithSlabHeapAndContainer::Finalize(); +void KEvent::Finalize(KernelCore& kernel) { + KAutoObjectWithSlabHeapAndContainer::Finalize(kernel); } -Result KEvent::Signal() { - KScopedSchedulerLock sl{m_kernel}; +Result KEvent::Signal(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; R_SUCCEED_IF(m_readable_event_destroyed); - return m_readable_event.Signal(); + return m_readable_event.Signal(kernel); } -Result KEvent::Clear() { - KScopedSchedulerLock sl{m_kernel}; +Result KEvent::Clear(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; R_SUCCEED_IF(m_readable_event_destroyed); - return m_readable_event.Clear(); + return m_readable_event.Clear(kernel); } -void KEvent::PostDestroy(uintptr_t arg) { +void KEvent::PostDestroy(KernelCore& kernel, uintptr_t arg) { // Release the event count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); if (owner != nullptr) { - owner->GetResourceLimit()->Release(LimitableResource::EventCountMax, 1); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::EventCountMax, 1); + owner->Close(kernel); } } diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index f522b0a84c..75b03efa69 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,9 +22,9 @@ public: explicit KEvent(KernelCore& kernel); ~KEvent() override; - void Initialize(KProcess* owner); + void Initialize(KernelCore& kernel, KProcess* owner); - void Finalize() override; + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_initialized; @@ -39,10 +42,10 @@ public: return m_readable_event; } - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); - Result Signal(); - Result Clear(); + Result Signal(KernelCore& kernel); + Result Clear(KernelCore& kernel); void OnReadableEventDestroyed() { m_readable_event_destroyed = true; diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 04ca235344..91d805fa79 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -6,28 +6,27 @@ #include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/kernel.h" namespace Kernel { -void KHandleTable::Finalize() { +void KHandleTable::Finalize(KernelCore& kernel) { // Get the table and clear our record of it. u16 saved_table_size = 0; { - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); std::swap(m_table_size, saved_table_size); } // Close and free all entries. - for (size_t i = 0; i < saved_table_size; i++) { - if (KAutoObject* obj = m_objects[i]; obj != nullptr) { - obj->Close(); - } - } + for (size_t i = 0; i < saved_table_size; i++) + if (KAutoObject* obj = m_objects[i]; obj != nullptr) + obj->Close(kernel); } -bool KHandleTable::Remove(Handle handle) { +bool KHandleTable::Remove(KernelCore& kernel, Handle handle) { // Don't allow removal of a pseudo-handle. if (Svc::IsPseudoHandle(handle)) [[unlikely]] { return false; @@ -42,7 +41,7 @@ bool KHandleTable::Remove(Handle handle) { // Find the object and free the entry. KAutoObject* obj = nullptr; { - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); if (this->IsValidHandle(handle)) [[likely]] { @@ -56,13 +55,13 @@ bool KHandleTable::Remove(Handle handle) { } // Close the object. - m_kernel.UnregisterInUseObject(obj); - obj->Close(); + kernel.UnregisterInUseObject(obj); + obj->Close(kernel); return true; } -Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { - KScopedDisableDispatch dd{m_kernel}; +Result KHandleTable::Add(KernelCore& kernel, Handle* out_handle, KAutoObject* obj) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -76,7 +75,7 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { m_entry_infos[index].linear_id = linear_id; m_objects[index] = obj; - obj->Open(); + obj->Open(kernel); *out_handle = EncodeHandle(static_cast(index), linear_id); } @@ -84,24 +83,22 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { R_SUCCEED(); } -KScopedAutoObject KHandleTable::GetObjectForIpc(Handle handle, - KThread* cur_thread) const { +KScopedAutoObject KHandleTable::GetObjectForIpc(KernelCore& kernel, Handle handle, KThread* cur_thread) const { // Handle pseudo-handles. ASSERT(cur_thread != nullptr); if (handle == Svc::PseudoHandle::CurrentProcess) { auto* const cur_process = cur_thread->GetOwnerProcess(); ASSERT(cur_process != nullptr); - return cur_process; + return {kernel, cur_process}; } if (handle == Svc::PseudoHandle::CurrentThread) { - return cur_thread; + return {kernel, cur_thread}; } - - return GetObjectForIpcWithoutPseudoHandle(handle); + return GetObjectForIpcWithoutPseudoHandle(kernel, handle); } -Result KHandleTable::Reserve(Handle* out_handle) { - KScopedDisableDispatch dd{m_kernel}; +Result KHandleTable::Reserve(KernelCore& kernel, Handle* out_handle) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -111,8 +108,8 @@ Result KHandleTable::Reserve(Handle* out_handle) { R_SUCCEED(); } -void KHandleTable::Unreserve(Handle handle) { - KScopedDisableDispatch dd{m_kernel}; +void KHandleTable::Unreserve(KernelCore& kernel, Handle handle) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -130,8 +127,8 @@ void KHandleTable::Unreserve(Handle handle) { } } -void KHandleTable::Register(Handle handle, KAutoObject* obj) { - KScopedDisableDispatch dd{m_kernel}; +void KHandleTable::Register(KernelCore& kernel, Handle handle, KAutoObject* obj) { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -149,7 +146,7 @@ void KHandleTable::Register(Handle handle, KAutoObject* obj) { m_entry_infos[index].linear_id = static_cast(linear_id); m_objects[index] = obj; - obj->Open(); + obj->Open(kernel); } } diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 731a5284dc..0704fd56ef 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -31,14 +31,14 @@ public: static constexpr size_t MaxTableSize = 1024; public: - explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} + explicit KHandleTable(KernelCore& kernel) {} - Result Initialize(s32 size) { + Result Initialize(KernelCore& kernel, s32 size) { // Check that the table size is valid. R_UNLESS(size <= static_cast(MaxTableSize), ResultOutOfMemory); // Lock. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); // Initialize all fields. @@ -68,76 +68,72 @@ public: return m_max_count; } - void Finalize(); - bool Remove(Handle handle); + void Finalize(KernelCore& kernel); + bool Remove(KernelCore& kernel, Handle handle); template - KScopedAutoObject GetObjectWithoutPseudoHandle(Handle handle) const { + KScopedAutoObject GetObjectWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); if constexpr (std::is_same_v) { - return this->GetObjectImpl(handle); + return {kernel, this->GetObjectImpl(handle)}; } else { if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) [[likely]] { - return obj->DynamicCast(); + return {kernel, obj->DynamicCast()}; } else { - return nullptr; + return {kernel, nullptr}; } } } template - KScopedAutoObject GetObject(Handle handle) const { + KScopedAutoObject GetObject(KernelCore& kernel, Handle handle) const { // Handle pseudo-handles. if constexpr (std::derived_from) { if (handle == Svc::PseudoHandle::CurrentProcess) { - auto* const cur_process = GetCurrentProcessPointer(m_kernel); + auto* const cur_process = GetCurrentProcessPointer(kernel); ASSERT(cur_process != nullptr); - return cur_process; + return {kernel, cur_process}; } } else if constexpr (std::derived_from) { if (handle == Svc::PseudoHandle::CurrentThread) { - auto* const cur_thread = GetCurrentThreadPointer(m_kernel); + auto* const cur_thread = GetCurrentThreadPointer(kernel); ASSERT(cur_thread != nullptr); - return cur_thread; + return {kernel, cur_thread}; } } - - return this->template GetObjectWithoutPseudoHandle(handle); + return this->template GetObjectWithoutPseudoHandle(kernel, handle); } - KScopedAutoObject GetObjectForIpcWithoutPseudoHandle(Handle handle) const { + KScopedAutoObject GetObjectForIpcWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; + KScopedSpinLock lk(m_lock); + return {kernel, this->GetObjectImpl(handle)}; + } + KScopedAutoObject GetObjectForIpc(KernelCore& kernel, Handle handle, KThread* cur_thread) const; + KScopedAutoObject GetObjectByIndex(KernelCore& kernel, Handle* out_handle, size_t index) const { + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); - return this->GetObjectImpl(handle); + return {kernel, this->GetObjectByIndexImpl(out_handle, index)}; } - KScopedAutoObject GetObjectForIpc(Handle handle, KThread* cur_thread) const; + Result Reserve(KernelCore& kernel, Handle* out_handle); + void Unreserve(KernelCore& kernel, Handle handle); - KScopedAutoObject GetObjectByIndex(Handle* out_handle, size_t index) const { - KScopedDisableDispatch dd{m_kernel}; - KScopedSpinLock lk(m_lock); - - return this->GetObjectByIndexImpl(out_handle, index); - } - - Result Reserve(Handle* out_handle); - void Unreserve(Handle handle); - - Result Add(Handle* out_handle, KAutoObject* obj); - void Register(Handle handle, KAutoObject* obj); + Result Add(KernelCore& kernel, Handle* out_handle, KAutoObject* obj); + void Register(KernelCore& kernel, Handle handle, KAutoObject* obj); template - bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const { + bool GetMultipleObjects(KernelCore& kernel, T** out, const Handle* handles, size_t num_handles) const { // Try to convert and open all the handles. size_t num_opened; { // Lock the table. - KScopedDisableDispatch dd{m_kernel}; + KScopedDisableDispatch dd{kernel}; KScopedSpinLock lk(m_lock); for (num_opened = 0; num_opened < num_handles; num_opened++) { // Get the current handle. @@ -150,14 +146,14 @@ public: } // Cast the current object to the desired type. - T* cur_t = cur_object->DynamicCast(); - if (cur_t == nullptr) [[unlikely]] { + T* cur_thread = cur_object->DynamicCast(); + if (cur_thread == nullptr) [[unlikely]] { break; } // Open a reference to the current object. - cur_t->Open(); - out[num_opened] = cur_t; + cur_thread->Open(kernel); + out[num_opened] = cur_thread; } } @@ -168,7 +164,7 @@ public: // If we didn't convert entry object, close the ones we opened. for (size_t i = 0; i < num_opened; i++) { - out[i]->Close(); + out[i]->Close(kernel); } return false; @@ -177,13 +173,9 @@ public: private: s32 AllocateEntry() { ASSERT(m_count < m_table_size); - const auto index = m_free_head_index; - m_free_head_index = m_entry_infos[index].GetNextFreeIndex(); - m_max_count = (std::max)(m_max_count, ++m_count); - return index; } @@ -302,7 +294,6 @@ private: }; private: - KernelCore& m_kernel; std::array m_entry_infos{}; std::array m_objects{}; mutable KSpinLock m_lock; diff --git a/src/core/hle/kernel/k_hardware_timer_base.h b/src/core/hle/kernel/k_hardware_timer_base.h index 6318b35bdd..75a4a54763 100644 --- a/src/core/hle/kernel/k_hardware_timer_base.h +++ b/src/core/hle/kernel/k_hardware_timer_base.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -45,7 +48,7 @@ protected: this->RemoveTaskFromTree(task); // Handle the task. - task->OnTimer(); + task->OnTimer(m_kernel); } } diff --git a/src/core/hle/kernel/k_interrupt_manager.cpp b/src/core/hle/kernel/k_interrupt_manager.cpp index 22d79569a5..9bd182fd9b 100644 --- a/src/core/hle/kernel/k_interrupt_manager.cpp +++ b/src/core/hle/kernel/k_interrupt_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,19 +21,19 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) { if (auto* process = GetCurrentProcessPointer(kernel); process) { // If the user disable count is set, we may need to pin the current thread. - if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) { + if (current_thread.GetUserDisableCount(kernel) && !process->GetPinnedThread(core_id)) { KScopedSchedulerLock sl{kernel}; // Pin the current thread. - process->PinCurrentThread(); + process->PinCurrentThread(kernel); // Set the interrupt flag for the thread. - GetCurrentThread(kernel).SetInterruptFlag(); + GetCurrentThread(kernel).SetInterruptFlag(kernel); } } // Request interrupt scheduling. - kernel.CurrentScheduler()->RequestScheduleOnInterrupt(); + kernel.CurrentScheduler()->RequestScheduleOnInterrupt(kernel); } void SendInterProcessorInterrupt(KernelCore& kernel, u64 core_mask) { diff --git a/src/core/hle/kernel/k_light_client_session.cpp b/src/core/hle/kernel/k_light_client_session.cpp index 8ce3e1ae49..23f77deffd 100644 --- a/src/core/hle/kernel/k_light_client_session.cpp +++ b/src/core/hle/kernel/k_light_client_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,21 +14,21 @@ KLightClientSession::KLightClientSession(KernelCore& kernel) : KAutoObject(kerne KLightClientSession::~KLightClientSession() = default; -void KLightClientSession::Destroy() { - m_parent->OnClientClosed(); +void KLightClientSession::Destroy(KernelCore& kernel) { + m_parent->OnClientClosed(kernel); } -void KLightClientSession::OnServerClosed() {} +void KLightClientSession::OnServerClosed(KernelCore& kernel) {} -Result KLightClientSession::SendSyncRequest(u32* data) { +Result KLightClientSession::SendSyncRequest(KernelCore& kernel, u32* data) { // Get the request thread. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // Set the light data. cur_thread->SetLightSessionData(data); // Send the request. - R_RETURN(m_parent->OnRequest(cur_thread)); + R_RETURN(m_parent->OnRequest(kernel, cur_thread)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_client_session.h b/src/core/hle/kernel/k_light_client_session.h index 881a15cbda..c0f48c295e 100644 --- a/src/core/hle/kernel/k_light_client_session.h +++ b/src/core/hle/kernel/k_light_client_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,15 +25,15 @@ public: m_parent = parent; } - virtual void Destroy() override; + virtual void Destroy(KernelCore& kernel) override; const KLightSession* GetParent() const { return m_parent; } - Result SendSyncRequest(u32* data); + Result SendSyncRequest(KernelCore& kernel, u32* data); - void OnServerClosed(); + void OnServerClosed(KernelCore& kernel); private: KLightSession* m_parent; diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp index 6d5a815aab..2c873162fb 100644 --- a/src/core/hle/kernel/k_light_condition_variable.cpp +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,11 +16,13 @@ namespace { class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { public: - ThreadQueueImplForKLightConditionVariable(KernelCore& kernel, KThread::WaiterList* wl, - bool term) - : KThreadQueue(kernel), m_wait_list(wl), m_allow_terminating_thread(term) {} + ThreadQueueImplForKLightConditionVariable(KernelCore& kernel, KThread::WaiterList* wl, bool term) + : KThreadQueue(kernel) + , m_wait_list(wl) + , m_allow_terminating_thread(term) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Only process waits if we're allowed to. if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { return; @@ -27,7 +32,7 @@ public: m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -61,7 +66,7 @@ void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_ter // Begin waiting. wait_queue.SetHardwareTimer(timer); - owner->BeginWait(std::addressof(wait_queue)); + owner->BeginWait(m_kernel, std::addressof(wait_queue)); } // Re-acquire the lock. @@ -73,7 +78,7 @@ void KLightConditionVariable::Broadcast() { // Signal all threads. for (auto it = m_wait_list.begin(); it != m_wait_list.end(); it = m_wait_list.erase(it)) { - it->EndWait(ResultSuccess); + it->EndWait(m_kernel, ResultSuccess); } } diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp index e87ee8b652..614e056d13 100644 --- a/src/core/hle/kernel/k_light_lock.cpp +++ b/src/core/hle/kernel/k_light_lock.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,29 +18,25 @@ class ThreadQueueImplForKLightLock final : public KThreadQueue { public: explicit ThreadQueueImplForKLightLock(KernelCore& kernel) : KThreadQueue(kernel) {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { - owner->RemoveWaiter(waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { + owner->RemoveWaiter(kernel, waiting_thread); } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; } // namespace void KLightLock::Lock() { - const uintptr_t cur_thread = reinterpret_cast(GetCurrentThreadPointer(m_kernel)); - + const uintptr_t cur_thread = uintptr_t(GetCurrentThreadPointer(m_kernel)); while (true) { uintptr_t old_tag = m_tag.load(std::memory_order_relaxed); - - while (!m_tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), - std::memory_order_acquire)) { - } - + while (!m_tag.compare_exchange_weak(old_tag, (old_tag == 0) ? cur_thread : (old_tag | 1), std::memory_order_acquire)) + ; if (old_tag == 0 || this->LockSlowPath(old_tag | 1, cur_thread)) { break; } @@ -69,13 +68,13 @@ bool KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) { // Add the current thread as a waiter on the owner. KThread* owner_thread = reinterpret_cast(_owner & ~1ULL); cur_thread->SetKernelAddressKey(reinterpret_cast(std::addressof(m_tag))); - owner_thread->AddWaiter(cur_thread); + owner_thread->AddWaiter(m_kernel, cur_thread); // Begin waiting to hold the lock. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(m_kernel, std::addressof(wait_queue)); if (owner_thread->IsSuspended()) { - owner_thread->ContinueIfHasKernelWaiters(); + owner_thread->ContinueIfHasKernelWaiters(m_kernel); } } @@ -91,26 +90,25 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { // Get the next owner. bool has_waiters; - KThread* next_owner = owner_thread->RemoveKernelWaiterByKey( - std::addressof(has_waiters), reinterpret_cast(std::addressof(m_tag))); + KThread* next_owner = owner_thread->RemoveKernelWaiterByKey(m_kernel, + std::addressof(has_waiters), uintptr_t(std::addressof(m_tag))); // Pass the lock to the next owner. uintptr_t next_tag = 0; if (next_owner != nullptr) { - next_tag = - reinterpret_cast(next_owner) | static_cast(has_waiters); + next_tag = uintptr_t(next_owner) | uintptr_t(has_waiters); - next_owner->EndWait(ResultSuccess); + next_owner->EndWait(m_kernel, ResultSuccess); if (next_owner->IsSuspended()) { - next_owner->ContinueIfHasKernelWaiters(); + next_owner->ContinueIfHasKernelWaiters(m_kernel); } } // We may have unsuspended in the process of acquiring the lock, so we'll re-suspend now if // so. if (owner_thread->IsSuspended()) { - owner_thread->TrySuspend(); + owner_thread->TrySuspend(m_kernel); } // Write the new tag value. @@ -119,8 +117,7 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) { } bool KLightLock::IsLockedByCurrentThread() const { - return (m_tag.load() | 1ULL) == - (reinterpret_cast(GetCurrentThreadPointer(m_kernel)) | 1ULL); + return (m_tag.load() | 1ULL) == (uintptr_t(GetCurrentThreadPointer(m_kernel)) | 1ULL); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_server_session.cpp b/src/core/hle/kernel/k_light_server_session.cpp index a4d2b11231..6344f418ed 100644 --- a/src/core/hle/kernel/k_light_server_session.cpp +++ b/src/core/hle/kernel/k_light_server_session.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -24,21 +24,20 @@ public: ThreadQueueImplForKLightServerSessionRequest(KernelCore& kernel, KThread::WaiterList* wl) : KThreadQueue(kernel), m_wait_list(wl) {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Remove the thread from our wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, - bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread from our wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -48,9 +47,11 @@ private: public: ThreadQueueImplForKLightServerSessionReceive(KernelCore& kernel, KThread** st) - : KThreadQueue(kernel), m_server_thread(st) {} + : KThreadQueue(kernel) + , m_server_thread(st) + {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Clear the server thread. *m_server_thread = nullptr; @@ -58,11 +59,10 @@ public: waiting_thread->ClearCancellable(); // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, - bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Clear the server thread. *m_server_thread = nullptr; @@ -70,7 +70,7 @@ public: waiting_thread->ClearCancellable(); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -79,24 +79,21 @@ public: KLightServerSession::KLightServerSession(KernelCore& kernel) : KAutoObject(kernel) {} KLightServerSession::~KLightServerSession() = default; -void KLightServerSession::Destroy() { - this->CleanupRequests(); - - m_parent->OnServerClosed(); +void KLightServerSession::Destroy(KernelCore& kernel) { + this->CleanupRequests(kernel); + m_parent->OnServerClosed(kernel); } -void KLightServerSession::OnClientClosed() { - this->CleanupRequests(); +void KLightServerSession::OnClientClosed(KernelCore& kernel) { + this->CleanupRequests(kernel); } -Result KLightServerSession::OnRequest(KThread* request_thread) { - ThreadQueueImplForKLightServerSessionRequest wait_queue(m_kernel, - std::addressof(m_request_list)); - +Result KLightServerSession::OnRequest(KernelCore& kernel, KThread* request_thread) { + ThreadQueueImplForKLightServerSessionRequest wait_queue(kernel, std::addressof(m_request_list)); // Send the request. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that the server isn't closed. R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); @@ -109,11 +106,11 @@ Result KLightServerSession::OnRequest(KThread* request_thread) { // Begin waiting on the request. request_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - request_thread->BeginWait(std::addressof(wait_queue)); + request_thread->BeginWait(kernel, std::addressof(wait_queue)); // If we have a server thread, end its wait. if (m_server_thread != nullptr) { - m_server_thread->EndWait(ResultSuccess); + m_server_thread->EndWait(kernel, ResultSuccess); } } @@ -123,13 +120,13 @@ Result KLightServerSession::OnRequest(KThread* request_thread) { R_RETURN(request_thread->GetWaitResult()); } -Result KLightServerSession::ReplyAndReceive(u32* data) { +Result KLightServerSession::ReplyAndReceive(KernelCore& kernel, u32* data) { // Set the server context. - GetCurrentThread(m_kernel).SetLightSessionData(data); + GetCurrentThread(kernel).SetLightSessionData(data); // Reply, if we need to. if (data[0] & KLightSession::ReplyFlag) { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we're open. R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed); @@ -139,17 +136,16 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { R_UNLESS(m_current_request != nullptr, ResultInvalidState); // Check that the server thread id is correct. - R_UNLESS(m_server_thread_id == GetCurrentThread(m_kernel).GetId(), ResultInvalidState); + R_UNLESS(m_server_thread_id == GetCurrentThread(kernel).GetId(), ResultInvalidState); // If we can reply, do so. if (!m_current_request->IsTerminationRequested()) { - std::memcpy(m_current_request->GetLightSessionData(), - GetCurrentThread(m_kernel).GetLightSessionData(), KLightSession::DataSize); - m_current_request->EndWait(ResultSuccess); + std::memcpy(m_current_request->GetLightSessionData(), GetCurrentThread(kernel).GetLightSessionData(), KLightSession::DataSize); + m_current_request->EndWait(kernel, ResultSuccess); } // Close our current request. - m_current_request->Close(); + m_current_request->Close(kernel); // Clear our current request. m_current_request = nullptr; @@ -157,14 +153,13 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { } // Create the wait queue for our receive. - ThreadQueueImplForKLightServerSessionReceive wait_queue(m_kernel, - std::addressof(m_server_thread)); + ThreadQueueImplForKLightServerSessionReceive wait_queue(kernel, std::addressof(m_server_thread)); // Receive. while (true) { // Try to receive a request. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we aren't already receiving. R_UNLESS(m_server_thread == nullptr, ResultInvalidState); @@ -175,20 +170,19 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); // Check that we're not terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), - ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // If we have a request available, use it. if (auto head = m_request_list.begin(); head != m_request_list.end()) { // Set our current request. m_current_request = std::addressof(*head); - m_current_request->Open(); + m_current_request->Open(kernel); // Set our server thread id. - m_server_thread_id = GetCurrentThread(m_kernel).GetId(); + m_server_thread_id = GetCurrentThread(kernel).GetId(); // Copy the client request data. - std::memcpy(GetCurrentThread(m_kernel).GetLightSessionData(), + std::memcpy(GetCurrentThread(kernel).GetLightSessionData(), m_current_request->GetLightSessionData(), KLightSession::DataSize); // We successfully received. @@ -198,51 +192,51 @@ Result KLightServerSession::ReplyAndReceive(u32* data) { // We need to wait for a request to come in. // Check if we were cancelled. - if (GetCurrentThread(m_kernel).IsWaitCancelled()) { - GetCurrentThread(m_kernel).ClearWaitCancelled(); + if (GetCurrentThread(kernel).IsWaitCancelled()) { + GetCurrentThread(kernel).ClearWaitCancelled(); R_THROW(ResultCancelled); } // Mark ourselves as cancellable. - GetCurrentThread(m_kernel).SetCancellable(); + GetCurrentThread(kernel).SetCancellable(); // Wait for a request to come in. - m_server_thread = GetCurrentThreadPointer(m_kernel); - GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + m_server_thread = GetCurrentThreadPointer(kernel); + GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } // We waited to receive a request; if our wait failed, return the failing result. - R_TRY(GetCurrentThread(m_kernel).GetWaitResult()); + R_TRY(GetCurrentThread(kernel).GetWaitResult()); } } -void KLightServerSession::CleanupRequests() { +void KLightServerSession::CleanupRequests(KernelCore& kernel) { // Cleanup all pending requests. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Handle the current request. if (m_current_request != nullptr) { // Reply to the current request. if (!m_current_request->IsTerminationRequested()) { - m_current_request->EndWait(ResultSessionClosed); + m_current_request->EndWait(kernel, ResultSessionClosed); } // Clear our current request. - m_current_request->Close(); + m_current_request->Close(kernel); m_current_request = nullptr; m_server_thread_id = InvalidThreadId; } // Reply to all other requests. for (auto& thread : m_request_list) { - thread.EndWait(ResultSessionClosed); + thread.EndWait(kernel, ResultSessionClosed); } // Wait up our server thread, if we have one. if (m_server_thread != nullptr) { - m_server_thread->EndWait(ResultSessionClosed); + m_server_thread->EndWait(kernel, ResultSessionClosed); } } } diff --git a/src/core/hle/kernel/k_light_server_session.h b/src/core/hle/kernel/k_light_server_session.h index 67db3f76ca..5849a41c7b 100644 --- a/src/core/hle/kernel/k_light_server_session.h +++ b/src/core/hle/kernel/k_light_server_session.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -34,19 +34,19 @@ public: m_parent = parent; } - virtual void Destroy() override; + virtual void Destroy(KernelCore& kernel) override; constexpr const KLightSession* GetParent() const { return m_parent; } - Result OnRequest(KThread* request_thread); - Result ReplyAndReceive(u32* data); + Result OnRequest(KernelCore& kernel, KThread* request_thread); + Result ReplyAndReceive(KernelCore& kernel, u32* data); - void OnClientClosed(); + void OnClientClosed(KernelCore& kernel); private: - void CleanupRequests(); + void CleanupRequests(KernelCore& kernel); }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_session.cpp b/src/core/hle/kernel/k_light_session.cpp index d8b1e69582..add72d404b 100644 --- a/src/core/hle/kernel/k_light_session.cpp +++ b/src/core/hle/kernel/k_light_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,15 +13,18 @@ namespace Kernel { KLightSession::KLightSession(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer(kernel), m_server(kernel), m_client(kernel) {} + : KAutoObjectWithSlabHeapAndContainer(kernel) + , m_server(kernel) + , m_client(kernel) +{} KLightSession::~KLightSession() = default; -void KLightSession::Initialize(KClientPort* client_port, uintptr_t name) { +void KLightSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name) { // Increment reference count. // Because reference count is one on creation, this will result // in a reference count of two. Thus, when both server and client are closed // this object will be destroyed. - this->Open(); + this->Open(kernel); // Create our sub sessions. KAutoObject::Create(std::addressof(m_server)); @@ -33,49 +39,47 @@ void KLightSession::Initialize(KClientPort* client_port, uintptr_t name) { m_name = name; // Set our owner process. - m_process = GetCurrentProcessPointer(m_kernel); - m_process->Open(); + m_process = GetCurrentProcessPointer(kernel); + m_process->Open(kernel); // Set our port. m_port = client_port; if (m_port != nullptr) { - m_port->Open(); + m_port->Open(kernel); } // Mark initialized. m_initialized = true; } -void KLightSession::Finalize() { +void KLightSession::Finalize(KernelCore& kernel) { if (m_port != nullptr) { - m_port->OnSessionFinalized(); - m_port->Close(); + m_port->OnSessionFinalized(kernel); + m_port->Close(kernel); } } -void KLightSession::OnServerClosed() { +void KLightSession::OnServerClosed(KernelCore& kernel) { if (m_state == State::Normal) { m_state = State::ServerClosed; - m_client.OnServerClosed(); + m_client.OnServerClosed(kernel); } - - this->Close(); + this->Close(kernel); } -void KLightSession::OnClientClosed() { +void KLightSession::OnClientClosed(KernelCore& kernel) { if (m_state == State::Normal) { m_state = State::ClientClosed; - m_server.OnClientClosed(); + m_server.OnClientClosed(kernel); } - - this->Close(); + this->Close(kernel); } -void KLightSession::PostDestroy(uintptr_t arg) { +void KLightSession::PostDestroy(KernelCore& kernel, uintptr_t arg) { // Release the session count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); - owner->ReleaseResource(Svc::LimitableResource::SessionCountMax, 1); - owner->Close(); + owner->ReleaseResource(kernel, Svc::LimitableResource::SessionCountMax, 1); + owner->Close(kernel); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_light_session.h b/src/core/hle/kernel/k_light_session.h index f78d8e6899..5bbb942b35 100644 --- a/src/core/hle/kernel/k_light_session.h +++ b/src/core/hle/kernel/k_light_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -43,20 +46,20 @@ public: explicit KLightSession(KernelCore& kernel); ~KLightSession(); - void Initialize(KClientPort* client_port, uintptr_t name); - void Finalize() override; + void Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name); + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_initialized; } uintptr_t GetPostDestroyArgument() const override { - return reinterpret_cast(m_process); + return uintptr_t(m_process); } - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); - void OnServerClosed(); - void OnClientClosed(); + void OnServerClosed(KernelCore& kernel); + void OnClientClosed(KernelCore& kernel); bool IsServerClosed() const { return m_state != State::Normal; @@ -65,8 +68,8 @@ public: return m_state != State::Normal; } - Result OnRequest(KThread* request_thread) { - R_RETURN(m_server.OnRequest(request_thread)); + Result OnRequest(KernelCore& kernel, KThread* request_thread) { + R_RETURN(m_server.OnRequest(kernel, request_thread)); } KLightClientSession& GetClientSession() { diff --git a/src/core/hle/kernel/k_object_name.cpp b/src/core/hle/kernel/k_object_name.cpp index df3a1c4c56..da0b04b450 100644 --- a/src/core/hle/kernel/k_object_name.cpp +++ b/src/core/hle/kernel/k_object_name.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,14 +11,14 @@ namespace Kernel { KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {} KObjectNameGlobalData::~KObjectNameGlobalData() = default; -void KObjectName::Initialize(KAutoObject* obj, const char* name) { +void KObjectName::Initialize(KernelCore& kernel, KAutoObject* obj, const char* name) { // Set member variables. m_object = obj; std::strncpy(m_name.data(), name, sizeof(m_name) - 1); m_name[sizeof(m_name) - 1] = '\x00'; // Open a reference to the object we hold. - m_object->Open(); + m_object->Open(kernel); } bool KObjectName::MatchesName(const char* name) const { @@ -28,7 +31,7 @@ Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char R_UNLESS(new_name != nullptr, ResultOutOfResource); // Initialize the new name. - new_name->Initialize(obj, name); + new_name->Initialize(kernel, obj, name); // Check if there's an existing name. { @@ -47,7 +50,7 @@ Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char } // The object already exists, which is an error condition. Perform cleanup. - obj->Close(); + obj->Close(kernel); KObjectName::Free(kernel, new_name); R_THROW(ResultInvalidState); } @@ -63,7 +66,7 @@ Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* com for (auto& name : gd.GetObjectList()) { if (name.MatchesName(compare_name) && obj == name.GetObject()) { // We found a match, clean up its resources. - obj->Close(); + obj->Close(kernel); gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name)); KObjectName::Free(kernel, std::addressof(name)); R_SUCCEED(); @@ -89,14 +92,12 @@ KScopedAutoObject KObjectName::FindImpl(KernelCore& kernel, const c KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()}; // Try to find a matching object in the global list. - for (const auto& name : gd.GetObjectList()) { - if (name.MatchesName(compare_name)) { - return name.GetObject(); - } - } + for (const auto& name : gd.GetObjectList()) + if (name.MatchesName(compare_name)) + return {kernel, name.GetObject()}; // There's no matching entry in the list. - return nullptr; + return {kernel, nullptr}; } } // namespace Kernel diff --git a/src/core/hle/kernel/k_object_name.h b/src/core/hle/kernel/k_object_name.h index a8876fe370..2ae9edcf51 100644 --- a/src/core/hle/kernel/k_object_name.h +++ b/src/core/hle/kernel/k_object_name.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,7 +44,7 @@ public: R_UNLESS(derived != nullptr, ResultNotFound); // Check that the object is closed. - R_UNLESS(derived->IsServerClosed(), ResultInvalidState); + R_UNLESS(derived->IsServerClosed(kernel), ResultInvalidState); R_RETURN(Delete(kernel, obj.GetPointerUnsafe(), name)); } @@ -49,13 +52,13 @@ public: template requires(std::derived_from) static KScopedAutoObject Find(KernelCore& kernel, const char* name) { - return Find(kernel, name); + return {kernel, static_cast(Find(kernel, name).GetPointerUnsafe())}; } private: static KScopedAutoObject FindImpl(KernelCore& kernel, const char* name); - void Initialize(KAutoObject* obj, const char* name); + void Initialize(KernelCore& kernel, KAutoObject* obj, const char* name); bool MatchesName(const char* name) const; KAutoObject* GetObject() const { diff --git a/src/core/hle/kernel/k_page_group.cpp b/src/core/hle/kernel/k_page_group.cpp index d8c644a336..ed7f219718 100644 --- a/src/core/hle/kernel/k_page_group.cpp +++ b/src/core/hle/kernel/k_page_group.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,8 +24,8 @@ void KPageGroup::Finalize() { m_last_block = nullptr; } -void KPageGroup::CloseAndReset() { - auto& mm = m_kernel.MemoryManager(); +void KPageGroup::CloseAndReset(KernelCore& kernel) { + auto& mm = kernel.MemoryManager(); KBlockInfo* cur = m_first_block; while (cur != nullptr) { @@ -76,28 +79,22 @@ Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) { R_SUCCEED(); } -void KPageGroup::Open() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { +void KPageGroup::Open(KernelCore& kernel) const { + auto& mm = kernel.MemoryManager(); + for (const auto& it : *this) mm.Open(it.GetAddress(), it.GetNumPages()); - } } -void KPageGroup::OpenFirst() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { +void KPageGroup::OpenFirst(KernelCore& kernel) const { + auto& mm = kernel.MemoryManager(); + for (const auto& it : *this) mm.OpenFirst(it.GetAddress(), it.GetNumPages()); - } } -void KPageGroup::Close() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { +void KPageGroup::Close(KernelCore& kernel) const { + auto& mm = kernel.MemoryManager(); + for (const auto& it : *this) mm.Close(it.GetAddress(), it.GetNumPages()); - } } bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const { diff --git a/src/core/hle/kernel/k_page_group.h b/src/core/hle/kernel/k_page_group.h index de9d63a8d2..60a6faa2fd 100644 --- a/src/core/hle/kernel/k_page_group.h +++ b/src/core/hle/kernel/k_page_group.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -139,12 +142,12 @@ public: }; explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m) - : m_kernel{kernel}, m_manager{m} {} + : m_manager{m} {} ~KPageGroup() { this->Finalize(); } - void CloseAndReset(); + void CloseAndReset(KernelCore& kernel); void Finalize(); Iterator begin() const { @@ -158,9 +161,9 @@ public: } Result AddBlock(KPhysicalAddress addr, size_t num_pages); - void Open() const; - void OpenFirst() const; - void Close() const; + void Open(KernelCore& kernel) const; + void OpenFirst(KernelCore& kernel) const; + void Close(KernelCore& kernel) const; size_t GetNumPages() const; @@ -175,7 +178,6 @@ public: } private: - KernelCore& m_kernel; KBlockInfo* m_first_block{}; KBlockInfo* m_last_block{}; KBlockInfoManager* m_manager{}; @@ -183,21 +185,24 @@ private: class KScopedPageGroup { public: - explicit KScopedPageGroup(const KPageGroup* gp, bool not_first = true) : m_pg(gp) { + explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup* gp, bool not_first = true) + : m_kernel{kernel} + , m_pg{gp} + { if (m_pg) { if (not_first) { - m_pg->Open(); + m_pg->Open(kernel); } else { - m_pg->OpenFirst(); + m_pg->OpenFirst(kernel); } } } - explicit KScopedPageGroup(const KPageGroup& gp, bool not_first = true) - : KScopedPageGroup(std::addressof(gp), not_first) {} + explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup& gp, bool not_first = true) + : KScopedPageGroup(kernel, std::addressof(gp), not_first) {} + ~KScopedPageGroup() { - if (m_pg) { - m_pg->Close(); - } + if (m_pg) + m_pg->Close(m_kernel); } void CancelClose() { @@ -205,6 +210,7 @@ public: } private: + KernelCore& m_kernel; const KPageGroup* m_pg{}; }; diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 3696f9f251..a727355a9f 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -127,22 +127,22 @@ constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission p } // namespace -void KPageTableBase::MemoryRange::Open() { +void KPageTableBase::MemoryRange::Open(KernelCore& kernel) { // If the range contains heap pages, open them. if (this->IsHeap()) { - m_kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); + kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); } } -void KPageTableBase::MemoryRange::Close() { +void KPageTableBase::MemoryRange::Close(KernelCore& kernel) { // If the range contains heap pages, close them. if (this->IsHeap()) { - m_kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); + kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); } } KPageTableBase::KPageTableBase(KernelCore& kernel) - : m_kernel(kernel), m_system(kernel.System()), m_general_lock(kernel), + : m_system(kernel.System()), m_general_lock(kernel), m_map_physical_memory_lock(kernel), m_device_map_lock(kernel) {} KPageTableBase::~KPageTableBase() = default; @@ -177,9 +177,9 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start m_mapped_ipc_server_memory = 0; m_memory_block_slab_manager = - m_kernel.GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); - m_block_info_manager = m_kernel.GetSystemSystemResource().GetBlockInfoManagerPointer(); - m_resource_limit = m_kernel.GetSystemResourceLimit(); + m_system.Kernel().GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); + m_block_info_manager = m_system.Kernel().GetSystemSystemResource().GetBlockInfoManagerPointer(); + m_resource_limit = m_system.Kernel().GetSystemResourceLimit(); m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool::System, KMemoryManager::Direction::FromFront); @@ -469,11 +469,11 @@ void KPageTableBase::Finalize() { } // Get physical pages. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); this->MakePageGroup(pg, addr, size / PageSize); // Free the pages. - pg.CloseAndReset(); + pg.CloseAndReset(m_system.Kernel()); }; // Finalize memory blocks. @@ -490,16 +490,16 @@ void KPageTableBase::Finalize() { // Release any insecure mapped memory. if (m_mapped_insecure_memory) { if (auto* const insecure_resource_limit = - KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); + KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); insecure_resource_limit != nullptr) { - insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + insecure_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, m_mapped_insecure_memory); } } // Release any ipc server memory. if (m_mapped_ipc_server_memory) { - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, m_mapped_ipc_server_memory); } } @@ -833,7 +833,7 @@ Result KPageTableBase::LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* o // If we have an output group, open. if (out_pg) { - out_pg->Open(); + out_pg->Open(m_system.Kernel()); } R_SUCCEED(); @@ -1041,7 +1041,7 @@ Result KPageTableBase::MapMemory(KProcessAddress dst_address, KProcessAddress sr const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the source. R_TRY(this->MakePageGroup(pg, src_address, num_pages)); @@ -1129,7 +1129,7 @@ Result KPageTableBase::UnmapMemory(KProcessAddress dst_address, KProcessAddress const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the destination. R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); @@ -1217,7 +1217,7 @@ Result KPageTableBase::MapCodeMemory(KProcessAddress dst_address, KProcessAddres const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the source. R_TRY(this->MakePageGroup(pg, src_address, num_pages)); @@ -1312,7 +1312,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr bool reprotected_pages = false; SCOPE_EXIT { if (reprotected_pages && any_code_pages) { - InvalidateInstructionCache(m_kernel, this, dst_address, size); + InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size); } }; @@ -1322,7 +1322,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr const size_t num_pages = size / PageSize; // Create page groups for the memory being unmapped. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Create the page group representing the destination. R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); @@ -1383,19 +1383,19 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // Get the insecure memory resource limit and pool. - auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); + auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); const auto insecure_pool = static_cast(KSystemControl::GetInsecureMemoryPool()); // Reserve the insecure memory. // NOTE: ResultOutOfMemory is returned here instead of the usual LimitReached. - KScopedResourceReservation memory_reservation(insecure_resource_limit, + KScopedResourceReservation memory_reservation(m_system.Kernel(), insecure_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, size); R_UNLESS(memory_reservation.Succeeded(), ResultOutOfMemory); // Allocate pages for the insecure memory. - KPageGroup pg(m_kernel, m_block_info_manager); - R_TRY(m_kernel.MemoryManager().AllocateAndOpen( + KPageGroup pg(m_system.Kernel(), m_block_info_manager); + R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen( std::addressof(pg), size / PageSize, KMemoryManager::EncodeOption(insecure_pool, KMemoryManager::Direction::FromFront))); @@ -1403,7 +1403,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // automatically. SCOPE_EXIT { - pg.Close(); + pg.Close(m_system.Kernel()); }; // Clear all the newly allocated pages. @@ -1491,9 +1491,9 @@ Result KPageTableBase::UnmapInsecureMemory(KProcessAddress address, size_t size) // Release the insecure memory from the insecure limit. if (auto* const insecure_resource_limit = - KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); + KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel()); insecure_resource_limit != nullptr) { - insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, size); + insecure_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, size); } R_SUCCEED(); @@ -1603,15 +1603,15 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce ASSERT(this->IsLockedByCurrentThread()); // Create a page group to hold the pages we allocate. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Allocate the pages. R_TRY( - m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); + m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); // Ensure that the page group is closed when we're done working with it. SCOPE_EXIT { - pg.Close(); + pg.Close(m_system.Kernel()); }; // Clear all pages. @@ -1992,7 +1992,7 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s KMemoryAttribute::All, KMemoryAttribute::None)); // Make a new page group for the region. - KPageGroup pg(m_kernel, m_block_info_manager); + KPageGroup pg(m_system.Kernel(), m_block_info_manager); // Determine new perm/state. const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm); @@ -2048,9 +2048,9 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s // Ensure cache coherency, if we're setting pages as executable. if (is_x) { for (const auto& block : pg) { - StoreDataCache(GetHeapVirtualPointer(m_kernel, block.GetAddress()), block.GetSize()); + StoreDataCache(GetHeapVirtualPointer(m_system.Kernel(), block.GetAddress()), block.GetSize()); } - InvalidateInstructionCache(m_kernel, this, addr, size); + InvalidateInstructionCache(m_system.Kernel(), this, addr, size); } R_SUCCEED(); @@ -2158,7 +2158,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { false, unmap_properties, OperationType::Unmap, false)); // Release the memory from the resource limit. - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, num_pages * PageSize); // Apply the memory block update. @@ -2188,20 +2188,20 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) { } // Reserve memory for the heap extension. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(m_system.Kernel(), m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, allocation_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the heap extension. - KPageGroup pg(m_kernel, m_block_info_manager); - R_TRY(m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, + KPageGroup pg(m_system.Kernel(), m_block_info_manager); + R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, m_allocate_option)); // Close the opened pages when we're done with them. // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // automatically. SCOPE_EXIT { - pg.Close(); + pg.Close(m_system.Kernel()); }; // Clear all the newly allocated pages. @@ -2406,7 +2406,7 @@ Result KPageTableBase::MapIoImpl(KProcessAddress* out, PageLinkedList* page_list ASSERT(this->CanContain(region_start, region_size, state)); // Locate the memory region. - const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); + const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr); R_UNLESS(region != nullptr, ResultInvalidAddress); ASSERT(region->Contains(GetInteger(phys_addr))); @@ -2640,7 +2640,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor const size_t region_num_pages = region_size / PageSize; // Locate the memory region. - const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); + const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr); R_UNLESS(region != nullptr, ResultInvalidAddress); ASSERT(region->Contains(GetInteger(phys_addr))); @@ -2707,7 +2707,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) { // Get the memory region. const KMemoryRegion* region = - m_kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); + m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); R_UNLESS(region != nullptr, ResultOutOfRange); // Check that the region is valid. @@ -3004,7 +3004,7 @@ Result KPageTableBase::MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress add R_TRY(this->MakePageGroup(*out, address, num_pages)); // Open a new reference to the pages in the group. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3051,7 +3051,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ // Invalidate the block. if (cur_size > 0) { // NOTE: Nintendo does not check the result of invalidation. - InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); } // Advance. @@ -3075,7 +3075,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ // Invalidate the last block. if (cur_size > 0) { // NOTE: Nintendo does not check the result of invalidation. - InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); } R_SUCCEED(); @@ -3083,7 +3083,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_ Result KPageTableBase::InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) { // Check pre-condition: this is being called on the current process. - ASSERT(this == std::addressof(GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable())); + ASSERT(this == std::addressof(GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable())); // Check that the region is in range. R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); @@ -3144,7 +3144,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr // Copy as much aligned data as we can. if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); - const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); FlushDataCache(copy_src, copy_size); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, copy_size), ResultInvalidPointer); @@ -3155,7 +3155,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr // Copy remaining data. if (cur_size > 0) { - const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); FlushDataCache(copy_src, cur_size); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, cur_size), ResultInvalidPointer); } @@ -3240,11 +3240,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd // Copy as much aligned data as we can. if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); - void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, copy_size), ResultInvalidCurrentMemory); - StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), copy_size); + StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size); src_address += copy_size; cur_addr += copy_size; @@ -3253,11 +3253,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd // Copy remaining data. if (cur_size > 0) { - void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); + void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr); R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, cur_size), ResultInvalidCurrentMemory); - StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); } R_SUCCEED(); @@ -3295,7 +3295,7 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd R_TRY(PerformCopy()); // Invalidate the instruction cache, as this svc allows modifying executable pages. - InvalidateInstructionCache(m_kernel, this, dst_address, size); + InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size); R_SUCCEED(); } @@ -3311,7 +3311,7 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre const size_t map_size = map_end - map_start; // Get the memory reference to write into. - auto& dst_memory = GetCurrentMemory(m_kernel); + auto& dst_memory = GetCurrentMemory(m_system.Kernel()); // We're going to perform an update, so create a helper. KScopedPageTableUpdater updater(this); @@ -3347,7 +3347,7 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd const size_t map_size = map_end - map_start; // Get the memory reference to read from. - auto& src_memory = GetCurrentMemory(m_kernel); + auto& src_memory = GetCurrentMemory(m_system.Kernel()); // We're going to perform an update, so create a helper. KScopedPageTableUpdater updater(this); @@ -3379,7 +3379,7 @@ Result KPageTableBase::ReadDebugIoMemory(KProcessAddress dst_address, KProcessAd // We need to lock both this table, and the current process's table, so set up some aliases. KPageTableBase& src_page_table = *this; - KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); + KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable(); // Acquire the table locks. KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); @@ -3421,7 +3421,7 @@ Result KPageTableBase::WriteDebugIoMemory(KProcessAddress dst_address, KProcessA // We need to lock both this table, and the current process's table, so set up some aliases. KPageTableBase& src_page_table = *this; - KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); + KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable(); // Acquire the table locks. KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); @@ -3606,7 +3606,7 @@ Result KPageTableBase::OpenMemoryRangeForMapDeviceAddressSpace(KPageTableBase::M KMemoryAttribute::IpcLocked | KMemoryAttribute::Locked, KMemoryAttribute::None)); // We got the range, so open it. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3624,7 +3624,7 @@ Result KPageTableBase::OpenMemoryRangeForUnmapDeviceAddressSpace(MemoryRange* ou KMemoryAttribute::DeviceShared | KMemoryAttribute::Locked, KMemoryAttribute::DeviceShared)); // We got the range, so open it. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3697,7 +3697,7 @@ Result KPageTableBase::OpenMemoryRangeForProcessCacheOperation(MemoryRange* out, KMemoryAttribute::None)); // We got the range, so open it. - out->Open(); + out->Open(m_system.Kernel()); R_SUCCEED(); } @@ -3710,7 +3710,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( R_UNLESS(this->Contains(src_addr, size), ResultInvalidCurrentMemory); // Get the destination memory reference. - auto& dst_memory = GetCurrentMemory(m_kernel); + auto& dst_memory = GetCurrentMemory(m_system.Kernel()); // Copy the memory. { @@ -3745,7 +3745,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); R_UNLESS(dst_memory.WriteBlock(dst_addr, - GetLinearMappedVirtualPointer(m_kernel, cur_addr), + GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size), ResultInvalidCurrentMemory); @@ -3757,7 +3757,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser( // Copy remaining data. if (cur_size > 0) { R_UNLESS(dst_memory.WriteBlock( - dst_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), + dst_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size), ResultInvalidCurrentMemory); } @@ -3836,7 +3836,7 @@ Result KPageTableBase::CopyMemoryFromLinearToKernel( R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(buffer, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); + std::memcpy(buffer, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size); R_SUCCEED(); }; @@ -3884,7 +3884,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( R_UNLESS(this->Contains(dst_addr, size), ResultInvalidCurrentMemory); // Get the source memory reference. - auto& src_memory = GetCurrentMemory(m_kernel); + auto& src_memory = GetCurrentMemory(m_system.Kernel()); // Copy the memory. { @@ -3919,7 +3919,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( if (cur_size >= sizeof(u32)) { const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); R_UNLESS(src_memory.ReadBlock(src_addr, - GetLinearMappedVirtualPointer(m_kernel, cur_addr), + GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size), ResultInvalidCurrentMemory); src_addr += copy_size; @@ -3930,7 +3930,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear( // Copy remaining data. if (cur_size > 0) { R_UNLESS(src_memory.ReadBlock( - src_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), + src_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size), ResultInvalidCurrentMemory); } @@ -4011,7 +4011,7 @@ Result KPageTableBase::CopyMemoryFromKernelToLinear(KProcessAddress dst_addr, si R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetLinearMappedVirtualPointer(m_kernel, cur_addr), buffer, cur_size); + std::memcpy(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), buffer, cur_size); R_SUCCEED(); }; @@ -4162,8 +4162,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeap( R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), - GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); + std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr), + GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size); // Update. cur_src_block_addr = src_next_entry.phys_addr; @@ -4296,8 +4296,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeapWithoutCheckDestination( R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); // Copy the data. - std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), - GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); + std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr), + GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size); // Update. cur_src_block_addr = src_next_entry.phys_addr; @@ -4493,7 +4493,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Reserve space for any partial pages we allocate. const size_t unmapped_size = aligned_src_size - mapping_src_size; - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(m_system.Kernel(), m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, unmapped_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); @@ -4506,10 +4506,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // free on scope exit. SCOPE_EXIT { if (start_partial_page != 0) { - m_kernel.MemoryManager().Close(start_partial_page, 1); + m_system.Kernel().MemoryManager().Close(start_partial_page, 1); } if (end_partial_page != 0) { - m_kernel.MemoryManager().Close(end_partial_page, 1); + m_system.Kernel().MemoryManager().Close(end_partial_page, 1); } }; @@ -4526,7 +4526,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Allocate the start page as needed. if (aligned_src_start < mapping_src_start) { start_partial_page = - m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); + m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); R_UNLESS(start_partial_page != 0, ResultOutOfMemory); } @@ -4534,7 +4534,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, if (mapping_src_end < aligned_src_end && (aligned_src_start < mapping_src_end || aligned_src_start == mapping_src_start)) { end_partial_page = - m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); + m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); R_UNLESS(end_partial_page != 0, ResultOutOfMemory); } @@ -4560,7 +4560,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Map the start page, if we have one. if (start_partial_page != 0) { // Ensure the page holds correct data. - u8* const start_partial_virt = GetHeapVirtualPointer(m_kernel, start_partial_page); + u8* const start_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), start_partial_page); if (send) { const size_t partial_offset = src_start - aligned_src_start; size_t copy_size, clear_size; @@ -4574,7 +4574,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, std::memset(start_partial_virt, fill_val, partial_offset); std::memcpy(start_partial_virt + partial_offset, - GetHeapVirtualPointer(m_kernel, cur_block_addr) + partial_offset, + GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr) + partial_offset, copy_size); if (clear_size > 0) { std::memset(start_partial_virt + partial_offset + copy_size, fill_val, clear_size); @@ -4663,10 +4663,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size, // Map the end page, if we have one. if (end_partial_page != 0) { // Ensure the page holds correct data. - u8* const end_partial_virt = GetHeapVirtualPointer(m_kernel, end_partial_page); + u8* const end_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), end_partial_page); if (send) { const size_t copy_size = src_end - mapping_src_end; - std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_kernel, cur_block_addr), + std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr), copy_size); std::memset(end_partial_virt + copy_size, fill_val, PageSize - copy_size); } else { @@ -4799,7 +4799,7 @@ Result KPageTableBase::CleanupForIpcServer(KProcessAddress address, size_t size, const KProcessAddress mapping_start = Common::AlignUp(GetInteger(address), PageSize); const KProcessAddress mapping_end = Common::AlignDown(GetInteger(address) + size, PageSize); const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size); R_SUCCEED(); @@ -5168,20 +5168,20 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { // Allocate and map the memory. { // Reserve the memory from the process resource limit. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(m_system.Kernel(), m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, size - mapped_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the new memory. - KPageGroup pg(m_kernel, m_block_info_manager); - R_TRY(m_kernel.MemoryManager().AllocateForProcess( + KPageGroup pg(m_system.Kernel(), m_block_info_manager); + R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess( std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option, - GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value)); + GetCurrentProcess(m_system.Kernel()).GetId(), m_heap_fill_value)); // If we fail in the next bit (or retry), we need to cleanup the pages. auto pg_guard = SCOPE_GUARD { - pg.OpenFirst(); - pg.Close(); + pg.OpenFirst(m_system.Kernel()); + pg.Close(m_system.Kernel()); }; // Map the memory. @@ -5304,12 +5304,12 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { } // Release any remaining unmapped memory. - m_kernel.MemoryManager().OpenFirst(pg_phys_addr, pg_pages); - m_kernel.MemoryManager().Close(pg_phys_addr, pg_pages); + m_system.Kernel().MemoryManager().OpenFirst(pg_phys_addr, pg_pages); + m_system.Kernel().MemoryManager().Close(pg_phys_addr, pg_pages); for (++pg_it; pg_it != pg.end(); ++pg_it) { - m_kernel.MemoryManager().OpenFirst(pg_it->GetAddress(), + m_system.Kernel().MemoryManager().OpenFirst(pg_it->GetAddress(), pg_it->GetNumPages()); - m_kernel.MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); + m_system.Kernel().MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); } }; @@ -5337,11 +5337,11 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { // While we have pages to map, map them. { // Create a page group for the current mapping range. - KPageGroup cur_pg(m_kernel, m_block_info_manager); + KPageGroup cur_pg(m_system.Kernel(), m_block_info_manager); { ON_RESULT_FAILURE_2 { - cur_pg.OpenFirst(); - cur_pg.Close(); + cur_pg.OpenFirst(m_system.Kernel()); + cur_pg.Close(m_system.Kernel()); }; size_t remain_pages = map_pages; @@ -5541,7 +5541,7 @@ Result KPageTableBase::UnmapPhysicalMemory(KProcessAddress address, size_t size) // Release the memory resource. m_mapped_physical_memory_size -= mapped_size; - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, mapped_size); + m_resource_limit->Release(m_system.Kernel(), Svc::LimitableResource::PhysicalMemoryMax, mapped_size); // Update memory blocks. m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, @@ -5706,9 +5706,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const bool separate_heap = operation == OperationType::UnmapPhysical; // Ensure that any pages we track are closed on exit. - KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager()); + KPageGroup pages_to_close(m_system.Kernel(), this->GetBlockInfoManager()); SCOPE_EXIT { - pages_to_close.CloseAndReset(); + pages_to_close.CloseAndReset(m_system.Kernel()); }; // Make a page group representing the region to unmap. @@ -5727,7 +5727,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a // Open references to pages, if we should. if (this->IsHeapPhysicalAddress(phys_addr)) { - m_kernel.MemoryManager().Open(phys_addr, num_pages); + m_system.Kernel().MemoryManager().Open(phys_addr, num_pages); } R_SUCCEED(); @@ -5767,7 +5767,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a const bool separate_heap = operation == OperationType::MapFirstGroupPhysical; // We want to maintain a new reference to every page in the group. - KScopedPageGroup spg(page_group, operation == OperationType::MapGroup); + KScopedPageGroup spg(m_system.Kernel(), page_group, operation == OperationType::MapGroup); for (const auto& node : page_group) { const size_t size{node.GetNumPages() * PageSize}; diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 726fad989f..160e722985 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -61,14 +61,12 @@ public: class MemoryRange { private: - KernelCore& m_kernel; - KPhysicalAddress m_address; - size_t m_size; - bool m_heap; + KPhysicalAddress m_address = 0; + size_t m_size = 0; + bool m_heap = false; public: - explicit MemoryRange(KernelCore& kernel) - : m_kernel(kernel), m_address(0), m_size(0), m_heap(false) {} + explicit MemoryRange() : m_address(0), m_size(0), m_heap(false) {} void Set(KPhysicalAddress address, size_t size, bool heap) { m_address = address; @@ -86,8 +84,8 @@ public: return m_heap; } - void Open(); - void Close(); + void Open(KernelCore& kernel); + void Close(KernelCore& kernel); }; protected: @@ -189,7 +187,6 @@ private: }; private: - KernelCore& m_kernel; Core::System& m_system; KProcessAddress m_address_space_start{}; KProcessAddress m_address_space_end{}; @@ -329,35 +326,35 @@ protected: bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( + return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress( m_cached_physical_linear_region, phys_addr); } bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( + return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress( m_cached_physical_linear_region, phys_addr, size); } bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); } bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { ASSERT(this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr, size); } bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) { ASSERT(!this->IsLockedByCurrentThread()); - return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, + return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, phys_addr); } @@ -744,15 +741,15 @@ public: // Member heap u8* GetHeapVirtualPointer(KPhysicalAddress addr) { - return GetHeapVirtualPointer(m_kernel, addr); + return GetHeapVirtualPointer(m_system.Kernel(), addr); } KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) { - return GetHeapPhysicalAddress(m_kernel, addr); + return GetHeapPhysicalAddress(m_system.Kernel(), addr); } KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) { - return GetHeapVirtualAddress(m_kernel, addr); + return GetHeapVirtualAddress(m_system.Kernel(), addr); } // TODO: GetPageTableVirtualAddress diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp index e5f5d8028c..f64d983e0c 100644 --- a/src/core/hle/kernel/k_port.cpp +++ b/src/core/hle/kernel/k_port.cpp @@ -1,8 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_port.h" #include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -12,15 +16,15 @@ KPort::KPort(KernelCore& kernel) KPort::~KPort() = default; -void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) { +void KPort::Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uintptr_t name) { // Open a new reference count to the initialized port. - this->Open(); + this->Open(kernel); // Create and initialize our server/client pair. KAutoObject::Create(std::addressof(m_server)); KAutoObject::Create(std::addressof(m_client)); - m_server.Initialize(this); - m_client.Initialize(this, max_sessions); + m_server.Initialize(kernel, this); + m_client.Initialize(kernel, this, max_sessions); // Set our member variables. m_is_light = is_light; @@ -28,42 +32,38 @@ void KPort::Initialize(s32 max_sessions, bool is_light, uintptr_t name) { m_state = State::Normal; } -void KPort::OnClientClosed() { - KScopedSchedulerLock sl{m_kernel}; +void KPort::OnClientClosed(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; if (m_state == State::Normal) { m_state = State::ClientClosed; } } -void KPort::OnServerClosed() { - KScopedSchedulerLock sl{m_kernel}; +void KPort::OnServerClosed(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; if (m_state == State::Normal) { m_state = State::ServerClosed; } } -bool KPort::IsServerClosed() const { - KScopedSchedulerLock sl{m_kernel}; +bool KPort::IsServerClosed(KernelCore& kernel) const { + KScopedSchedulerLock sl{kernel}; return m_state == State::ServerClosed; } -Result KPort::EnqueueSession(KServerSession* session) { - KScopedSchedulerLock sl{m_kernel}; - +Result KPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { + KScopedSchedulerLock sl{kernel}; R_UNLESS(m_state == State::Normal, ResultPortClosed); - - m_server.EnqueueSession(session); + m_server.EnqueueSession(kernel, session); R_SUCCEED(); } -Result KPort::EnqueueSession(KLightServerSession* session) { - KScopedSchedulerLock sl{m_kernel}; - +Result KPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { + KScopedSchedulerLock sl{kernel}; R_UNLESS(m_state == State::Normal, ResultPortClosed); - - m_server.EnqueueSession(session); + m_server.EnqueueSession(kernel, session); R_SUCCEED(); } diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index 26f5f14eff..698f794538 100644 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,11 +26,11 @@ public: explicit KPort(KernelCore& kernel); ~KPort() override; - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} - void Initialize(s32 max_sessions, bool is_light, uintptr_t name); - void OnClientClosed(); - void OnServerClosed(); + void Initialize(KernelCore& kernel, s32 max_sessions, bool is_light, uintptr_t name); + void OnClientClosed(KernelCore& kernel); + void OnServerClosed(KernelCore& kernel); uintptr_t GetName() const { return m_name; @@ -36,10 +39,10 @@ public: return m_is_light; } - bool IsServerClosed() const; + bool IsServerClosed(KernelCore& kernel) const; - Result EnqueueSession(KServerSession* session); - Result EnqueueSession(KLightServerSession* session); + Result EnqueueSession(KernelCore& kernel, KServerSession* session); + Result EnqueueSession(KernelCore& kernel, KLightServerSession* session); KClientPort& GetClientPort() { return m_client; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index f737a18736..7308b0ff87 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -28,8 +28,7 @@ namespace Kernel { namespace { -Result TerminateChildren(KernelCore& kernel, KProcess* process, - const KThread* thread_to_not_terminate) { +Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* thread_to_not_terminate) { // Request that all children threads terminate. { KScopedLightLock proc_lk(process->GetListLock()); @@ -41,14 +40,14 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, // This is valid because the only caller which uses non-nullptr as argument uses // GetCurrentThreadPointer(), but it's still notable because it seems incorrect at // first glance. - process->UnpinCurrentThread(); + process->UnpinCurrentThread(kernel); } auto& thread_list = process->GetThreadList(); for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - thread->RequestTerminate(); + thread->RequestTerminate(kernel); } } } @@ -65,7 +64,7 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - if (thread->Open()) { + if (thread->Open(kernel)) { cur_child = thread; break; } @@ -81,11 +80,10 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, // Terminate and close the thread. SCOPE_EXIT { - cur_child->Close(); + cur_child->Close(kernel); }; - if (const Result terminate_result = cur_child->Terminate(); - ResultTerminationRequested == terminate_result) { + if (const Result terminate_result = cur_child->Terminate(kernel); ResultTerminationRequested == terminate_result) { R_THROW(terminate_result); } } @@ -101,21 +99,21 @@ public: explicit ThreadQueueImplForKProcessEnterUserException(KernelCore& kernel, KThread** t) : KThreadQueue(kernel), m_exception_thread(t) {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Set the exception thread. *m_exception_thread = waiting_thread; // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter on its mutex owner. - waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -128,12 +126,12 @@ void GenerateRandom(std::span out_random) { } // namespace -void KProcess::Finalize() { +void KProcess::Finalize(KernelCore& kernel) { // Delete the process local region. - this->DeleteThreadLocalRegion(m_plr_address); + this->DeleteThreadLocalRegion(kernel, m_plr_address); // Get the used memory size. - const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(); + const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); // Finalize the page table. m_page_table.Finalize(); @@ -142,10 +140,10 @@ void KProcess::Finalize() { if (m_system_resource) { if (m_system_resource->IsSecureResource()) { // Finalize optimized memory. If memory wasn't optimized, this is a no-op. - m_kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); + kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); } - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; } @@ -157,12 +155,12 @@ void KProcess::Finalize() { KSharedMemory* shmem = info->GetSharedMemory(); while (!info->Close()) { - shmem->Close(); + shmem->Close(kernel); } - shmem->Close(); + shmem->Close(kernel); it = m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(m_kernel, info); + KSharedMemoryInfo::Free(kernel, info); } } @@ -173,9 +171,8 @@ void KProcess::Finalize() { // Release memory to the resource limit. if (m_resource_limit != nullptr) { ASSERT(used_memory_size >= m_memory_release_hint); - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, - used_memory_size - m_memory_release_hint); - m_resource_limit->Close(); + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint); + m_resource_limit->Close(kernel); } // Clear expensive resources, as the destructor is not called for guest objects. @@ -185,15 +182,14 @@ void KProcess::Finalize() { m_exclusive_monitor.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(); + KSynchronizationObject::Finalize(kernel); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, - bool is_real) { +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real) { // TODO: remove this special case if (is_real) { // Create and clear the process local region. - R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address))); + R_TRY(this->CreateThreadLocalRegion(kernel, std::addressof(m_plr_address))); this->GetMemory().ZeroBlock(m_plr_address, Svc::ThreadLocalRegionSize); } @@ -259,7 +255,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResource // Open a reference to our resource limit. m_resource_limit = res_limit; - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // We're initialized! m_is_initialized = true; @@ -267,7 +263,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResource R_SUCCEED(); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal) { ASSERT(res_limit != nullptr); @@ -283,34 +279,33 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(); + secure_resource->Close(kernel); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, res_limit, - m_memory_pool)); + R_TRY(secure_resource->Initialize(kernel, system_resource_num_pages * PageSize, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() - : m_kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() + : kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(); + m_system_resource->Open(kernel); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; }; @@ -330,7 +325,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, @@ -350,18 +345,18 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa } // Initialize the process id. - m_process_id = m_kernel.CreateNewUserProcessID(); + m_process_id = kernel.CreateNewUserProcessID(); ASSERT(InitialProcessIdMin <= m_process_id); ASSERT(m_process_id <= InitialProcessIdMax); // Initialize the rest of the process. - R_TRY(this->Initialize(params, res_limit, true)); + R_TRY(this->Initialize(kernel, params, res_limit, true)); // We succeeded! R_SUCCEED(); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, std::span user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start) { ASSERT(res_limit != nullptr); @@ -378,22 +373,22 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const size_t system_resource_size = system_resource_num_pages * PageSize; // Reserve memory for our code resource. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(kernel, res_limit, Svc::LimitableResource::PhysicalMemoryMax, code_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Setup our system resource. if (system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(); + secure_resource->Close(kernel); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(system_resource_size, res_limit, m_memory_pool)); + R_TRY(secure_resource->Initialize(kernel, system_resource_size, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; @@ -401,18 +396,18 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() - : m_kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() + : kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(); + m_system_resource->Open(kernel); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; }; @@ -432,7 +427,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), @@ -451,101 +446,99 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, } // Initialize the process id. - m_process_id = m_kernel.CreateNewUserProcessID(); + m_process_id = kernel.CreateNewUserProcessID(); ASSERT(ProcessIdMin <= m_process_id); ASSERT(m_process_id <= ProcessIdMax); // If we should optimize memory allocations, do so. if (m_system_resource->IsSecureResource() && True(params.flags & Svc::CreateProcessFlag::OptimizeMemoryAllocation)) { - R_TRY(m_kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); + R_TRY(kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); } // Initialize the rest of the process. - R_TRY(this->Initialize(params, res_limit, true)); + R_TRY(this->Initialize(kernel, params, res_limit, true)); // We succeeded, so commit our memory reservation. memory_reservation.Commit(); R_SUCCEED(); } -void KProcess::DoWorkerTaskImpl() { +void KProcess::DoWorkerTaskImpl(KernelCore& kernel) { // Terminate child threads. - TerminateChildren(m_kernel, this, nullptr); + TerminateChildren(kernel, this, nullptr); // Finalize the handle table, if we're not immortal. if (!m_is_immortal && m_is_handle_table_initialized) { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); } // Finish termination. - this->FinishTermination(); + this->FinishTermination(kernel); } -Result KProcess::StartTermination() { +Result KProcess::StartTermination(KernelCore& kernel) { // Finalize the handle table when we're done, if the process isn't immortal. SCOPE_EXIT { if (!m_is_immortal) { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); } }; // Terminate child threads other than the current one. - R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel))); + R_RETURN(TerminateChildren(kernel, this, GetCurrentThreadPointer(kernel))); } -void KProcess::FinishTermination() { +void KProcess::FinishTermination(KernelCore& kernel) { // Only allow termination to occur if the process isn't immortal. if (!m_is_immortal) { // Release resource limit hint. if (m_resource_limit != nullptr) { - m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(); - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, 0, - m_memory_release_hint); + m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, 0, m_memory_release_hint); } // Change state. { - KScopedSchedulerLock sl(m_kernel); - this->ChangeState(State::Terminated); + KScopedSchedulerLock sl(kernel); + this->ChangeState(kernel, State::Terminated); } // Close. - this->Close(); + this->Close(kernel); } } -void KProcess::Exit() { +void KProcess::Exit(KernelCore& kernel) { // Determine whether we need to start terminating bool needs_terminate = false; { KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_state != State::Created); ASSERT(m_state != State::CreatedAttached); ASSERT(m_state != State::Crashed); ASSERT(m_state != State::Terminated); - if (m_state == State::Running || m_state == State::RunningAttached || - m_state == State::DebugBreak) { - this->ChangeState(State::Terminating); + if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::DebugBreak) { + this->ChangeState(kernel, State::Terminating); needs_terminate = true; } } // If we need to start termination, do so. if (needs_terminate) { - this->StartTermination(); + this->StartTermination(kernel); // Register the process as a work task. - m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); + kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } // Exit the current thread. - GetCurrentThread(m_kernel).Exit(); + GetCurrentThread(kernel).Exit(kernel); } -Result KProcess::Terminate() { +Result KProcess::Terminate(KernelCore& kernel) { // Determine whether we need to start terminating. bool needs_terminate = false; { @@ -555,11 +548,11 @@ Result KProcess::Terminate() { R_UNLESS(m_state != State::Created, ResultInvalidState); R_UNLESS(m_state != State::CreatedAttached, ResultInvalidState); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::Crashed || m_state == State::DebugBreak) { - this->ChangeState(State::Terminating); + this->ChangeState(kernel, State::Terminating); needs_terminate = true; } } @@ -567,20 +560,19 @@ Result KProcess::Terminate() { // If we need to terminate, do so. if (needs_terminate) { // Start termination. - if (R_SUCCEEDED(this->StartTermination())) { + if (R_SUCCEEDED(this->StartTermination(kernel))) { // Finish termination. - this->FinishTermination(); + this->FinishTermination(kernel); } else { // Register the process as a work task. - m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, - this); + kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } } R_SUCCEED(); } -Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { +Result KProcess::AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -596,7 +588,7 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, // If we didn't find an info, create one. if (info == nullptr) { // Allocate a new info. - info = KSharedMemoryInfo::Allocate(m_kernel); + info = KSharedMemoryInfo::Allocate(kernel); R_UNLESS(info != nullptr, ResultOutOfResource); // Initialize the info and add it to our list. @@ -605,13 +597,13 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, } // Open a reference to the shared memory and its info. - shmem->Open(); + shmem->Open(kernel); info->Open(); R_SUCCEED(); } -void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { +void KProcess::RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -629,19 +621,19 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, // Close a reference to the info and its memory. if (info->Close()) { m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(m_kernel, info); + KSharedMemoryInfo::Free(kernel, info); } - shmem->Close(); + shmem->Close(kernel); } -Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { +Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out) { KThreadLocalPage* tlp = nullptr; KProcessAddress tlr = 0; // See if we can get a region from a partially used TLP. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) { tlr = it->Reserve(); @@ -659,14 +651,14 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { } // Allocate a new page. - tlp = KThreadLocalPage::Allocate(m_kernel); + tlp = KThreadLocalPage::Allocate(kernel); R_UNLESS(tlp != nullptr, ResultOutOfMemory); ON_RESULT_FAILURE { - KThreadLocalPage::Free(m_kernel, tlp); + KThreadLocalPage::Free(kernel, tlp); }; // Initialize the new page. - R_TRY(tlp->Initialize(m_kernel, this)); + R_TRY(tlp->Initialize(kernel, this)); // Reserve a TLR. tlr = tlp->Reserve(); @@ -674,7 +666,7 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { // Insert into our tree. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (tlp->IsAllUsed()) { m_fully_used_tlp_tree.insert(*tlp); } else { @@ -687,12 +679,12 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { R_SUCCEED(); } -Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { +Result KProcess::DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr) { KThreadLocalPage* page_to_free = nullptr; // Release the region. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Try to find the page in the partially used list. auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize)); @@ -729,57 +721,56 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { if (page_to_free != nullptr) { page_to_free->Finalize(); - KThreadLocalPage::Free(m_kernel, page_to_free); + KThreadLocalPage::Free(kernel, page_to_free); } R_SUCCEED(); } -bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value) { +bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(which, value); + return rl->Reserve(kernel, which, value); } else { return true; } } -bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout) { +bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(which, value, timeout); + return rl->Reserve(kernel, which, value, timeout); } else { return true; } } -void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value) { +void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(which, value); + rl->Release(kernel, which, value); } } -void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint) { +void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(which, value, hint); + rl->Release(kernel, which, value, hint); } } -void KProcess::IncrementRunningThreadCount() { +void KProcess::IncrementRunningThreadCount(KernelCore& kernel) { ASSERT(m_num_running_threads.load() >= 0); ++m_num_running_threads; } -void KProcess::DecrementRunningThreadCount() { +void KProcess::DecrementRunningThreadCount(KernelCore& kernel) { ASSERT(m_num_running_threads.load() > 0); - if (const auto prev = m_num_running_threads--; prev == 1) { - this->Terminate(); + this->Terminate(kernel); } } -bool KProcess::EnterUserException() { +bool KProcess::EnterUserException(KernelCore& kernel) { // Get the current thread. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); ASSERT(this == cur_thread->GetOwnerProcess()); // Check that we haven't already claimed the exception thread. @@ -788,13 +779,13 @@ bool KProcess::EnterUserException() { } // Create the wait queue we'll be using. - ThreadQueueImplForKProcessEnterUserException wait_queue(m_kernel, + ThreadQueueImplForKProcessEnterUserException wait_queue(kernel, std::addressof(m_exception_thread)); // Claim the exception thread. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we're not terminating. if (cur_thread->IsTerminationRequested()) { @@ -804,45 +795,44 @@ bool KProcess::EnterUserException() { // If we don't have an exception thread, we can just claim it directly. if (m_exception_thread == nullptr) { m_exception_thread = cur_thread; - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); return true; } // Otherwise, we need to wait until we don't have an exception thread. // Add the current thread as a waiter on the current exception thread. - cur_thread->SetKernelAddressKey( - reinterpret_cast(std::addressof(m_exception_thread)) | 1); - m_exception_thread->AddWaiter(cur_thread); + cur_thread->SetKernelAddressKey(uintptr_t(std::addressof(m_exception_thread)) | 1); + m_exception_thread->AddWaiter(kernel, cur_thread); // Wait to claim the exception thread. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(kernel, std::addressof(wait_queue)); } // If our wait didn't end due to thread termination, we succeeded. return ResultTerminationRequested != cur_thread->GetWaitResult(); } -bool KProcess::LeaveUserException() { - return this->ReleaseUserException(GetCurrentThreadPointer(m_kernel)); +bool KProcess::LeaveUserException(KernelCore& kernel) { + return this->ReleaseUserException(kernel, GetCurrentThreadPointer(kernel)); } -bool KProcess::ReleaseUserException(KThread* thread) { - KScopedSchedulerLock sl(m_kernel); +bool KProcess::ReleaseUserException(KernelCore& kernel, KThread* thread) { + KScopedSchedulerLock sl(kernel); if (m_exception_thread == thread) { m_exception_thread = nullptr; // Remove waiter thread. bool has_waiters; - if (KThread* next = thread->RemoveKernelWaiterByKey( + if (KThread* next = thread->RemoveKernelWaiterByKey(kernel, std::addressof(has_waiters), reinterpret_cast(std::addressof(m_exception_thread)) | 1); next != nullptr) { - next->EndWait(ResultSuccess); + next->EndWait(kernel, ResultSuccess); } - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); return true; } else { @@ -850,19 +840,19 @@ bool KProcess::ReleaseUserException(KThread* thread) { } } -void KProcess::RegisterThread(KThread* thread) { +void KProcess::RegisterThread(KernelCore& kernel, KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.push_back(*thread); } -void KProcess::UnregisterThread(KThread* thread) { +void KProcess::UnregisterThread(KernelCore& kernel, KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.erase(m_thread_list.iterator_to(*thread)); } -size_t KProcess::GetUsedUserPhysicalMemorySize() const { +size_t KProcess::GetUsedUserPhysicalMemorySize(KernelCore& kernel) const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault(); @@ -870,7 +860,7 @@ size_t KProcess::GetUsedUserPhysicalMemorySize() const { return norm_size + other_size + sec_size; } -size_t KProcess::GetTotalUserPhysicalMemorySize() const { +size_t KProcess::GetTotalUserPhysicalMemorySize(KernelCore& kernel) const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -889,18 +879,18 @@ size_t KProcess::GetTotalUserPhysicalMemorySize() const { if (used_size + free_size > max_size) { return max_size; } else { - return free_size + this->GetUsedUserPhysicalMemorySize(); + return free_size + this->GetUsedUserPhysicalMemorySize(kernel); } } -size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const { +size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; return norm_size + other_size; } -size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { +size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -919,11 +909,11 @@ size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { if (used_size + free_size > max_size) { return max_size - this->GetRequiredSecureMemorySizeNonDefault(); } else { - return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(); + return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(kernel); } } -Result KProcess::Run(s32 priority, size_t stack_size) { +Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -932,7 +922,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_UNLESS(state == State::Created || state == State::CreatedAttached, ResultInvalidState); // Place a tentative reservation of a thread for this process. - KScopedResourceReservation thread_reservation(this, Svc::LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(kernel, this, Svc::LimitableResource::ThreadCountMax); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); // Ensure that we haven't already allocated stack. @@ -944,7 +934,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_UNLESS(stack_size + m_code_size >= m_code_size, ResultOutOfMemory); // Place a tentative reservation of memory for our new stack. - KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax, + KScopedResourceReservation mem_reservation(kernel, this, Svc::LimitableResource::PhysicalMemoryMax, stack_size); R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached); @@ -974,29 +964,29 @@ Result KProcess::Run(s32 priority, size_t stack_size) { (m_main_thread_stack_size + m_code_size))); // Initialize our handle table. - R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize())); + R_TRY(this->InitializeHandleTable(kernel, m_capabilities.GetHandleTableSize())); ON_RESULT_FAILURE_2 { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); }; // Create a new thread for the process. - KThread* main_thread = KThread::Create(m_kernel); + KThread* main_thread = KThread::Create(kernel); R_UNLESS(main_thread != nullptr, ResultOutOfResource); SCOPE_EXIT { - main_thread->Close(); + main_thread->Close(kernel); }; // Initialize the thread. - R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0, + R_TRY(KThread::InitializeUserThread(kernel.System(), main_thread, this->GetEntryPoint(), 0, stack_top, priority, m_ideal_core_id, this)); // Register the thread, and commit our reservation. - KThread::Register(m_kernel, main_thread); + KThread::Register(kernel, main_thread); thread_reservation.Commit(); // Add the thread to our handle table. Handle thread_handle; - R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread)); + R_TRY(m_handle_table.Add(kernel, std::addressof(thread_handle), main_thread)); // Set the thread arguments. Two distinct entry conventions: // * Kernel/NSO entry (no homebrew ABI): x0 = 0, x1 = thread_handle @@ -1024,21 +1014,21 @@ Result KProcess::Run(s32 priority, size_t stack_size) { this->GetMemory().Write32(GetInteger(main_thread->GetTlsAddress()) + 0x110, thread_handle); // Update our state. - this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached); + this->ChangeState(kernel, (state == State::Created) ? State::Running : State::RunningAttached); ON_RESULT_FAILURE_2 { - this->ChangeState(state); + this->ChangeState(kernel, state); }; // Suspend for debug, if we should. - if (m_kernel.System().DebuggerEnabled()) { - main_thread->RequestSuspend(SuspendType::Debug); + if (kernel.System().DebuggerEnabled()) { + main_thread->RequestSuspend(kernel, SuspendType::Debug); } // Run our thread. - R_TRY(main_thread->Run()); + R_TRY(main_thread->Run(kernel)); // Open a reference to represent that we're running. - this->Open(); + this->Open(kernel); // We succeeded! Commit our memory reservation. mem_reservation.Commit(); @@ -1046,10 +1036,10 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_SUCCEED(); } -Result KProcess::Reset() { +Result KProcess::Reset(KernelCore& kernel) { // Lock the process and the scheduler. KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Validate that we're in a state that we can reset. R_UNLESS(m_state != State::Terminated, ResultInvalidState); @@ -1060,11 +1050,11 @@ Result KProcess::Reset() { R_SUCCEED(); } -Result KProcess::SetActivity(Svc::ProcessActivity activity) { +Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) { // Lock ourselves and the scheduler. KScopedLightLock lk(m_state_lock); KScopedLightLock list_lk(m_list_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Validate our state. R_UNLESS(m_state != State::Terminating, ResultInvalidState); @@ -1078,7 +1068,7 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Suspend all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->RequestSuspend(SuspendType::Process); + it->RequestSuspend(kernel, SuspendType::Process); } // Set ourselves as suspended. @@ -1092,7 +1082,7 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Resume all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->Resume(SuspendType::Process); + it->Resume(kernel, SuspendType::Process); } // Set ourselves as resumed. @@ -1102,54 +1092,54 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { R_SUCCEED(); } -void KProcess::PinCurrentThread() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::PinCurrentThread(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(m_kernel); - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + const s32 core_id = GetCurrentCoreId(kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // If the thread isn't terminated, pin it. if (!cur_thread->IsTerminationRequested()) { // Pin it. this->PinThread(core_id, cur_thread); - cur_thread->Pin(core_id); + cur_thread->Pin(kernel, core_id); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } } -void KProcess::UnpinCurrentThread() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::UnpinCurrentThread(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(m_kernel); - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + const s32 core_id = GetCurrentCoreId(kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // Unpin it. - cur_thread->Unpin(); + cur_thread->Unpin(kernel); this->UnpinThread(core_id, cur_thread); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } -void KProcess::UnpinThread(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::UnpinThread(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the thread's core id. const auto core_id = thread->GetActiveCore(); // Unpin it. this->UnpinThread(core_id, thread); - thread->Unpin(); + thread->Unpin(kernel); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } -Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, +Result KProcess::GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count) { auto& memory = this->GetMemory(); @@ -1179,7 +1169,7 @@ Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ R_SUCCEED(); } -void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} +void KProcess::Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process) {} KProcess::KProcess(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer(kernel) @@ -1195,16 +1185,16 @@ KProcess::KProcess(KernelCore& kernel) KProcess::~KProcess() = default; -Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { +Result KProcess::LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { // Create a resource limit for the process. const auto pool = static_cast(metadata.GetPoolPartition()); - const auto physical_memory_size = m_kernel.MemoryManager().GetSize(pool); + const auto physical_memory_size = kernel.MemoryManager().GetSize(pool); auto* res_limit = - Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size); + Kernel::CreateResourceLimitForProcess(kernel.System(), physical_memory_size); // Ensure we maintain a clean state on exit. SCOPE_EXIT { - res_limit->Close(); + res_limit->Close(kernel); }; // Declare flags and code address. @@ -1263,22 +1253,20 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: std::memcpy(params.name.data(), name.data(), sizeof(params.name)); // Initialize for application process. - R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, pool, - aslr_space_start)); + R_TRY(this->Initialize(kernel, params, metadata.GetKernelCapabilities(), res_limit, pool, aslr_space_start)); // Assign remaining properties. m_ideal_core_id = metadata.GetMainThreadCore(); // Set up emulation context. - this->InitializeInterfaces(); + this->InitializeInterfaces(kernel); // We succeeded. R_SUCCEED(); } -void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { - const auto ReprotectSegment = [&](const CodeSet::Segment& segment, - Svc::MemoryPermission permission) { +void KProcess::LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr) { + const auto ReprotectSegment = [&](const CodeSet::Segment& segment, Svc::MemoryPermission permission) { m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); }; @@ -1292,7 +1280,7 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { const auto& patch = code_set.PatchSegment(); const auto& post_patch = code_set.PostPatchSegment(); if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) { - auto& buffer = m_kernel.System().DeviceMemory().buffer; + auto& buffer = kernel.System().DeviceMemory().buffer; const auto& code = code_set.CodeSegment(); buffer.Protect(GetInteger(base_addr + code.addr), code.size, Common::MemoryPermission::Read | Common::MemoryPermission::Execute); @@ -1311,32 +1299,32 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { #endif } -void KProcess::InitializeInterfaces() { +void KProcess::InitializeInterfaces(KernelCore& kernel) { m_exclusive_monitor = Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES); #ifdef HAS_NCE if (this->IsApplication() && Settings::IsNceEnabled()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) - m_arm_interfaces[i] = std::make_unique(m_kernel.System(), true, i); + m_arm_interfaces[i] = std::make_unique(kernel.System(), true, i); } else #endif if (this->Is64Bit()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique( - m_kernel.System(), m_kernel.IsMulticore(), this, + kernel.System(), kernel.IsMulticore(), this, static_cast(*m_exclusive_monitor), i); } } else { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique( - m_kernel.System(), m_kernel.IsMulticore(), this, + kernel.System(), kernel.IsMulticore(), this, static_cast(*m_exclusive_monitor), i); } } } -bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.type == DebugWatchpointType::None; })}; @@ -1358,7 +1346,7 @@ bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointT return true; } -bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; })}; diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 2413e5bfd9..c861a9ea51 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -141,8 +141,8 @@ private: bool m_is_handle_table_initialized : 1 = false; private: - Result StartTermination(); - void FinishTermination(); + Result StartTermination(KernelCore& kernel); + void FinishTermination(KernelCore& kernel); void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); @@ -162,16 +162,16 @@ public: explicit KProcess(KernelCore& kernel); ~KProcess() override; - Result Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, + Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real); - Result Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, + Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal); - Result Initialize(const Svc::CreateProcessParameter& params, std::span user_caps, + Result Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, std::span user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start); - void Exit(); + void Exit(KernelCore& kernel); const char* GetName() const { return m_name.data(); @@ -267,7 +267,7 @@ public: m_pointer_buffer_size = size; } - Result Terminate(); + Result Terminate(KernelCore& kernel); bool IsTerminated() const { return m_state == State::Terminated; @@ -300,9 +300,9 @@ public: return m_thread_list; } - bool EnterUserException(); - bool LeaveUserException(); - bool ReleaseUserException(KThread* thread); + bool EnterUserException(KernelCore& kernel); + bool LeaveUserException(KernelCore& kernel); + bool ReleaseUserException(KernelCore& kernel, KThread* thread); KThread* GetPinnedThread(s32 core_id) const { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); @@ -317,10 +317,10 @@ public: return m_resource_limit; } - bool ReserveResource(Svc::LimitableResource which, s64 value); - bool ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout); - void ReleaseResource(Svc::LimitableResource which, s64 value); - void ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint); + bool ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value); + bool ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout); + void ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value); + void ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint); KLightLock& GetStateLock() { return m_state_lock; @@ -343,16 +343,16 @@ public: return m_handle_table; } - size_t GetUsedUserPhysicalMemorySize() const; - size_t GetTotalUserPhysicalMemorySize() const; - size_t GetUsedNonSystemUserPhysicalMemorySize() const; - size_t GetTotalNonSystemUserPhysicalMemorySize() const; + size_t GetUsedUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetTotalUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const; + size_t GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const; - Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); - void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); + Result AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size); + void RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size); - Result CreateThreadLocalRegion(KProcessAddress* out); - Result DeleteThreadLocalRegion(KProcessAddress addr); + Result CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out); + Result DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr); KProcessAddress GetProcessLocalRegionAddress() const { return m_plr_address; @@ -376,8 +376,8 @@ public: ++m_schedule_count; } - void IncrementRunningThreadCount(); - void DecrementRunningThreadCount(); + void IncrementRunningThreadCount(KernelCore& kernel); + void DecrementRunningThreadCount(KernelCore& kernel); size_t GetRequiredSecureMemorySizeNonDefault() const { if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) { @@ -422,11 +422,9 @@ public: } void ClearRunningThread(KThread* thread) { - for (size_t i = 0; i < m_running_threads.size(); ++i) { - if (m_running_threads[i] == thread) { + for (size_t i = 0; i < m_running_threads.size(); ++i) + if (m_running_threads[i] == thread) m_running_threads[i] = nullptr; - } - } } const KSystemResource& GetSystemResource() const { @@ -453,30 +451,27 @@ public: return m_running_thread_switch_counts[core]; } - void RegisterThread(KThread* thread); - void UnregisterThread(KThread* thread); + void RegisterThread(KernelCore& kernel, KThread* thread); + void UnregisterThread(KernelCore& kernel, KThread* thread); + Result Run(KernelCore& kernel, s32 priority, size_t stack_size); + Result Reset(KernelCore& kernel); - Result Run(s32 priority, size_t stack_size); - - Result Reset(); - - void SetDebugBreak() { + void SetDebugBreak(KernelCore& kernel) { if (m_state == State::RunningAttached) { - this->ChangeState(State::DebugBreak); + this->ChangeState(kernel, State::DebugBreak); } } - void SetAttached() { + void SetAttached(KernelCore& kernel) { if (m_state == State::DebugBreak) { - this->ChangeState(State::RunningAttached); + this->ChangeState(kernel, State::RunningAttached); } } - Result SetActivity(Svc::ProcessActivity activity); - - void PinCurrentThread(); - void UnpinCurrentThread(); - void UnpinThread(KThread* thread); + Result SetActivity(KernelCore& kernel, Svc::ProcessActivity activity); + void PinCurrentThread(KernelCore& kernel); + void UnpinCurrentThread(KernelCore& kernel); + void UnpinThread(KernelCore& kernel, KThread* thread); void SignalConditionVariable(uintptr_t cv_key, int32_t count) { return m_cond_var.Signal(cv_key, count); @@ -486,19 +481,17 @@ public: R_RETURN(m_cond_var.Wait(address, cv_key, tag, ns)); } - Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value, - s32 count) { + Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value, s32 count) { R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count)); } - Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value, - s64 timeout) { + Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value, s64 timeout) { R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout)); } - Result GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count); + Result GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count); - static void Switch(KProcess* cur_process, KProcess* next_process); + static void Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process); #ifdef HAS_NCE ankerl::unordered_dense::map& GetPostHandlers() noexcept { @@ -512,21 +505,21 @@ public: public: // Attempts to insert a watchpoint into a free slot. Returns false if none are available. - bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); + bool InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type); // Attempts to remove the watchpoint specified by the given parameters. - bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); + bool RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type); const std::array& GetWatchpoints() const { return m_watchpoints; } public: - Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset); + Result LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset); - void LoadModule(CodeSet code_set, KProcessAddress base_addr); + void LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr); - void InitializeInterfaces(); + void InitializeInterfaces(KernelCore& kernel); Core::Memory::Memory& GetMemory() { return m_memory; @@ -542,9 +535,9 @@ public: return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} - void Finalize() override; + void Finalize(KernelCore& kernel) override; u64 GetIdImpl() const { return this->GetProcessId(); @@ -553,34 +546,34 @@ public: return this->GetIdImpl(); } - virtual bool IsSignaled() const override { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + virtual bool IsSignaled(KernelCore& kernel) const override { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); return m_is_signaled; } - void DoWorkerTaskImpl(); + void DoWorkerTaskImpl(KernelCore& kernel); private: - void ChangeState(State new_state) { + void ChangeState(KernelCore& kernel, State new_state) { if (m_state != new_state) { m_state = new_state; m_is_signaled = true; - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } - Result InitializeHandleTable(s32 size) { + Result InitializeHandleTable(KernelCore& kernel, s32 size) { // Try to initialize the handle table. - R_TRY(m_handle_table.Initialize(size)); + R_TRY(m_handle_table.Initialize(kernel, size)); // We succeeded, so note that we did. m_is_handle_table_initialized = true; R_SUCCEED(); } - void FinalizeHandleTable() { + void FinalizeHandleTable(KernelCore& kernel) { // Finalize the table. - m_handle_table.Finalize(); + m_handle_table.Finalize(kernel); // Note that the table is finalized. m_is_handle_table_initialized = false; diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index c30662666b..a00941bc1e 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,50 +18,45 @@ KReadableEvent::KReadableEvent(KernelCore& kernel) : KSynchronizationObject{kern KReadableEvent::~KReadableEvent() = default; -void KReadableEvent::Initialize(KEvent* parent) { +void KReadableEvent::Initialize(KernelCore& kernel, KEvent* parent) { m_is_signaled = false; m_parent = parent; - if (m_parent != nullptr) { - m_parent->Open(); + m_parent->Open(kernel); } } -bool KReadableEvent::IsSignaled() const { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); - +bool KReadableEvent::IsSignaled(KernelCore& kernel) const { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); return m_is_signaled; } -void KReadableEvent::Destroy() { +void KReadableEvent::Destroy(KernelCore& kernel) { if (m_parent) { { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; m_parent->OnReadableEventDestroyed(); } - m_parent->Close(); + m_parent->Close(kernel); } } -Result KReadableEvent::Signal() { - KScopedSchedulerLock lk{m_kernel}; - +Result KReadableEvent::Signal(KernelCore& kernel) { + KScopedSchedulerLock lk{kernel}; if (!m_is_signaled) { m_is_signaled = true; - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } - R_SUCCEED(); } -Result KReadableEvent::Clear() { - this->Reset(); - +Result KReadableEvent::Clear(KernelCore& kernel) { + this->Reset(kernel); R_SUCCEED(); } -Result KReadableEvent::Reset() { - KScopedSchedulerLock lk{m_kernel}; +Result KReadableEvent::Reset(KernelCore& kernel) { + KScopedSchedulerLock lk{kernel}; R_UNLESS(m_is_signaled, ResultInvalidState); diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index d2ec363233..63a6e8de60 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,19 +23,17 @@ public: explicit KReadableEvent(KernelCore& kernel); ~KReadableEvent() override; - void Initialize(KEvent* parent); + void Initialize(KernelCore& kernel, KEvent* parent); KEvent* GetParent() const { return m_parent; } - Result Signal(); - Result Clear(); - - bool IsSignaled() const override; - void Destroy() override; - - Result Reset(); + Result Signal(KernelCore& kernel); + Result Clear(KernelCore& kernel); + bool IsSignaled(KernelCore& kernel) const override; + void Destroy(KernelCore& kernel) override; + Result Reset(KernelCore& kernel); private: bool m_is_signaled{}; diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index e886f97ebd..1a2c92a665 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -16,12 +16,15 @@ namespace Kernel { constexpr s64 DefaultTimeout = 10000000000; // 10 seconds KResourceLimit::KResourceLimit(KernelCore& kernel) - : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {} + : KAutoObjectWithSlabHeapAndContainer{kernel} + , m_lock{kernel} + , m_cond_var{kernel} +{} KResourceLimit::~KResourceLimit() = default; void KResourceLimit::Initialize() {} -void KResourceLimit::Finalize() {} +void KResourceLimit::Finalize(KernelCore& kernel) {} s64 KResourceLimit::GetLimitValue(LimitableResource which) const { const auto index = static_cast(which); @@ -87,11 +90,11 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { R_SUCCEED(); } -bool KResourceLimit::Reserve(LimitableResource which, s64 value) { - return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout); +bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 value) { + return Reserve(kernel, which, value, kernel.HardwareTimer().GetTick() + DefaultTimeout); } -bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { +bool KResourceLimit::Reserve(KernelCore& kernel, LimitableResource which, s64 value, s64 timeout) { ASSERT(value >= 0); const auto index = static_cast(which); KScopedLightLock lk(m_lock); @@ -119,7 +122,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { } if (m_current_hints[index] + value <= m_limit_values[index] && - (timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) { + (timeout < 0 || kernel.HardwareTimer().GetTick() < timeout)) { m_waiter_count++; m_cond_var.Wait(std::addressof(m_lock), timeout, false); m_waiter_count--; @@ -131,11 +134,11 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { return false; } -void KResourceLimit::Release(LimitableResource which, s64 value) { - Release(which, value, value); +void KResourceLimit::Release(KernelCore& kernel, LimitableResource which, s64 value) { + Release(kernel, which, value, value); } -void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { +void KResourceLimit::Release(KernelCore& kernel, LimitableResource which, s64 value, s64 hint) { ASSERT(value >= 0); ASSERT(hint >= 0); diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index b733ec8f81..eb45d23bab 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -32,7 +35,7 @@ public: ~KResourceLimit() override; void Initialize(); - void Finalize() override; + void Finalize(KernelCore& kernel) override; s64 GetLimitValue(LimitableResource which) const; s64 GetCurrentValue(LimitableResource which) const; @@ -41,12 +44,12 @@ public: Result SetLimitValue(LimitableResource which, s64 value); - bool Reserve(LimitableResource which, s64 value); - bool Reserve(LimitableResource which, s64 value, s64 timeout); - void Release(LimitableResource which, s64 value); - void Release(LimitableResource which, s64 value, s64 hint); + bool Reserve(KernelCore& kernel, LimitableResource which, s64 value); + bool Reserve(KernelCore& kernel, LimitableResource which, s64 value, s64 timeout); + void Release(KernelCore& kernel, LimitableResource which, s64 value); + void Release(KernelCore& kernel, LimitableResource which, s64 value, s64 hint); - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} private: using ResourceArray = std::array(LimitableResource::Count)>; diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 4b76e18950..8e629f6456 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -30,34 +30,32 @@ static void IncrementScheduledCount(Kernel::KThread* thread) { } } -KScheduler::KScheduler(KernelCore& kernel) : m_kernel{kernel} { - m_switch_fiber = std::make_shared([this] { +KScheduler::KScheduler(KernelCore& kernel) { + m_switch_fiber = std::make_shared([this, &kernel] { while (true) { - ScheduleImplFiber(); + ScheduleImplFiber(kernel); } }); - m_state.needs_scheduling = true; } KScheduler::~KScheduler() = default; -void KScheduler::SetInterruptTaskRunnable() { +void KScheduler::SetInterruptTaskRunnable(KernelCore& kernel) { m_state.interrupt_task_runnable = true; m_state.needs_scheduling = true; } -void KScheduler::RequestScheduleOnInterrupt() { +void KScheduler::RequestScheduleOnInterrupt(KernelCore& kernel) { m_state.needs_scheduling = true; - - if (CanSchedule(m_kernel)) { - ScheduleOnInterrupt(); + if (CanSchedule(kernel)) { + ScheduleOnInterrupt(kernel); } } void KScheduler::DisableScheduling(KernelCore& kernel) { ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); - GetCurrentThread(kernel).DisableDispatch(); + GetCurrentThread(kernel).DisableDispatch(kernel); } void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduling) { @@ -71,12 +69,12 @@ void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduli return; } - scheduler->RescheduleOtherCores(cores_needing_scheduling); + scheduler->RescheduleOtherCores(kernel, cores_needing_scheduling); if (GetCurrentThread(kernel).GetDisableDispatchCount() > 1) { - GetCurrentThread(kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); } else { - scheduler->RescheduleCurrentCore(); + scheduler->RescheduleCurrentCore(kernel); } } @@ -85,10 +83,10 @@ void KScheduler::RescheduleCurrentHLEThread(KernelCore& kernel) { ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); // Ensure dummy threads that are waiting block. - GetCurrentThread(kernel).DummyThreadBeginWait(); + GetCurrentThread(kernel).DummyThreadBeginWait(kernel); ASSERT(GetCurrentThread(kernel).GetState() != ThreadState::Waiting); - GetCurrentThread(kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); } u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { @@ -99,55 +97,55 @@ u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { } } -void KScheduler::Schedule() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); - ASSERT(m_core_id == GetCurrentCoreId(m_kernel)); +void KScheduler::Schedule(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); + ASSERT(m_core_id == GetCurrentCoreId(kernel)); - ScheduleImpl(); + ScheduleImpl(kernel); } -void KScheduler::ScheduleOnInterrupt() { - GetCurrentThread(m_kernel).DisableDispatch(); - Schedule(); - GetCurrentThread(m_kernel).EnableDispatch(); +void KScheduler::ScheduleOnInterrupt(KernelCore& kernel) { + GetCurrentThread(kernel).DisableDispatch(kernel); + Schedule(kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } -void KScheduler::PreemptSingleCore() { - GetCurrentThread(m_kernel).DisableDispatch(); +void KScheduler::PreemptSingleCore(KernelCore& kernel) { + GetCurrentThread(kernel).DisableDispatch(kernel); - auto* thread = GetCurrentThreadPointer(m_kernel); - auto& previous_scheduler = m_kernel.Scheduler(thread->GetCurrentCore()); - previous_scheduler.Unload(thread); + auto* thread = GetCurrentThreadPointer(kernel); + auto& previous_scheduler = kernel.Scheduler(thread->GetCurrentCore()); + previous_scheduler.Unload(kernel, thread); Common::Fiber::YieldTo(thread->GetHostContext(), *m_switch_fiber); - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); } -void KScheduler::RescheduleCurrentCore() { - ASSERT(!m_kernel.IsPhantomModeForSingleCore()); - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); +void KScheduler::RescheduleCurrentCore(KernelCore& kernel) { + ASSERT(!kernel.IsPhantomModeForSingleCore()); + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(kernel).EnableDispatch(kernel); if (m_state.needs_scheduling.load()) { // Disable interrupts, and then check again if rescheduling is needed. // KScopedInterruptDisable intr_disable; - m_kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(); + kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(kernel); } } -void KScheduler::RescheduleCurrentCoreImpl() { +void KScheduler::RescheduleCurrentCoreImpl(KernelCore& kernel) { // Check that scheduling is needed. if (m_state.needs_scheduling.load()) [[likely]] { - GetCurrentThread(m_kernel).DisableDispatch(); - Schedule(); - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(kernel).DisableDispatch(kernel); + Schedule(kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } } -void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id) { +void KScheduler::Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id) { // Set core ID/idle thread/interrupt task manager. m_core_id = core_id; m_idle_thread = idle_thread; @@ -156,39 +154,39 @@ void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core // Insert the main thread into the priority queue. // { - // KScopedSchedulerLock lk{m_kernel}; - // GetPriorityQueue(m_kernel).PushBack(GetCurrentThreadPointer(m_kernel)); - // SetSchedulerUpdateNeeded(m_kernel); + // KScopedSchedulerLock lk{kernel}; + // GetPriorityQueue(kernel).PushBack(GetCurrentThreadPointer(kernel)); + // SetSchedulerUpdateNeeded(kernel); // } // Bind interrupt handler. // kernel.GetInterruptManager().BindHandler( - // GetSchedulerInterruptHandler(m_kernel), KInterruptName::Scheduler, m_core_id, + // GetSchedulerInterruptHandler(kernel), KInterruptName::Scheduler, m_core_id, // KInterruptController::PriorityLevel::Scheduler, false, false); // Set the current thread. m_current_thread = main_thread; } -void KScheduler::Activate() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); +void KScheduler::Activate(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); // m_state.should_count_idle = KTargetSystem::IsDebugMode(); m_is_active = true; - RescheduleCurrentCore(); + RescheduleCurrentCore(kernel); } -void KScheduler::OnThreadStart() { - GetCurrentThread(m_kernel).EnableDispatch(); +void KScheduler::OnThreadStart(KernelCore& kernel) { + GetCurrentThread(kernel).EnableDispatch(kernel); } -u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { +u64 KScheduler::UpdateHighestPriorityThread(KernelCore& kernel, KThread* highest_thread) { if (KThread* prev_highest_thread = m_state.highest_priority_thread; prev_highest_thread != highest_thread) [[likely]] { if (prev_highest_thread != nullptr) [[likely]] { IncrementScheduledCount(prev_highest_thread); prev_highest_thread->SetLastScheduledTick( - m_kernel.System().CoreTiming().GetClockTicks()); + kernel.System().CoreTiming().GetClockTicks()); } if (m_state.should_count_idle) { if (highest_thread != nullptr) [[likely]] { @@ -245,8 +243,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } top_threads[core_id] = top_thread; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); } // Idle cores are bad. We're going to try to migrate threads to each idle core in turn. @@ -274,8 +271,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); break; } @@ -298,17 +294,13 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { // The candidate core can run some other thread! We'll migrate its current // top thread to us. top_threads[candidate_core] = next_on_candidate_core; - cores_needing_scheduling |= - kernel.Scheduler(candidate_core) - .UpdateHighestPriorityThread(top_threads[candidate_core]); + cores_needing_scheduling |= kernel.Scheduler(candidate_core).UpdateHighestPriorityThread(kernel, top_threads[candidate_core]); // Perform the migration. suggested->SetActiveCore(core_id); priority_queue.ChangeCore(candidate_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread( - top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); break; } } @@ -319,21 +311,21 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } // HACK: any waiting dummy threads can wake up now. - kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads(); + kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads(kernel); // HACK: if we are a dummy thread, and we need to go sleep, indicate // that for when the lock is released. KThread* const cur_thread = GetCurrentThreadPointer(kernel); if (cur_thread->IsDummyThread() && cur_thread->GetState() != ThreadState::Runnable) { - cur_thread->RequestDummyThreadWait(); + cur_thread->RequestDummyThreadWait(kernel); } return cores_needing_scheduling; } -void KScheduler::SwitchThread(KThread* next_thread) { - KProcess* const cur_process = GetCurrentProcessPointer(m_kernel); - KThread* const cur_thread = GetCurrentThreadPointer(m_kernel); +void KScheduler::SwitchThread(KernelCore& kernel, KThread* next_thread) { + KProcess* const cur_process = GetCurrentProcessPointer(kernel); + KThread* const cur_thread = GetCurrentThreadPointer(kernel); // We never want to schedule a null thread, so use the idle thread if we don't have a next. if (next_thread == nullptr) { @@ -355,7 +347,7 @@ void KScheduler::SwitchThread(KThread* next_thread) { // Update the CPU time tracking variables. const s64 prev_tick = m_last_context_switch_time; - const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks(); + const s64 cur_tick = kernel.System().CoreTiming().GetClockTicks(); const s64 tick_diff = cur_tick - prev_tick; cur_thread->AddCpuTime(m_core_id, tick_diff); if (cur_process != nullptr) { @@ -379,23 +371,23 @@ void KScheduler::SwitchThread(KThread* next_thread) { // } // Set the new thread. - SetCurrentThread(m_kernel, next_thread); + SetCurrentThread(kernel, next_thread); m_current_thread = next_thread; // Set the new Thread Local region. // cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress())); // Update the thread's cpu time differential in TLS, if relevant. - next_thread->UpdateTlsThreadCpuTime(cur_tick); + next_thread->UpdateTlsThreadCpuTime(kernel, cur_tick); } -void KScheduler::ScheduleImpl() { +void KScheduler::ScheduleImpl(KernelCore& kernel) { // First, clear the needs scheduling bool. m_state.needs_scheduling.store(false, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_seq_cst); // Load the appropriate thread pointers for scheduling. - KThread* const cur_thread{GetCurrentThreadPointer(m_kernel)}; + KThread* const cur_thread{GetCurrentThreadPointer(kernel)}; KThread* highest_priority_thread{m_state.highest_priority_thread}; // Check whether there are runnable interrupt tasks. @@ -423,7 +415,7 @@ void KScheduler::ScheduleImpl() { // Returning from ScheduleImpl occurs after this thread has been scheduled again. } -void KScheduler::ScheduleImplFiber() { +void KScheduler::ScheduleImplFiber(KernelCore& kernel) { KThread* const cur_thread{m_switch_cur_thread}; KThread* highest_priority_thread{m_switch_highest_priority_thread}; @@ -437,7 +429,7 @@ void KScheduler::ScheduleImplFiber() { m_switch_from_schedule = false; // Save the original thread context. - Unload(cur_thread); + Unload(kernel, cur_thread); // The current thread's context has been entirely taken care of. // Now we want to loop until we successfully switch the thread context. @@ -468,7 +460,7 @@ void KScheduler::ScheduleImplFiber() { // It's time to switch the thread. // Switch to the highest priority thread. - SwitchThread(highest_priority_thread); + SwitchThread(kernel, highest_priority_thread); // Check if we need scheduling. If we do, then we can't complete the switch and should // retry. @@ -493,14 +485,14 @@ void KScheduler::ScheduleImplFiber() { } // Reload the guest thread context. - Reload(highest_priority_thread); + Reload(kernel, highest_priority_thread); // Reload the host thread. Common::Fiber::YieldTo(m_switch_fiber, *highest_priority_thread->m_host_context); } -void KScheduler::Unload(KThread* thread) { - m_kernel.PhysicalCore(m_core_id).SaveContext(thread); +void KScheduler::Unload(KernelCore& kernel, KThread* thread) { + kernel.PhysicalCore(m_core_id).SaveContext(thread); // Check if the thread is terminated by checking the DPC flags. if ((thread->GetStackParameters().dpc_flags & static_cast(DpcFlag::Terminated)) == 0) { @@ -509,8 +501,8 @@ void KScheduler::Unload(KThread* thread) { } } -void KScheduler::Reload(KThread* thread) { - m_kernel.PhysicalCore(m_core_id).LoadContext(thread); +void KScheduler::Reload(KernelCore& kernel, KThread* thread) { + kernel.PhysicalCore(m_core_id).LoadContext(thread); } void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { @@ -877,9 +869,9 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { } } -void KScheduler::RescheduleOtherCores(u64 cores_needing_scheduling) { +void KScheduler::RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling) { if (const u64 core_mask = cores_needing_scheduling & ~(1ULL << m_core_id); core_mask != 0) { - RescheduleCores(m_kernel, core_mask); + RescheduleCores(kernel, core_mask); } } diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index d85a0c0408..5a896fd899 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,15 +44,15 @@ public: explicit KScheduler(KernelCore& kernel); ~KScheduler(); - void Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id); - void Activate(); - void OnThreadStart(); - void Unload(KThread* thread); - void Reload(KThread* thread); + void Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id); + void Activate(KernelCore& kernel); + void OnThreadStart(KernelCore& kernel); + void Unload(KernelCore& kernel, KThread* thread); + void Reload(KernelCore& kernel, KThread* thread); - void SetInterruptTaskRunnable(); - void RequestScheduleOnInterrupt(); - void PreemptSingleCore(); + void SetInterruptTaskRunnable(KernelCore& kernel); + void RequestScheduleOnInterrupt(KernelCore& kernel); + void PreemptSingleCore(KernelCore& kernel); u64 GetIdleCount() { return m_state.idle_count; @@ -122,18 +125,18 @@ private: static void RescheduleCurrentHLEThread(KernelCore& kernel); // Instanced private API. - void ScheduleImpl(); - void ScheduleImplFiber(); - void SwitchThread(KThread* next_thread); + void ScheduleImpl(KernelCore& kernel); + void ScheduleImplFiber(KernelCore& kernel); + void SwitchThread(KernelCore& kernel, KThread* next_thread); - void Schedule(); - void ScheduleOnInterrupt(); + void Schedule(KernelCore& kernel); + void ScheduleOnInterrupt(KernelCore& kernel); - void RescheduleOtherCores(u64 cores_needing_scheduling); - void RescheduleCurrentCore(); - void RescheduleCurrentCoreImpl(); + void RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling); + void RescheduleCurrentCore(KernelCore& kernel); + void RescheduleCurrentCoreImpl(KernelCore& kernel); - u64 UpdateHighestPriorityThread(KThread* thread); + u64 UpdateHighestPriorityThread(KernelCore& kernel, KThread* thread); private: friend class KScopedDisableDispatch; @@ -149,14 +152,12 @@ private: KInterruptTaskManager* interrupt_task_manager{nullptr}; }; - KernelCore& m_kernel; SchedulingState m_state; bool m_is_active{false}; s32 m_core_id{0}; s64 m_last_context_switch_time{0}; KThread* m_idle_thread{nullptr}; std::atomic m_current_thread{nullptr}; - std::shared_ptr m_switch_fiber{}; KThread* m_switch_cur_thread{}; KThread* m_switch_highest_priority_thread{}; diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h index 2cc464612a..4fc66af725 100644 --- a/src/core/hle/kernel/k_scoped_resource_reservation.h +++ b/src/core/hle/kernel/k_scoped_resource_reservation.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,34 +14,42 @@ namespace Kernel { class KScopedResourceReservation { public: - explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) - : m_limit(l), m_value(v), m_resource(r) { + explicit KScopedResourceReservation(KernelCore& kernel, KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) + : m_kernel{kernel} + , m_limit(l) + , m_value(v) + , m_resource(r) + { if (m_limit && m_value) { - m_succeeded = m_limit->Reserve(m_resource, m_value, timeout); + m_succeeded = m_limit->Reserve(kernel, m_resource, m_value, timeout); } else { m_succeeded = true; } } - explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1) - : m_limit(l), m_value(v), m_resource(r) { + explicit KScopedResourceReservation(KernelCore& kernel, KResourceLimit* l, LimitableResource r, s64 v = 1) + : m_kernel{kernel} + , m_limit(l) + , m_value(v) + , m_resource(r) + { if (m_limit && m_value) { - m_succeeded = m_limit->Reserve(m_resource, m_value); + m_succeeded = m_limit->Reserve(kernel, m_resource, m_value); } else { m_succeeded = true; } } - explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v, s64 t) - : KScopedResourceReservation(p->GetResourceLimit(), r, v, t) {} + explicit KScopedResourceReservation(KernelCore& kernel, const KProcess* p, LimitableResource r, s64 v, s64 t) + : KScopedResourceReservation(kernel, p->GetResourceLimit(), r, v, t) {} - explicit KScopedResourceReservation(const KProcess* p, LimitableResource r, s64 v = 1) - : KScopedResourceReservation(p->GetResourceLimit(), r, v) {} + explicit KScopedResourceReservation(KernelCore& kernel, const KProcess* p, LimitableResource r, s64 v = 1) + : KScopedResourceReservation(kernel, p->GetResourceLimit(), r, v) {} ~KScopedResourceReservation() noexcept { if (m_limit && m_value && m_succeeded) { // Resource was not committed, release the reservation. - m_limit->Release(m_resource, m_value); + m_limit->Release(m_kernel, m_resource, m_value); } } @@ -52,6 +63,7 @@ public: } private: + KernelCore& m_kernel; KResourceLimit* m_limit{}; s64 m_value{}; LimitableResource m_resource{}; diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index bb6632f58e..dad6ef0678 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,18 +18,18 @@ namespace Kernel { KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} KServerPort::~KServerPort() = default; -void KServerPort::Initialize(KPort* parent) { +void KServerPort::Initialize(KernelCore& kernel, KPort* parent) { // Set member variables. m_parent = parent; } -bool KServerPort::IsLight() const { +bool KServerPort::IsLight(KernelCore& kernel) const { return this->GetParent()->IsLight(); } -void KServerPort::CleanupSessions() { +void KServerPort::CleanupSessions(KernelCore& kernel) { // Ensure our preconditions are met. - if (this->IsLight()) { + if (this->IsLight(kernel)) { ASSERT(m_session_list.empty()); } else { ASSERT(m_light_session_list.empty()); @@ -37,7 +40,7 @@ void KServerPort::CleanupSessions() { // Get the last session in the list. KServerSession* session = nullptr; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!m_session_list.empty()) { session = std::addressof(m_session_list.front()); m_session_list.pop_front(); @@ -46,7 +49,7 @@ void KServerPort::CleanupSessions() { // Close the session. if (session != nullptr) { - session->Close(); + session->Close(kernel); } else { break; } @@ -57,7 +60,7 @@ void KServerPort::CleanupSessions() { // Get the last session in the list. KLightServerSession* session = nullptr; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!m_light_session_list.empty()) { session = std::addressof(m_light_session_list.front()); m_light_session_list.pop_front(); @@ -66,60 +69,60 @@ void KServerPort::CleanupSessions() { // Close the session. if (session != nullptr) { - session->Close(); + session->Close(kernel); } else { break; } } } -void KServerPort::Destroy() { +void KServerPort::Destroy(KernelCore& kernel) { // Note with our parent that we're closed. - m_parent->OnServerClosed(); + m_parent->OnServerClosed(kernel); // Perform necessary cleanup of our session lists. - this->CleanupSessions(); + this->CleanupSessions(kernel); // Close our reference to our parent. - m_parent->Close(); + m_parent->Close(kernel); } -bool KServerPort::IsSignaled() const { - if (this->IsLight()) { +bool KServerPort::IsSignaled(KernelCore& kernel) const { + if (this->IsLight(kernel)) { return !m_light_session_list.empty(); } else { return !m_session_list.empty(); } } -void KServerPort::EnqueueSession(KServerSession* session) { - ASSERT(!this->IsLight()); +void KServerPort::EnqueueSession(KernelCore& kernel, KServerSession* session) { + ASSERT(!this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Add the session to our queue. m_session_list.push_back(*session); if (m_session_list.size() == 1) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } -void KServerPort::EnqueueSession(KLightServerSession* session) { - ASSERT(this->IsLight()); +void KServerPort::EnqueueSession(KernelCore& kernel, KLightServerSession* session) { + ASSERT(this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Add the session to our queue. m_light_session_list.push_back(*session); if (m_light_session_list.size() == 1) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } -KServerSession* KServerPort::AcceptSession() { - ASSERT(!this->IsLight()); +KServerSession* KServerPort::AcceptSession(KernelCore& kernel) { + ASSERT(!this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Return the first session in the list. if (m_session_list.empty()) { @@ -131,10 +134,10 @@ KServerSession* KServerPort::AcceptSession() { return session; } -KLightServerSession* KServerPort::AcceptLightSession() { - ASSERT(this->IsLight()); +KLightServerSession* KServerPort::AcceptLightSession(KernelCore& kernel) { + ASSERT(this->IsLight(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Return the first session in the list. if (m_light_session_list.empty()) { diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index 72fdb6734a..5996a3a3ee 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,29 +29,29 @@ public: explicit KServerPort(KernelCore& kernel); ~KServerPort() override; - void Initialize(KPort* parent); + void Initialize(KernelCore& kernel, KPort* parent); - void EnqueueSession(KServerSession* session); - void EnqueueSession(KLightServerSession* session); + void EnqueueSession(KernelCore& kernel, KServerSession* session); + void EnqueueSession(KernelCore& kernel, KLightServerSession* session); - KServerSession* AcceptSession(); - KLightServerSession* AcceptLightSession(); + KServerSession* AcceptSession(KernelCore& kernel); + KLightServerSession* AcceptLightSession(KernelCore& kernel); const KPort* GetParent() const { return m_parent; } - bool IsLight() const; + bool IsLight(KernelCore& kernel) const; // Overridden virtual functions. - void Destroy() override; - bool IsSignaled() const override; + void Destroy(KernelCore& kernel) override; + bool IsSignaled(KernelCore& kernel) const override; private: using SessionList = Common::IntrusiveListBaseTraits::ListType; using LightSessionList = Common::IntrusiveListBaseTraits::ListType; - void CleanupSessions(); + void CleanupSessions(KernelCore& kernel); SessionList m_session_list{}; LightSessionList m_light_session_list{}; diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 4c91235ac9..e3cfe6b6c2 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -159,7 +159,7 @@ private: }; template -Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& src_process, +Result ProcessMessageSpecialData(KernelCore& kernel, s32& offset, KProcess& dst_process, KProcess& src_process, KThread& src_thread, const MessageBuffer& dst_msg, const MessageBuffer& src_msg, const MessageBuffer::SpecialHeader& src_special_header) { @@ -185,10 +185,9 @@ Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& s // If we're in a success state, try to move the handle to the new table. if (R_SUCCEEDED(result) && src_handle != Svc::InvalidHandle) { KScopedAutoObject obj = - src_handle_table.GetObjectForIpc(src_handle, std::addressof(src_thread)); + src_handle_table.GetObjectForIpc(kernel, src_handle, std::addressof(src_thread)); if (obj.IsNotNull()) { - Result add_result = - dst_handle_table.Add(std::addressof(dst_handle), obj.GetPointerUnsafe()); + Result add_result = dst_handle_table.Add(kernel, std::addressof(dst_handle), obj.GetPointerUnsafe()); if (R_FAILED(add_result)) { result = add_result; dst_handle = Svc::InvalidHandle; @@ -213,12 +212,10 @@ Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& s if (src_handle != Svc::InvalidHandle) { if (R_SUCCEEDED(result)) { KScopedAutoObject obj = - src_handle_table.GetObjectForIpcWithoutPseudoHandle(src_handle); + src_handle_table.GetObjectForIpcWithoutPseudoHandle(kernel, src_handle); if (obj.IsNotNull()) { - Result add_result = dst_handle_table.Add(std::addressof(dst_handle), - obj.GetPointerUnsafe()); - - src_handle_table.Remove(src_handle); + Result add_result = dst_handle_table.Add(kernel, std::addressof(dst_handle), obj.GetPointerUnsafe()); + src_handle_table.Remove(kernel, src_handle); if (R_FAILED(add_result)) { result = add_result; @@ -228,7 +225,7 @@ Result ProcessMessageSpecialData(s32& offset, KProcess& dst_process, KProcess& s result = ResultInvalidHandle; } } else { - src_handle_table.Remove(src_handle); + src_handle_table.Remove(kernel, src_handle); } } @@ -336,7 +333,7 @@ constexpr Result GetMapAliasTestStateAndAttributeMask(KMemoryState& out_state, R_SUCCEED(); } -void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) { +void CleanupSpecialData(KernelCore& kernel, KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) { // Parse the message. const MessageBuffer dst_msg(dst_msg_ptr, dst_buffer_size); const MessageBuffer::MessageHeader dst_header(dst_msg); @@ -363,15 +360,14 @@ void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buff const Handle handle = dst_msg.GetHandle(offset); if (handle != Svc::InvalidHandle) { - dst_handle_table.Remove(handle); + dst_handle_table.Remove(kernel, handle); } offset = dst_msg.SetHandle(offset, Svc::InvalidHandle); } } -Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_size, - KPhysicalAddress message_paddr) { +Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_size, KPhysicalAddress message_paddr) { // Server is assumed to be current thread. KThread& thread = GetCurrentThread(kernel); @@ -410,7 +406,7 @@ Result CleanupServerHandles(KernelCore& kernel, uint64_t message, size_t buffer_ // Close the handles. for (auto i = 0; i < special_header.GetMoveHandleCount(); ++i) { - handle_table.Remove(msg.GetHandle(offset)); + handle_table.Remove(kernel, msg.GetHandle(offset)); offset += static_cast(sizeof(Svc::Handle) / sizeof(u32)); } } @@ -558,7 +554,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m recv_list_broken = false; // Set the server process for the request. - request->SetServerProcess(std::addressof(dst_process)); + request->SetServerProcess(kernel, std::addressof(dst_process)); // Determine the message buffers. u32 *dst_msg_ptr, *src_msg_ptr; @@ -639,7 +635,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m // Cleanup special data. if (src_header.GetHasSpecialHeader()) { - CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size); + CleanupSpecialData(kernel, dst_process, dst_msg_ptr, dst_buffer_size); } // Cleanup the header if the receive list isn't broken. @@ -661,7 +657,7 @@ Result ReceiveMessage(KernelCore& kernel, bool& recv_list_broken, uint64_t dst_m }; // Process special data. - R_TRY(ProcessMessageSpecialData(offset, dst_process, src_process, src_thread, + R_TRY(ProcessMessageSpecialData(kernel, offset, dst_process, src_process, src_thread, dst_msg, src_msg, src_special_header)); } @@ -922,7 +918,7 @@ Result SendMessage(KernelCore& kernel, uint64_t src_message_buffer, size_t src_b // Cleanup special data. if (processed_special_data) { if (src_header.GetHasSpecialHeader()) { - CleanupSpecialData(dst_process, dst_msg_ptr, dst_buffer_size); + CleanupSpecialData(kernel, dst_process, dst_msg_ptr, dst_buffer_size); } } else { CleanupServerHandles(kernel, src_user ? src_message_buffer : 0, src_buffer_size, @@ -987,7 +983,7 @@ Result SendMessage(KernelCore& kernel, uint64_t src_message_buffer, size_t src_b ASSERT(GetCurrentThreadPointer(kernel) == std::addressof(src_thread)); processed_special_data = true; if (src_header.GetHasSpecialHeader()) { - R_TRY(ProcessMessageSpecialData(offset, dst_process, src_process, src_thread, + R_TRY(ProcessMessageSpecialData(kernel, offset, dst_process, src_process, src_thread, dst_msg, src_msg, src_special_header)); } @@ -1080,19 +1076,17 @@ void ReplyAsyncError(KProcess* to_process, uint64_t to_msg_buf, size_t to_msg_bu } // namespace KServerSession::KServerSession(KernelCore& kernel) - : KSynchronizationObject{kernel}, m_lock{m_kernel} {} + : KSynchronizationObject{kernel}, m_lock{kernel} {} KServerSession::~KServerSession() = default; -void KServerSession::Destroy() { - m_parent->OnServerClosed(); - - this->CleanupRequests(); - - m_parent->Close(); +void KServerSession::Destroy(KernelCore& kernel) { + m_parent->OnServerClosed(kernel); + this->CleanupRequests(kernel); + m_parent->Close(kernel); } -Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, +Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, std::shared_ptr* out_context, std::weak_ptr manager) { @@ -1104,7 +1098,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server KThread* client_thread; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Ensure that we can service the request. R_UNLESS(!m_parent->IsClientClosed(), ResultSessionClosed); @@ -1124,11 +1118,11 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server R_UNLESS(client_thread != nullptr, ResultSessionClosed); // Open the client thread. - client_thread->Open(); + client_thread->Open(kernel); } SCOPE_EXIT { - client_thread->Close(); + client_thread->Close(kernel); }; // Set the request as our current. @@ -1150,13 +1144,13 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()}; u32* cmd_buf{reinterpret_cast(memory.GetPointer(client_message))}; *out_context = - std::make_shared(m_kernel, memory, this, client_thread); + std::make_shared(kernel, memory, this, client_thread); (*out_context)->SetSessionRequestManager(manager); (*out_context)->PopulateFromIncomingCommandBuffer(cmd_buf); // We succeeded. R_SUCCEED(); } else { - result = ReceiveMessage(m_kernel, recv_list_broken, server_message, server_buffer_size, + result = ReceiveMessage(kernel, recv_list_broken, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request); } @@ -1168,11 +1162,11 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server // Clear the current request. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_current_request == request); m_current_request = nullptr; if (!m_request_list.empty()) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } @@ -1180,7 +1174,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server { // After we reply, close our reference to the request. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Get the event to check whether the request is async. @@ -1199,13 +1193,13 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server client_pt.UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(); + event->Signal(kernel); } else { // End the client thread's wait. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(result_for_client); + client_thread->EndWait(kernel, result_for_client); } } } @@ -1221,7 +1215,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server R_RETURN(result); } -Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buffer_size, +Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, bool is_hle) { // Lock the session. KScopedLightLock lk{m_lock}; @@ -1229,7 +1223,7 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff // Get the request. KSessionRequest* request; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Get the current request. request = m_current_request; @@ -1238,13 +1232,13 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff // Clear the current request, since we're processing it. m_current_request = nullptr; if (!m_request_list.empty()) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } } // Close reference to the request once we're done processing it. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Extract relevant information from the request. @@ -1263,7 +1257,7 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff // HLE servers write directly to a pointer to the thread command buffer. Therefore // the reply has already been written in this case. } else { - result = SendMessage(m_kernel, server_message, server_buffer_size, server_message_paddr, + result = SendMessage(kernel, server_message, server_buffer_size, server_message_paddr, *client_thread, client_message, client_buffer_size, this, request); } } else if (!is_hle) { @@ -1275,7 +1269,7 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff (client_process != nullptr) ? std::addressof(client_process->GetPageTable()) : nullptr; // Cleanup server handles. - result = CleanupServerHandles(m_kernel, server_message, server_buffer_size, + result = CleanupServerHandles(kernel, server_message, server_buffer_size, server_message_paddr); // Cleanup mappings. @@ -1313,13 +1307,13 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(); + event->Signal(kernel); } else { // End the client thread's wait. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(client_result); + client_thread->EndWait(kernel, client_result); } } } @@ -1327,45 +1321,45 @@ Result KServerSession::SendReply(uintptr_t server_message, uintptr_t server_buff R_RETURN(result); } -Result KServerSession::OnRequest(KSessionRequest* request) { +Result KServerSession::OnRequest(KernelCore& kernel, KSessionRequest* request) { // Create the wait queue. - ThreadQueueImplForKServerSessionRequest wait_queue{m_kernel}; + ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; { // Lock the scheduler. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Ensure that we can handle new requests. R_UNLESS(!m_parent->IsServerClosed(), ResultSessionClosed); // Check that we're not terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Get whether we're empty. const bool was_empty = m_request_list.empty(); // Add the request to the list. - request->Open(); + request->Open(kernel); m_request_list.push_back(*request); // If we were empty, signal. if (was_empty) { - this->NotifyAvailable(); + this->NotifyAvailable(kernel); } // If we have a request event, this is asynchronous, and we don't need to wait. R_SUCCEED_IF(request->GetEvent() != nullptr); // This is a synchronous request, so we should wait for our request to complete. - GetCurrentThread(m_kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } - return GetCurrentThread(m_kernel).GetWaitResult(); + return GetCurrentThread(kernel).GetWaitResult(); } -bool KServerSession::IsSignaled() const { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +bool KServerSession::IsSignaled(KernelCore& kernel) const { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // If the client is closed, we're always signaled. if (m_parent->IsClientClosed()) { @@ -1376,7 +1370,7 @@ bool KServerSession::IsSignaled() const { return !m_request_list.empty() && m_current_request == nullptr; } -void KServerSession::CleanupRequests() { +void KServerSession::CleanupRequests(KernelCore& kernel) { KScopedLightLock lk(m_lock); // Clean up any pending requests. @@ -1384,7 +1378,7 @@ void KServerSession::CleanupRequests() { // Get the next request. KSessionRequest* request = nullptr; { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (m_current_request) { // Choose the current request if we have one. @@ -1404,7 +1398,7 @@ void KServerSession::CleanupRequests() { // Close a reference to the request once it's cleaned up. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // Extract relevant information from the request. @@ -1434,20 +1428,20 @@ void KServerSession::CleanupRequests() { client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size); // Signal the event. - event->Signal(); + event->Signal(kernel); } else { // End the client thread's wait. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (!client_thread->IsTerminationRequested()) { - client_thread->EndWait(ResultSessionClosed); + client_thread->EndWait(kernel, ResultSessionClosed); } } } } } -void KServerSession::OnClientClosed() { +void KServerSession::OnClientClosed(KernelCore& kernel) { KScopedLightLock lk{m_lock}; // Handle any pending requests. @@ -1462,12 +1456,12 @@ void KServerSession::OnClientClosed() { // Get the next request. { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; if (m_current_request != nullptr && m_current_request != prev_request) { // Set the request, open a reference as we process it. request = m_current_request; - request->Open(); + request->Open(kernel); cur_request = true; // Get thread and event for the request. @@ -1503,14 +1497,14 @@ void KServerSession::OnClientClosed() { // Ensure that we close the request when done. SCOPE_EXIT { - request->Close(); + request->Close(kernel); }; // If we're terminating, close a reference to the thread and event. if (terminate) { - thread->Close(); + thread->Close(kernel); if (event != nullptr) { - event->Close(); + event->Close(kernel); } } @@ -1534,12 +1528,12 @@ void KServerSession::OnClientClosed() { client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize()); // Signal the event. - event->Signal(); + event->Signal(kernel); } } // Notify. - this->NotifyAvailable(ResultSessionClosed); + this->NotifyAvailable(kernel, ResultSessionClosed); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 2876c231b2..217e7dc7be 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -36,7 +39,7 @@ public: explicit KServerSession(KernelCore& kernel); ~KServerSession() override; - void Destroy() override; + void Destroy(KernelCore& kernel) override; void Initialize(KSession* p) { m_parent = p; @@ -46,29 +49,29 @@ public: return m_parent; } - bool IsSignaled() const override; - void OnClientClosed(); + bool IsSignaled(KernelCore& kernel) const override; + void OnClientClosed(KernelCore& kernel); - Result OnRequest(KSessionRequest* request); - Result SendReply(uintptr_t server_message, uintptr_t server_buffer_size, + Result OnRequest(KernelCore& kernel, KSessionRequest* request); + Result SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, bool is_hle = false); - Result ReceiveRequest(uintptr_t server_message, uintptr_t server_buffer_size, + Result ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, KPhysicalAddress server_message_paddr, std::shared_ptr* out_context = nullptr, std::weak_ptr manager = {}); - Result SendReplyHLE() { - R_RETURN(this->SendReply(0, 0, 0, true)); + Result SendReplyHLE(KernelCore& kernel) { + R_RETURN(this->SendReply(kernel, 0, 0, 0, true)); } - Result ReceiveRequestHLE(std::shared_ptr* out_context, + Result ReceiveRequestHLE(KernelCore& kernel, std::shared_ptr* out_context, std::weak_ptr manager) { - R_RETURN(this->ReceiveRequest(0, 0, 0, out_context, manager)); + R_RETURN(this->ReceiveRequest(kernel, 0, 0, 0, out_context, manager)); } private: /// Frees up waiting client sessions when this server session is about to die - void CleanupRequests(); + void CleanupRequests(KernelCore& kernel); /// KSession that owns this KServerSession KSession* m_parent{}; diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp index 4a1f6027ee..58b0d5de67 100644 --- a/src/core/hle/kernel/k_session.cpp +++ b/src/core/hle/kernel/k_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,12 +16,12 @@ KSession::KSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_server{kernel}, m_client{kernel} {} KSession::~KSession() = default; -void KSession::Initialize(KClientPort* client_port, uintptr_t name) { +void KSession::Initialize(KernelCore& kernel, KClientPort* client_port, uintptr_t name) { // Increment reference count. // Because reference count is one on creation, this will result // in a reference count of two. Thus, when both server and client are closed // this object will be destroyed. - this->Open(); + this->Open(kernel); // Create our sub sessions. KAutoObject::Create(std::addressof(m_server)); @@ -33,45 +36,45 @@ void KSession::Initialize(KClientPort* client_port, uintptr_t name) { m_name = name; // Set our owner process. - m_process = GetCurrentProcessPointer(m_kernel); - m_process->Open(); + m_process = GetCurrentProcessPointer(kernel); + m_process->Open(kernel); // Set our port. m_port = client_port; if (m_port != nullptr) { - m_port->Open(); + m_port->Open(kernel); } // Mark initialized. m_initialized = true; } -void KSession::Finalize() { +void KSession::Finalize(KernelCore& kernel) { if (m_port != nullptr) { - m_port->OnSessionFinalized(); - m_port->Close(); + m_port->OnSessionFinalized(kernel); + m_port->Close(kernel); } } -void KSession::OnServerClosed() { +void KSession::OnServerClosed(KernelCore& kernel) { if (this->GetState() == State::Normal) { this->SetState(State::ServerClosed); m_client.OnServerClosed(); } } -void KSession::OnClientClosed() { +void KSession::OnClientClosed(KernelCore& kernel) { if (this->GetState() == State::Normal) { - SetState(State::ClientClosed); - m_server.OnClientClosed(); + this->SetState(State::ClientClosed); + m_server.OnClientClosed(kernel); } } -void KSession::PostDestroy(uintptr_t arg) { +void KSession::PostDestroy(KernelCore& kernel, uintptr_t arg) { // Release the session count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); - owner->GetResourceLimit()->Release(LimitableResource::SessionCountMax, 1); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::SessionCountMax, 1); + owner->Close(kernel); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 3f4dd5989f..0d77bc1fd4 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -21,8 +24,8 @@ public: explicit KSession(KernelCore& kernel); ~KSession() override; - void Initialize(KClientPort* port, uintptr_t name); - void Finalize() override; + void Initialize(KernelCore& kernel, KClientPort* port, uintptr_t name); + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_initialized; @@ -32,11 +35,9 @@ public: return reinterpret_cast(m_process); } - static void PostDestroy(uintptr_t arg); - - void OnServerClosed(); - - void OnClientClosed(); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); + void OnServerClosed(KernelCore& kernel); + void OnClientClosed(KernelCore& kernel); bool IsServerClosed() const { return this->GetState() != State::Normal; @@ -46,8 +47,8 @@ public: return this->GetState() != State::Normal; } - Result OnRequest(KSessionRequest* request) { - R_RETURN(m_server.OnRequest(request)); + Result OnRequest(KernelCore& kernel, KSessionRequest* request) { + R_RETURN(m_server.OnRequest(kernel, request)); } KClientSession& GetClientSession() { diff --git a/src/core/hle/kernel/k_session_request.cpp b/src/core/hle/kernel/k_session_request.cpp index 9a69b4ffc1..25451a3922 100644 --- a/src/core/hle/kernel/k_session_request.cpp +++ b/src/core/hle/kernel/k_session_request.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +21,7 @@ Result KSessionRequest::SessionMappings::PushMap(KProcessAddress client, KProces } else { // Allocate a page for the extra mappings. if (m_mappings == nullptr) { - KPageBuffer* page_buffer = KPageBuffer::Allocate(m_kernel); + KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel); R_UNLESS(page_buffer != nullptr, ResultOutOfMemory); m_mappings = reinterpret_cast(page_buffer); @@ -54,7 +57,7 @@ Result KSessionRequest::SessionMappings::PushExchange(KProcessAddress client, void KSessionRequest::SessionMappings::Finalize() { if (m_mappings) { - KPageBuffer::Free(m_kernel, reinterpret_cast(m_mappings)); + KPageBuffer::Free(kernel, reinterpret_cast(m_mappings)); m_mappings = nullptr; } } diff --git a/src/core/hle/kernel/k_session_request.h b/src/core/hle/kernel/k_session_request.h index 283669e0ac..6665eca56f 100644 --- a/src/core/hle/kernel/k_session_request.h +++ b/src/core/hle/kernel/k_session_request.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -56,7 +59,7 @@ public: }; public: - explicit SessionMappings(KernelCore& kernel) : m_kernel(kernel) {} + explicit SessionMappings(KernelCore& kernel_) : kernel(kernel_) {} void Initialize() {} void Finalize(); @@ -155,7 +158,7 @@ public: } private: - KernelCore& m_kernel; + KernelCore& kernel; std::array m_static_mappings{}; Mapping* m_mappings{}; u8 m_num_send{}; @@ -174,26 +177,26 @@ public: return req; } - void Destroy() override { - this->Finalize(); - KSessionRequest::Free(m_kernel, this); + void Destroy(KernelCore& kernel) override { + this->Finalize(kernel); + KSessionRequest::Free(kernel, this); } - void Initialize(KEvent* event, uintptr_t address, size_t size) { + void Initialize(KernelCore& kernel, KEvent* event, uintptr_t address, size_t size) { m_mappings.Initialize(); - m_thread = GetCurrentThreadPointer(m_kernel); + m_thread = GetCurrentThreadPointer(kernel); m_event = event; m_address = address; m_size = size; - m_thread->Open(); + m_thread->Open(kernel); if (m_event != nullptr) { - m_event->Open(); + m_event->Open(kernel); } } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} KThread* GetThread() const { return m_thread; @@ -211,9 +214,9 @@ public: return m_server; } - void SetServerProcess(KProcess* process) { + void SetServerProcess(KernelCore& kernel, KProcess* process) { m_server = process; - m_server->Open(); + m_server->Open(kernel); } void ClearThread() { @@ -289,17 +292,16 @@ public: private: // NOTE: This is public and virtual in Nintendo's kernel. - void Finalize() override { + void Finalize(KernelCore& kernel) override { m_mappings.Finalize(); - if (m_thread) { - m_thread->Close(); + m_thread->Close(kernel); } if (m_event) { - m_event->Close(); + m_event->Close(kernel); } if (m_server) { - m_server->Close(); + m_server->Close(kernel); } } diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index f713968f68..61f2872560 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,7 +18,7 @@ namespace Kernel { KSharedMemory::KSharedMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} KSharedMemory::~KSharedMemory() = default; -Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* owner_process, +Result KSharedMemory::Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory, KProcess* owner_process, Svc::MemoryPermission owner_permission, Svc::MemoryPermission user_permission, std::size_t size) { // Set members. @@ -28,11 +31,10 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow const size_t num_pages = Common::DivideUp(size, PageSize); // Get the resource limit. - KResourceLimit* reslimit = m_kernel.GetSystemResourceLimit(); + KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); // Reserve memory for ourselves. - KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemoryMax, - size); + KScopedResourceReservation memory_reservation(kernel, reslimit, LimitableResource::PhysicalMemoryMax, size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate the memory. @@ -40,12 +42,11 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow //! HACK: Open continuous mapping from sysmodule pool. auto option = KMemoryManager::EncodeOption(KMemoryManager::Pool::Secure, KMemoryManager::Direction::FromBack); - m_physical_address = m_kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); + m_physical_address = kernel.MemoryManager().AllocateAndOpenContinuous(num_pages, 1, option); R_UNLESS(m_physical_address != 0, ResultOutOfMemory); //! Insert the result into our page group. - m_page_group.emplace(m_kernel, - std::addressof(m_kernel.GetSystemSystemResource().GetBlockInfoManager())); + m_page_group.emplace(kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); m_page_group->AddBlock(m_physical_address, num_pages); // Commit our reservation. @@ -53,7 +54,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow // Set our resource limit. m_resource_limit = reslimit; - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // Mark initialized. m_is_initialized = true; @@ -66,14 +67,14 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow R_SUCCEED(); } -void KSharedMemory::Finalize() { +void KSharedMemory::Finalize(KernelCore& kernel) { // Close and finalize the page group. - m_page_group->Close(); + m_page_group->Close(kernel); m_page_group->Finalize(); // Release the memory reservation. - m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, m_size); - m_resource_limit->Close(); + m_resource_limit->Release(kernel, LimitableResource::PhysicalMemoryMax, m_size); + m_resource_limit->Close(kernel); } Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std::size_t map_size, diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 54b23d7ac2..3aede457c9 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,7 +29,7 @@ public: explicit KSharedMemory(KernelCore& kernel); ~KSharedMemory() override; - Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, + Result Initialize(KernelCore& kernel, Core::DeviceMemory& device_memory_, KProcess* owner_process_, Svc::MemoryPermission owner_permission_, Svc::MemoryPermission user_permission_, std::size_t size_); @@ -66,12 +69,12 @@ public: return m_device_memory->GetPointer(m_physical_address + offset); } - void Finalize() override; + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} private: Core::DeviceMemory* m_device_memory{}; diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 3e5b735b1e..221cab655f 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,12 +21,10 @@ namespace { class ThreadQueueImplForKSynchronizationObjectWait final : public KThreadQueueWithoutEndWait { public: - ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel, KSynchronizationObject** o, - KSynchronizationObject::ThreadListNode* n, s32 c) + ThreadQueueImplForKSynchronizationObjectWait(KernelCore& kernel, KSynchronizationObject** o, KSynchronizationObject::ThreadListNode* n, s32 c) : KThreadQueueWithoutEndWait(kernel), m_objects(o), m_nodes(n), m_count(c) {} - void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - Result wait_result) override { + void NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result) override { // Determine the sync index, and unlink all nodes. s32 sync_index = -1; for (auto i = 0; i < m_count; ++i) { @@ -43,10 +44,10 @@ public: waiting_thread->ClearCancellable(); // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove all nodes from our list. for (auto i = 0; i < m_count; ++i) { m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); @@ -56,7 +57,7 @@ public: waiting_thread->ClearCancellable(); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -67,9 +68,9 @@ private: } // namespace -void KSynchronizationObject::Finalize() { +void KSynchronizationObject::Finalize(KernelCore& kernel) { this->OnFinalizeSynchronizationObject(); - KAutoObject::Finalize(); + KAutoObject::Finalize(kernel); } Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, @@ -98,7 +99,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, for (auto i = 0; i < num_objects; ++i) { ASSERT(objects[i] != nullptr); - if (objects[i]->IsSignaled()) { + if (objects[i]->IsSignaled(kernel)) { *out_index = i; slp.CancelSleep(); R_THROW(ResultSuccess); @@ -134,7 +135,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, // Wait for an object to be signaled. wait_queue.SetHardwareTimer(timer); - thread->BeginWait(std::addressof(wait_queue)); + thread->BeginWait(kernel, std::addressof(wait_queue)); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); } @@ -149,26 +150,26 @@ KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : KAutoObject KSynchronizationObject::~KSynchronizationObject() = default; -void KSynchronizationObject::NotifyAvailable(Result result) { - KScopedSchedulerLock sl(m_kernel); +void KSynchronizationObject::NotifyAvailable(KernelCore& kernel, Result result) { + KScopedSchedulerLock sl(kernel); // If we're not signaled, we've nothing to notify. - if (!this->IsSignaled()) { + if (!this->IsSignaled(kernel)) { return; } // Iterate over each thread. for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { - cur_node->thread->NotifyAvailable(this, result); + cur_node->thread->NotifyAvailable(kernel, this, result); } } -std::vector KSynchronizationObject::GetWaitingThreadsForDebugging() const { +std::vector KSynchronizationObject::GetWaitingThreadsForDebugging(KernelCore& kernel) const { std::vector threads; // If debugging, dump the list of waiters. { - KScopedSchedulerLock lock(m_kernel); + KScopedSchedulerLock lock(kernel); for (auto* cur_node = m_thread_list_head; cur_node != nullptr; cur_node = cur_node->next) { threads.emplace_back(cur_node->thread); } diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index d55a2673df..4c54a4d2cb 100644 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -24,14 +27,13 @@ public: KThread* thread{}; }; - static Result Wait(KernelCore& kernel, s32* out_index, KSynchronizationObject** objects, - const s32 num_objects, s64 timeout); + static Result Wait(KernelCore& kernel, s32* out_index, KSynchronizationObject** objects, const s32 num_objects, s64 timeout); - void Finalize() override; + void Finalize(KernelCore& kernel) override; - virtual bool IsSignaled() const = 0; + virtual bool IsSignaled(KernelCore& kernel) const = 0; - std::vector GetWaitingThreadsForDebugging() const; + std::vector GetWaitingThreadsForDebugging(KernelCore& kernel) const; void LinkNode(ThreadListNode* node_) { // Link the node to the list. @@ -71,9 +73,9 @@ protected: virtual void OnFinalizeSynchronizationObject() {} - void NotifyAvailable(Result result); - void NotifyAvailable() { - return this->NotifyAvailable(ResultSuccess); + void NotifyAvailable(KernelCore& kernel, Result result); + void NotifyAvailable(KernelCore& kernel) { + return this->NotifyAvailable(kernel, ResultSuccess); } private: diff --git a/src/core/hle/kernel/k_system_resource.cpp b/src/core/hle/kernel/k_system_resource.cpp index b51941faf4..fb664eb57a 100644 --- a/src/core/hle/kernel/k_system_resource.cpp +++ b/src/core/hle/kernel/k_system_resource.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,8 +10,7 @@ namespace Kernel { -Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit, - KMemoryManager::Pool pool) { +Result KSecureSystemResource::Initialize(KernelCore& kernel, size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool) { // Set members. m_resource_limit = resource_limit; m_resource_size = size; @@ -18,18 +20,17 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l const size_t secure_size = this->CalculateRequiredSecureMemorySize(); // Reserve memory for our secure resource. - KScopedResourceReservation memory_reservation( - m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size); + KScopedResourceReservation memory_reservation(kernel, m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate secure memory. - R_TRY(KSystemControl::AllocateSecureMemory(m_kernel, std::addressof(m_resource_address), + R_TRY(KSystemControl::AllocateSecureMemory(kernel, std::addressof(m_resource_address), m_resource_size, static_cast(m_resource_pool))); ASSERT(m_resource_address != 0); // Ensure we clean up the secure memory, if we fail past this point. ON_RESULT_FAILURE { - KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size, + KSystemControl::FreeSecureMemory(kernel, m_resource_address, m_resource_size, static_cast(m_resource_pool)); }; @@ -40,9 +41,9 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l // Get resource pointer. KPhysicalAddress resource_paddr = - KPageTable::GetHeapPhysicalAddress(m_kernel, m_resource_address); + KPageTable::GetHeapPhysicalAddress(kernel, m_resource_address); auto* resource = - m_kernel.System().DeviceMemory().GetPointer(resource_paddr); + kernel.System().DeviceMemory().GetPointer(resource_paddr); // Initialize slab heaps. m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, @@ -66,7 +67,7 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l memory_reservation.Commit(); // Open reference to our resource limit. - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // Set ourselves as initialized. m_is_initialized = true; @@ -74,26 +75,25 @@ Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_l R_SUCCEED(); } -void KSecureSystemResource::Finalize() { +void KSecureSystemResource::Finalize(KernelCore& kernel) { // Check that we have no outstanding allocations. ASSERT(m_memory_block_slab_manager.GetUsed() == 0); ASSERT(m_block_info_manager.GetUsed() == 0); ASSERT(m_page_table_manager.GetUsed() == 0); // Free our secure memory. - KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size, + KSystemControl::FreeSecureMemory(kernel, m_resource_address, m_resource_size, static_cast(m_resource_pool)); // Release the memory reservation. - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, this->CalculateRequiredSecureMemorySize()); // Close reference to our resource limit. - m_resource_limit->Close(); + m_resource_limit->Close(kernel); } -size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, - KMemoryManager::Pool pool) { +size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool) { return KSystemControl::CalculateRequiredSecureMemorySize(size, static_cast(pool)); } diff --git a/src/core/hle/kernel/k_system_resource.h b/src/core/hle/kernel/k_system_resource.h index 6ea4821858..c0362497f9 100644 --- a/src/core/hle/kernel/k_system_resource.h +++ b/src/core/hle/kernel/k_system_resource.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,7 +32,7 @@ protected: } public: - virtual void Destroy() override { + virtual void Destroy(KernelCore& kernel) override { UNREACHABLE_MSG("KSystemResource::Destroy() was called"); } @@ -93,13 +96,13 @@ public: this->SetSecureResource(); } - Result Initialize(size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool); - void Finalize(); + Result Initialize(KernelCore& kernel, size_t size, KResourceLimit* resource_limit, KMemoryManager::Pool pool); + void Finalize(KernelCore& kernel); bool IsInitialized() const { return m_is_initialized; } - static void PostDestroy(uintptr_t arg) {} + static void PostDestroy(KernelCore& kernel, uintptr_t arg) {} size_t CalculateRequiredSecureMemorySize() const { return CalculateRequiredSecureMemorySize(m_resource_size, m_resource_pool); diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 0af315d726..b499bd4073 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -95,12 +95,12 @@ namespace Kernel { explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel, KThread::WaiterList* wl) : KThreadQueue(kernel), m_wait_list(wl) {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread from the wait list. m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } private: @@ -113,7 +113,7 @@ namespace Kernel { : KAutoObjectWithSlabHeapAndContainer{kernel}, m_activity_pause_lock{kernel} {} KThread::~KThread() = default; - Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, + Result KThread::Initialize(KernelCore& kernel, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type) { // Assert parameters are valid. ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) || @@ -225,12 +225,12 @@ namespace Kernel { if (owner != nullptr) { // Setup the TLS, if needed. if (type == ThreadType::User) { - R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address))); + R_TRY(owner->CreateThreadLocalRegion(kernel, std::addressof(m_tls_address))); owner->GetMemory().ZeroBlock(m_tls_address, Svc::ThreadLocalRegionSize); } m_parent = owner; - m_parent->Open(); + m_parent->Open(kernel); } // Initialize thread context. @@ -247,28 +247,28 @@ namespace Kernel { this->SetInExceptionHandler(); // Set thread ID. - m_thread_id = m_kernel.CreateNewThreadID(); + m_thread_id = kernel.CreateNewThreadID(); // We initialized! m_initialized = true; // Register ourselves with our parent process. if (m_parent != nullptr) { - m_parent->RegisterThread(this); + m_parent->RegisterThread(kernel, this); if (m_parent->IsSuspended()) { - RequestSuspend(SuspendType::Process); + RequestSuspend(kernel, SuspendType::Process); } } R_SUCCEED(); } - Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, + Result KThread::InitializeThread(KernelCore& kernel, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess* owner, ThreadType type, std::function&& init_func) { // Initialize the thread. - R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); + R_TRY(thread->Initialize(kernel, func, arg, user_stack_top, prio, core, owner, type)); // Initialize emulation parameters. thread->m_host_context = std::make_shared(std::move(init_func)); @@ -276,9 +276,9 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) { + Result KThread::InitializeDummyThread(Core::System& system, KThread* thread, KProcess* owner) { // Initialize the thread. - R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); + R_TRY(thread->Initialize(system.Kernel(), {}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); // Initialize emulation parameters. thread->m_stack_parameters.disable_count = 0; @@ -287,37 +287,27 @@ namespace Kernel { } Result KThread::InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, - ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc(system.Kernel()))); } Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, - ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc(system.Kernel()))); } - Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, - KThreadFunction func, uintptr_t arg, s32 virt_core) { - R_RETURN(InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, - ThreadType::HighPriority, - system.GetCpuManager().GetShutdownThreadStartFunc())); + Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, s32 virt_core) { + R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, system.GetCpuManager().GetShutdownThreadStartFunc(system.Kernel()))); } - Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, - uintptr_t arg, KProcessAddress user_stack_top, s32 prio, - s32 virt_core, KProcess* owner) { + Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); - R_RETURN(InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, - ThreadType::User, system.GetCpuManager().GetGuestThreadFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, user_stack_top, prio, virt_core, owner, ThreadType::User, system.GetCpuManager().GetGuestThreadFunc(system.Kernel()))); } - Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, - std::function&& func, s32 prio, s32 virt_core, - KProcess* owner) { + Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, std::function&& func, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); std::function func2{[&system, func_{std::move(func)}] { // Similar to UserModeThreadStarter. - system.Kernel().CurrentScheduler()->OnThreadStart(); + system.Kernel().CurrentScheduler()->OnThreadStart(system.Kernel()); // Run the guest function. func_(); @@ -326,35 +316,35 @@ namespace Kernel { Svc::ExitThread(system); }}; - R_RETURN(InitializeThread(thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority, + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority, std::move(func2))); } - void KThread::PostDestroy(uintptr_t arg) { + void KThread::PostDestroy(KernelCore& kernel, uintptr_t arg) { KProcess* owner = reinterpret_cast(arg & ~1ULL); const bool resource_limit_release_hint = (arg & 1); const s64 hint_value = (resource_limit_release_hint ? 0 : 1); if (owner != nullptr) { - owner->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1, hint_value); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::ThreadCountMax, 1, hint_value); + owner->Close(kernel); } } - void KThread::Finalize() { + void KThread::Finalize(KernelCore& kernel) { // If the thread has an owner process, unregister it. if (m_parent != nullptr) { - m_parent->UnregisterThread(this); + m_parent->UnregisterThread(kernel, this); } // If the thread has a local region, delete it. if (m_tls_address != 0) { - ASSERT(m_parent->DeleteThreadLocalRegion(m_tls_address).IsSuccess()); + ASSERT(m_parent->DeleteThreadLocalRegion(kernel, m_tls_address).IsSuccess()); } // Release any waiters. { ASSERT(m_waiting_lock_info == nullptr); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Check that we have no kernel waiters. ASSERT(m_num_kernel_waiters == 0); @@ -378,14 +368,14 @@ namespace Kernel { } // Cancel the thread's wait. - waiter->CancelWait(ResultInvalidState, true); + waiter->CancelWait(kernel, ResultInvalidState, true); } // Remove the held lock from our list. it = m_held_lock_info_list.erase(it); // Free the lock info. - LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(kernel, lock_info); } } @@ -393,35 +383,35 @@ namespace Kernel { m_host_context.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(); + KSynchronizationObject::Finalize(kernel); } - bool KThread::IsSignaled() const { + bool KThread::IsSignaled(KernelCore& kernel) const { return m_signaled; } - void KThread::OnTimer() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::OnTimer(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // If we're waiting, cancel the wait. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(this, ResultTimedOut, false); + m_wait_queue->CancelWait(kernel, this, ResultTimedOut, false); } } - void KThread::StartTermination() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::StartTermination(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Release user exception and unpin, if relevant. if (m_parent != nullptr) { - m_parent->ReleaseUserException(this); - if (m_parent->GetPinnedThread(GetCurrentCoreId(m_kernel)) == this) { - m_parent->UnpinCurrentThread(); + m_parent->ReleaseUserException(kernel, this); + if (m_parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) { + m_parent->UnpinCurrentThread(kernel); } } // Set state to terminated. - this->SetState(ThreadState::Terminated); + this->SetState(kernel, ThreadState::Terminated); // Clear the thread's status as running in parent. if (m_parent != nullptr) { @@ -429,41 +419,41 @@ namespace Kernel { } // Clear previous thread in KScheduler. - KScheduler::ClearPreviousThread(m_kernel, this); + KScheduler::ClearPreviousThread(kernel, this); // Register terminated dpc flag. this->RegisterDpc(DpcFlag::Terminated); } - void KThread::FinishTermination() { + void KThread::FinishTermination(KernelCore& kernel) { // Ensure that the thread is not executing on any core. if (m_parent != nullptr) { - for (std::size_t i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { + for (std::size_t i = 0; i < std::size_t(Core::Hardware::NUM_CPU_CORES); ++i) { KThread* core_thread{}; do { - core_thread = m_kernel.Scheduler(i).GetSchedulerCurrentThread(); + core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread(); } while (core_thread == this); } } // Acquire the scheduler lock. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Signal. m_signaled = true; - KSynchronizationObject::NotifyAvailable(); + KSynchronizationObject::NotifyAvailable(kernel); // Close the thread. - this->Close(); + this->Close(kernel); } - void KThread::DoWorkerTaskImpl() { + void KThread::DoWorkerTaskImpl(KernelCore& kernel) { // Finish the termination that was begun by Exit(). - this->FinishTermination(); + this->FinishTermination(kernel); } - void KThread::Pin(s32 current_core) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::Pin(KernelCore& kernel, s32 current_core) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set ourselves as pinned. GetStackParameters().is_pinned = true; @@ -487,7 +477,7 @@ namespace Kernel { if (active_core != current_core || m_physical_affinity_mask.GetAffinityMask() != m_original_physical_affinity_mask.GetAffinityMask()) { - KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, + KScheduler::OnThreadAffinityMaskChanged(kernel, this, m_original_physical_affinity_mask, active_core); } } @@ -499,15 +489,15 @@ namespace Kernel { static_cast(ThreadState::SuspendShift))); // Update our state. - this->UpdateState(); + this->UpdateState(kernel); } // TODO(bunnei): Update our SVC access permissions. ASSERT(m_parent != nullptr); } - void KThread::Unpin() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::Unpin(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set ourselves as unpinned. this->GetStackParameters().is_pinned = false; @@ -535,7 +525,7 @@ namespace Kernel { std::countl_zero(m_physical_affinity_mask.GetAffinityMask()))); } } - KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, old_mask, active_core); + KScheduler::OnThreadAffinityMaskChanged(kernel, this, old_mask, active_core); } } @@ -546,20 +536,19 @@ namespace Kernel { static_cast(ThreadState::SuspendShift))); // Update our state. - this->UpdateState(); + this->UpdateState(kernel); } // TODO(bunnei): Update our SVC access permissions. ASSERT(m_parent != nullptr); // Resume any threads that began waiting on us while we were pinned. - for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); - it = m_pinned_waiter_list.erase(it)) { - it->EndWait(ResultSuccess); - } + for (auto it = m_pinned_waiter_list.begin(); it != m_pinned_waiter_list.end(); it = m_pinned_waiter_list.erase(it)) { + it->EndWait(kernel, ResultSuccess); + } } - u16 KThread::GetUserDisableCount() const { + u16 KThread::GetUserDisableCount(KernelCore& kernel) const { if (!this->IsUserThread()) { // We only emulate TLS for user threads return {}; @@ -569,7 +558,7 @@ namespace Kernel { return memory.Read16(m_tls_address + offsetof(ThreadLocalRegion, disable_count)); } - void KThread::SetInterruptFlag() { + void KThread::SetInterruptFlag(KernelCore& kernel) { if (!this->IsUserThread()) { // We only emulate TLS for user threads return; @@ -579,7 +568,7 @@ namespace Kernel { memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1); } - void KThread::ClearInterruptFlag() { + void KThread::ClearInterruptFlag(KernelCore& kernel) { if (!this->IsUserThread()) { // We only emulate TLS for user threads return; @@ -589,7 +578,7 @@ namespace Kernel { memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0); } - void KThread::UpdateTlsThreadCpuTime(s64 switch_tick) { + void KThread::UpdateTlsThreadCpuTime(KernelCore& kernel, s64 switch_tick) { if (!this->IsUserThread()) { return; } @@ -602,8 +591,8 @@ namespace Kernel { memory.Write64(m_tls_address + offsetof(ThreadLocalRegion, thread_cpu_time), static_cast(value)); } - Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { - KScopedSchedulerLock sl{m_kernel}; + Result KThread::GetCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask) { + KScopedSchedulerLock sl{kernel}; // Get the virtual mask. *out_ideal_core = m_virtual_ideal_core_id; @@ -612,8 +601,8 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { - KScopedSchedulerLock sl{m_kernel}; + Result KThread::GetPhysicalCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask) { + KScopedSchedulerLock sl{kernel}; ASSERT(m_num_core_migration_disables >= 0); // Select between core mask and original core mask. @@ -628,7 +617,7 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { + Result KThread::SetCoreMask(KernelCore& kernel, s32 core_id, u64 v_affinity_mask) { ASSERT(m_parent != nullptr); ASSERT(v_affinity_mask != 0); KScopedLightLock lk(m_activity_pause_lock); @@ -636,7 +625,7 @@ namespace Kernel { // Set the core mask. u64 p_affinity_mask = 0; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_num_core_migration_disables >= 0); // If we're updating, set our ideal virtual core. @@ -682,7 +671,7 @@ namespace Kernel { std::countl_zero(m_physical_affinity_mask.GetAffinityMask())); SetActiveCore(new_core); } - KScheduler::OnThreadAffinityMaskChanged(m_kernel, this, old_mask, active_core); + KScheduler::OnThreadAffinityMaskChanged(kernel, this, old_mask, active_core); } } else { // Otherwise, we edit the original affinity for restoration later. @@ -692,12 +681,12 @@ namespace Kernel { } // Update the pinned waiter list. - ThreadQueueImplForKThreadSetProperty wait_queue(m_kernel, std::addressof(m_pinned_waiter_list)); + ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(m_pinned_waiter_list)); { bool retry_update{}; do { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(this->IsTerminationRequested()); @@ -710,7 +699,7 @@ namespace Kernel { s32 thread_core; for (thread_core = 0; thread_core < static_cast(Core::Hardware::NUM_CPU_CORES); ++thread_core) { - if (m_kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) { + if (kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) { thread_is_current = true; break; } @@ -722,12 +711,12 @@ namespace Kernel { // If the thread is pinned, we want to wait until it's not pinned. if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Wait until the thread isn't pinned any more. - m_pinned_waiter_list.push_back(GetCurrentThread(m_kernel)); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + m_pinned_waiter_list.push_back(GetCurrentThread(kernel)); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } else { // If the thread isn't pinned, release the scheduler lock and retry until it's // not current. @@ -740,25 +729,25 @@ namespace Kernel { R_SUCCEED(); } - void KThread::SetBasePriority(s32 value) { + void KThread::SetBasePriority(KernelCore& kernel, s32 value) { ASSERT(Svc::HighestThreadPriority <= value && value <= Svc::LowestThreadPriority); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Change our base priority. m_base_priority = value; // Perform a priority restoration. - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); } - KThread* KThread::GetLockOwner() const { + KThread* KThread::GetLockOwner(KernelCore& kernel) const { return m_waiting_lock_info != nullptr ? m_waiting_lock_info->GetOwner() : nullptr; } - void KThread::IncreaseBasePriority(s32 priority) { + void KThread::IncreaseBasePriority(KernelCore& kernel, s32 priority) { ASSERT(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority); - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(!this->GetStackParameters().is_pinned); // Set our base priority. @@ -766,47 +755,47 @@ namespace Kernel { m_base_priority = priority; // Perform a priority restoration. - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); } } - void KThread::RequestSuspend(SuspendType type) { - KScopedSchedulerLock sl{m_kernel}; + void KThread::RequestSuspend(KernelCore& kernel, SuspendType type) { + KScopedSchedulerLock sl{kernel}; // Note the request in our flags. m_suspend_request_flags |= (1U << (static_cast(ThreadState::SuspendShift) + static_cast(type))); // Try to perform the suspend. - this->TrySuspend(); + this->TrySuspend(kernel); } - void KThread::Resume(SuspendType type) { - KScopedSchedulerLock sl{m_kernel}; + void KThread::Resume(KernelCore& kernel, SuspendType type) { + KScopedSchedulerLock sl{kernel}; // Clear the request in our flags. m_suspend_request_flags &= ~(1U << (static_cast(ThreadState::SuspendShift) + static_cast(type))); // Update our state. - this->UpdateState(); + this->UpdateState(kernel); } - void KThread::WaitCancel() { - KScopedSchedulerLock sl{m_kernel}; + void KThread::WaitCancel(KernelCore& kernel) { + KScopedSchedulerLock sl{kernel}; // Check if we're waiting and cancellable. if (this->GetState() == ThreadState::Waiting && m_cancellable) { m_wait_cancelled = false; - m_wait_queue->CancelWait(this, ResultCancelled, true); + m_wait_queue->CancelWait(kernel, this, ResultCancelled, true); } else { // Otherwise, note that we cancelled a wait. m_wait_cancelled = true; } } - void KThread::TrySuspend() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::TrySuspend(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(this->IsSuspendRequested()); // Ensure that we have no waiters. @@ -816,11 +805,11 @@ namespace Kernel { ASSERT(this->GetNumKernelWaiters() == 0); // Perform the suspend. - this->UpdateState(); + this->UpdateState(kernel); } - void KThread::UpdateState() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::UpdateState(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set our suspend flags in state. const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); @@ -830,37 +819,37 @@ namespace Kernel { // Note the state change in scheduler. if (new_state != old_state) { - KScheduler::OnThreadStateChanged(m_kernel, this, old_state); + KScheduler::OnThreadStateChanged(kernel, this, old_state); } } - void KThread::Continue() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::Continue(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Clear our suspend flags in state. const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); m_thread_state.store(old_state & ThreadState::Mask, std::memory_order_relaxed); // Note the state change in scheduler. - KScheduler::OnThreadStateChanged(m_kernel, this, old_state); + KScheduler::OnThreadStateChanged(kernel, this, old_state); } - void KThread::CloneFpuStatus() { + void KThread::CloneFpuStatus(KernelCore& kernel) { // We shouldn't reach here when starting kernel threads. ASSERT(this->GetOwnerProcess() != nullptr); - ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(m_kernel)); + ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel)); - m_kernel.CurrentPhysicalCore().CloneFpuStatus(this); + kernel.CurrentPhysicalCore().CloneFpuStatus(this); } - Result KThread::SetActivity(Svc::ThreadActivity activity) { + Result KThread::SetActivity(KernelCore& kernel, Svc::ThreadActivity activity) { // Lock ourselves. KScopedLightLock lk(m_activity_pause_lock); // Set the activity. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Verify our state. const auto cur_state = this->GetState(); @@ -873,7 +862,7 @@ namespace Kernel { R_UNLESS(!this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Suspend. - this->RequestSuspend(SuspendType::Thread); + this->RequestSuspend(kernel, SuspendType::Thread); } else { ASSERT(activity == Svc::ThreadActivity::Runnable); @@ -881,19 +870,19 @@ namespace Kernel { R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); // Resume. - this->Resume(SuspendType::Thread); + this->Resume(kernel, SuspendType::Thread); } } // If the thread is now paused, update the pinned waiter list. if (activity == Svc::ThreadActivity::Paused) { - ThreadQueueImplForKThreadSetProperty wait_queue(m_kernel, + ThreadQueueImplForKThreadSetProperty wait_queue(kernel, std::addressof(m_pinned_waiter_list)); bool thread_is_current{}; do { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Don't do any further management if our termination has been requested. R_SUCCEED_IF(this->IsTerminationRequested()); @@ -904,17 +893,17 @@ namespace Kernel { // Check whether the thread is pinned. if (this->GetStackParameters().is_pinned) { // Verify that the current thread isn't terminating. - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Wait until the thread isn't pinned any more. - m_pinned_waiter_list.push_back(GetCurrentThread(m_kernel)); - GetCurrentThread(m_kernel).BeginWait(std::addressof(wait_queue)); + m_pinned_waiter_list.push_back(GetCurrentThread(kernel)); + GetCurrentThread(kernel).BeginWait(kernel, std::addressof(wait_queue)); } else { // Check if the thread is currently running. // If it is, we'll need to retry. for (auto i = 0; i < static_cast(Core::Hardware::NUM_CPU_CORES); ++i) { - if (m_kernel.Scheduler(i).GetSchedulerCurrentThread() == this) { + if (kernel.Scheduler(i).GetSchedulerCurrentThread() == this) { thread_is_current = true; break; } @@ -926,14 +915,14 @@ namespace Kernel { R_SUCCEED(); } - Result KThread::GetThreadContext3(Svc::ThreadContext* out) { + Result KThread::GetThreadContext3(KernelCore& kernel, Svc::ThreadContext* out) { // Lock ourselves. KScopedLightLock lk{m_activity_pause_lock}; // Get the context. { // Lock the scheduler. - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Verify that we're suspended. R_UNLESS(this->IsSuspendRequested(SuspendType::Thread), ResultInvalidState); @@ -957,8 +946,8 @@ namespace Kernel { R_SUCCEED(); } - void KThread::AddHeldLock(LockWithPriorityInheritanceInfo* lock_info) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::AddHeldLock(KernelCore& kernel, LockWithPriorityInheritanceInfo* lock_info) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Set ourselves as the lock's owner. lock_info->SetOwner(this); @@ -967,23 +956,21 @@ namespace Kernel { m_held_lock_info_list.push_front(*lock_info); } - KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KProcessAddress address_key, - bool is_kernel_address_key) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(KernelCore& kernel, KProcessAddress address_key, bool is_kernel_address_key) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Try to find an existing held lock. for (auto& held_lock : m_held_lock_info_list) { - if (held_lock.GetAddressKey() == address_key && - held_lock.GetIsKernelAddressKey() == is_kernel_address_key) { + if (held_lock.GetAddressKey() == address_key && held_lock.GetIsKernelAddressKey() == is_kernel_address_key) { return std::addressof(held_lock); - } + } } return nullptr; } - void KThread::AddWaiterImpl(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::AddWaiterImpl(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(thread->GetConditionVariableTree() == nullptr); // Get the thread's address key. @@ -993,31 +980,31 @@ namespace Kernel { // Keep track of how many kernel waiters we have. if (is_kernel_address_key) { ASSERT((m_num_kernel_waiters++) >= 0); - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(address_key, is_kernel_address_key); + auto* lock_info = this->FindHeldLock(kernel, address_key, is_kernel_address_key); if (lock_info == nullptr) { // Create a new lock for the address key. lock_info = - LockWithPriorityInheritanceInfo::Create(m_kernel, address_key, is_kernel_address_key); + LockWithPriorityInheritanceInfo::Create(kernel, address_key, is_kernel_address_key); // Add the new lock to our list. - this->AddHeldLock(lock_info); + this->AddHeldLock(kernel, lock_info); } // Add the thread as waiter to the lock info. lock_info->AddWaiter(thread); } - void KThread::RemoveWaiterImpl(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::RemoveWaiterImpl(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Keep track of how many kernel waiters we have. if (thread->GetIsKernelAddressKey()) { ASSERT((m_num_kernel_waiters--) > 0); - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } // Get the info for the lock the thread is waiting on. @@ -1027,7 +1014,7 @@ namespace Kernel { // Remove the waiter. if (lock_info->RemoveWaiter(thread)) { m_held_lock_info_list.erase(m_held_lock_info_list.iterator_to(*lock_info)); - LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(kernel, lock_info); } } @@ -1048,12 +1035,12 @@ namespace Kernel { } // Get the owner of whatever lock this thread is waiting on. - KThread* const lock_owner = thread->GetLockOwner(); + KThread* const lock_owner = thread->GetLockOwner(kernel); // If the thread is waiting on some lock, remove it as a waiter to prevent violating red // black tree invariants. if (lock_owner != nullptr) { - lock_owner->RemoveWaiterImpl(thread); + lock_owner->RemoveWaiterImpl(kernel, thread); } // Ensure we don't violate condition variable red black tree invariants. @@ -1072,7 +1059,7 @@ namespace Kernel { // If we removed the thread from some lock's waiting list, add it back. if (lock_owner != nullptr) { - lock_owner->AddWaiterImpl(thread); + lock_owner->AddWaiterImpl(kernel, thread); } // Update the scheduler. @@ -1083,32 +1070,30 @@ namespace Kernel { } } - void KThread::AddWaiter(KThread* thread) { - this->AddWaiterImpl(thread); + void KThread::AddWaiter(KernelCore& kernel, KThread* thread) { + this->AddWaiterImpl(kernel, thread); // If the thread has a higher priority than us, we should inherit. if (thread->GetPriority() < this->GetPriority()) { - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); } } - void KThread::RemoveWaiter(KThread* thread) { - this->RemoveWaiterImpl(thread); + void KThread::RemoveWaiter(KernelCore& kernel, KThread* thread) { + this->RemoveWaiterImpl(kernel, thread); // If our priority is the same as the thread's (and we've inherited), we may need to restore to // lower priority. - if (this->GetPriority() == thread->GetPriority() && - this->GetPriority() < this->GetBasePriority()) { - RestorePriority(m_kernel, this); - } + if (this->GetPriority() == thread->GetPriority() && this->GetPriority() < this->GetBasePriority()) { + RestorePriority(kernel, this); + } } - KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, - bool is_kernel_address_key_) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + KThread* KThread::RemoveWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key_) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the relevant lock info. - auto* lock_info = this->FindHeldLock(key, is_kernel_address_key_); + auto* lock_info = this->FindHeldLock(kernel, key, is_kernel_address_key_); if (lock_info == nullptr) { *out_has_waiters = false; return nullptr; @@ -1121,7 +1106,7 @@ namespace Kernel { if (lock_info->GetIsKernelAddressKey()) { m_num_kernel_waiters -= lock_info->GetWaiterCount(); ASSERT(m_num_kernel_waiters >= 0); - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } ASSERT(lock_info->GetWaiterCount() > 0); @@ -1133,13 +1118,13 @@ namespace Kernel { *out_has_waiters = false; // Free the lock info, since it has no waiters. - LockWithPriorityInheritanceInfo::Free(m_kernel, lock_info); + LockWithPriorityInheritanceInfo::Free(kernel, lock_info); } else { // There are additional waiters on the lock. *out_has_waiters = true; // Add the lock to the new owner's held list. - next_lock_owner->AddHeldLock(lock_info); + next_lock_owner->AddHeldLock(kernel, lock_info); // Keep track of any kernel waiters for the new owner. if (lock_info->GetIsKernelAddressKey()) { @@ -1155,7 +1140,7 @@ namespace Kernel { // to lower priority. if (this->GetPriority() == next_lock_owner->GetPriority() && this->GetPriority() < this->GetBasePriority()) { - RestorePriority(m_kernel, this); + RestorePriority(kernel, this); // NOTE: No need to restore priority on the next lock owner, because it was already the // highest priority waiter on the lock. } @@ -1164,91 +1149,91 @@ namespace Kernel { return next_lock_owner; } - Result KThread::Run() { + Result KThread::Run(KernelCore& kernel) { while (true) { - KScopedSchedulerLock lk{m_kernel}; + KScopedSchedulerLock lk{kernel}; // If either this thread or the current thread are requesting termination, note it. R_UNLESS(!this->IsTerminationRequested(), ResultTerminationRequested); - R_UNLESS(!GetCurrentThread(m_kernel).IsTerminationRequested(), ResultTerminationRequested); + R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested); // Ensure our thread state is correct. R_UNLESS(this->GetState() == ThreadState::Initialized, ResultInvalidState); // If the current thread has been asked to suspend, suspend it and retry. - if (GetCurrentThread(m_kernel).IsSuspended()) { - GetCurrentThread(m_kernel).UpdateState(); + if (GetCurrentThread(kernel).IsSuspended()) { + GetCurrentThread(kernel).UpdateState(kernel); continue; } // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) { if (this->IsUserThread() && this->IsSuspended()) { - this->UpdateState(); + this->UpdateState(kernel); } - owner->IncrementRunningThreadCount(); + owner->IncrementRunningThreadCount(kernel); } // Open a reference, now that we're running. - this->Open(); + this->Open(kernel); // Set our state and finish. - this->SetState(ThreadState::Runnable); + this->SetState(kernel, ThreadState::Runnable); R_SUCCEED(); } } - void KThread::Exit() { - ASSERT(this == GetCurrentThreadPointer(m_kernel)); + void KThread::Exit(KernelCore& kernel) { + ASSERT(this == GetCurrentThreadPointer(kernel)); // Release the thread resource hint, running thread count from parent. if (m_parent != nullptr) { - m_parent->GetResourceLimit()->Release(Kernel::LimitableResource::ThreadCountMax, 0, 1); + m_parent->GetResourceLimit()->Release(kernel, Kernel::LimitableResource::ThreadCountMax, 0, 1); m_resource_limit_release_hint = true; - m_parent->DecrementRunningThreadCount(); + m_parent->DecrementRunningThreadCount(kernel); } // Perform termination. { - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Disallow all suspension. m_suspend_allowed_flags = 0; - this->UpdateState(); + this->UpdateState(kernel); // Disallow all suspension. m_suspend_allowed_flags = 0; // Start termination. - this->StartTermination(); + this->StartTermination(kernel); // Register the thread as a work task. - KWorkerTaskManager::AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); + KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } UNREACHABLE_MSG("KThread::Exit() would return"); } - Result KThread::Terminate() { - ASSERT(this != GetCurrentThreadPointer(m_kernel)); + Result KThread::Terminate(KernelCore& kernel) { + ASSERT(this != GetCurrentThreadPointer(kernel)); // Request the thread terminate if it hasn't already. - if (const auto new_state = this->RequestTerminate(); new_state != ThreadState::Terminated) { + if (const auto new_state = this->RequestTerminate(kernel); new_state != ThreadState::Terminated) { // If the thread isn't terminated, wait for it to terminate. s32 index; KSynchronizationObject* objects[] = {this}; - R_TRY(KSynchronizationObject::Wait(m_kernel, std::addressof(index), objects, 1, + R_TRY(KSynchronizationObject::Wait(kernel, std::addressof(index), objects, 1, Svc::WaitInfinite)); } R_SUCCEED(); } - ThreadState KThread::RequestTerminate() { - ASSERT(this != GetCurrentThreadPointer(m_kernel)); + ThreadState KThread::RequestTerminate(KernelCore& kernel) { + ASSERT(this != GetCurrentThreadPointer(kernel)); - KScopedSchedulerLock sl{m_kernel}; + KScopedSchedulerLock sl{kernel}; // Determine if this is the first termination request. const bool first_request = [&]() -> bool { @@ -1270,46 +1255,46 @@ namespace Kernel { // If the thread is pinned, unpin it. if (this->GetStackParameters().is_pinned) { - this->GetOwnerProcess()->UnpinThread(this); + this->GetOwnerProcess()->UnpinThread(kernel, this); } // If the thread is suspended, continue it. if (this->IsSuspended()) { m_suspend_allowed_flags = 0; - this->UpdateState(); + this->UpdateState(kernel); } // Change the thread's priority to be higher than any system thread's. - this->IncreaseBasePriority(TerminatingThreadPriority); + this->IncreaseBasePriority(kernel, TerminatingThreadPriority); // If the thread is runnable, send a termination interrupt to cores it may be running on. if (this->GetState() == ThreadState::Runnable) { // NOTE: We do not mask the "current core", because this code may not actually be // executing from the thread representing the "current core". if (const u64 core_mask = m_physical_affinity_mask.GetAffinityMask(); core_mask != 0) { - Kernel::KInterruptManager::SendInterProcessorInterrupt(m_kernel, core_mask); + Kernel::KInterruptManager::SendInterProcessorInterrupt(kernel, core_mask); } } // Wake up the thread. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(this, ResultTerminationRequested, true); + m_wait_queue->CancelWait(kernel, this, ResultTerminationRequested, true); } } return this->GetState(); } - Result KThread::Sleep(s64 timeout) { - ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); - ASSERT(this == GetCurrentThreadPointer(m_kernel)); + Result KThread::Sleep(KernelCore& kernel, s64 timeout) { + ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread(kernel)); + ASSERT(this == GetCurrentThreadPointer(kernel)); ASSERT(timeout > 0); - ThreadQueueImplForKThreadSleep wait_queue(m_kernel); + ThreadQueueImplForKThreadSleep wait_queue(kernel); KHardwareTimer* timer{}; { // Setup the scheduling lock and sleep. - KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), this, timeout); + KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), this, timeout); // Check if the thread should terminate. if (this->IsTerminationRequested()) { @@ -1319,15 +1304,15 @@ namespace Kernel { // Wait for the sleep to end. wait_queue.SetHardwareTimer(timer); - this->BeginWait(std::addressof(wait_queue)); + this->BeginWait(kernel, std::addressof(wait_queue)); this->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); } R_SUCCEED(); } - void KThread::RequestDummyThreadWait() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::RequestDummyThreadWait(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(this->IsDummyThread()); // We will block when the scheduler lock is released. @@ -1335,8 +1320,8 @@ namespace Kernel { m_dummy_thread_runnable = false; } - void KThread::DummyThreadBeginWait() { - if (!this->IsDummyThread() || m_kernel.IsPhantomModeForSingleCore()) { + void KThread::DummyThreadBeginWait(KernelCore& kernel) { + if (!this->IsDummyThread() || kernel.IsPhantomModeForSingleCore()) { // Occurs in single core mode. return; } @@ -1346,8 +1331,8 @@ namespace Kernel { m_dummy_thread_cv.wait(lock, [this] { return m_dummy_thread_runnable; }); } - void KThread::DummyThreadEndWait() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + void KThread::DummyThreadEndWait(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); ASSERT(this->IsDummyThread()); // Wake up the waiting thread. @@ -1358,28 +1343,26 @@ namespace Kernel { m_dummy_thread_cv.notify_one(); } - void KThread::BeginWait(KThreadQueue* queue) { + void KThread::BeginWait(KernelCore& kernel, KThreadQueue* queue) { // Set our state as waiting. - this->SetState(ThreadState::Waiting); + this->SetState(kernel, ThreadState::Waiting); // Set our wait queue. m_wait_queue = queue; } - void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result) { + void KThread::NotifyAvailable(KernelCore& kernel, KSynchronizationObject* signaled_object, Result wait_result) { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); - + KScopedSchedulerLock sl(kernel); // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->NotifyAvailable(this, signaled_object, wait_result); + m_wait_queue->NotifyAvailable(kernel, this, signaled_object, wait_result); } } - void KThread::EndWait(Result wait_result) { + void KThread::EndWait(KernelCore& kernel, Result wait_result) { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); - + KScopedSchedulerLock sl(kernel); // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { if (m_wait_queue == nullptr) { @@ -1388,32 +1371,29 @@ namespace Kernel { return; } - m_wait_queue->EndWait(this, wait_result); + m_wait_queue->EndWait(kernel, this, wait_result); } } - void KThread::CancelWait(Result wait_result, bool cancel_timer_task) { + void KThread::CancelWait(KernelCore& kernel, Result wait_result, bool cancel_timer_task) { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); - + KScopedSchedulerLock sl(kernel); // If we're waiting, notify our queue that we're available. if (this->GetState() == ThreadState::Waiting) { - m_wait_queue->CancelWait(this, wait_result, cancel_timer_task); + m_wait_queue->CancelWait(kernel, this, wait_result, cancel_timer_task); } } - void KThread::SetState(ThreadState state) { - KScopedSchedulerLock sl{m_kernel}; - + void KThread::SetState(KernelCore& kernel, ThreadState state) { + KScopedSchedulerLock sl{kernel}; // Clear debugging state this->SetWaitReasonForDebugging({}); - const ThreadState old_state = m_thread_state.load(std::memory_order_relaxed); m_thread_state.store( static_cast((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)), std::memory_order_relaxed); if (m_thread_state.load(std::memory_order_relaxed) != old_state) { - KScheduler::OnThreadStateChanged(m_kernel, this, old_state); + KScheduler::OnThreadStateChanged(kernel, this, old_state); } } @@ -1459,12 +1439,12 @@ namespace Kernel { auto* scheduler = m_kernel.CurrentScheduler(); if (scheduler && !m_kernel.IsPhantomModeForSingleCore()) { - scheduler->RescheduleCurrentCore(); + scheduler->RescheduleCurrentCore(m_kernel); } else { KScheduler::RescheduleCurrentHLEThread(m_kernel); } } else { - GetCurrentThread(m_kernel).EnableDispatch(); + GetCurrentThread(m_kernel).EnableDispatch(m_kernel); } } } \ No newline at end of file diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index e79704ce4b..95ba1b4d76 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -181,21 +181,17 @@ public: return m_thread_id; } - void ContinueIfHasKernelWaiters() { + void ContinueIfHasKernelWaiters(KernelCore& kernel) { if (GetNumKernelWaiters() > 0) { - Continue(); + Continue(kernel); } } - void SetBasePriority(s32 value); - - Result Run(); - - void Exit(); - - Result Terminate(); - - ThreadState RequestTerminate(); + void SetBasePriority(KernelCore& kernel, s32 value); + Result Run(KernelCore& kernel); + void Exit(KernelCore& kernel); + Result Terminate(KernelCore& kernel); + ThreadState RequestTerminate(KernelCore& kernel); u32 GetSuspendFlags() const { return m_suspend_allowed_flags & m_suspend_request_flags; @@ -215,15 +211,11 @@ public: return m_suspend_request_flags != 0; } - void RequestSuspend(SuspendType type); - - void Resume(SuspendType type); - - void TrySuspend(); - - void UpdateState(); - - void Continue(); + void RequestSuspend(KernelCore& kernel, SuspendType type); + void Resume(KernelCore& kernel, SuspendType type); + void TrySuspend(KernelCore& kernel); + void UpdateState(KernelCore& kernel); + void Continue(KernelCore& kernel); constexpr void SetSyncedIndex(s32 index) { m_synced_index = index; @@ -262,7 +254,7 @@ public: m_thread_context.tpidr = value; } - void CloneFpuStatus(); + void CloneFpuStatus(KernelCore& kernel); Svc::ThreadContext& GetContext() { return m_thread_context; @@ -282,7 +274,7 @@ public: return m_thread_state.load(std::memory_order_relaxed); } - void SetState(ThreadState state); + void SetState(KernelCore& kernel, ThreadState state); StepState GetStepState() const { return m_step_state; @@ -342,27 +334,27 @@ public: Svc::ArgumentHandleCountMax}; } - u16 GetUserDisableCount() const; - void SetInterruptFlag(); - void ClearInterruptFlag(); + u16 GetUserDisableCount(KernelCore& kernel) const; + void SetInterruptFlag(KernelCore& kernel); + void ClearInterruptFlag(KernelCore& kernel); - void UpdateTlsThreadCpuTime(s64 switch_tick); + void UpdateTlsThreadCpuTime(KernelCore& kernel, s64 switch_tick); - KThread* GetLockOwner() const; + KThread* GetLockOwner(KernelCore& kernel) const; const KAffinityMask& GetAffinityMask() const { return m_physical_affinity_mask; } - Result GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask); + Result GetCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask); - Result GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); + Result GetPhysicalCoreMask(KernelCore& kernel, s32* out_ideal_core, u64* out_affinity_mask); - Result SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask); + Result SetCoreMask(KernelCore& kernel, s32 cpu_core_id, u64 v_affinity_mask); - Result SetActivity(Svc::ThreadActivity activity); + Result SetActivity(KernelCore& kernel, Svc::ThreadActivity activity); - Result Sleep(s64 timeout); + Result Sleep(KernelCore& kernel, s64 timeout); s64 GetYieldScheduleCount() const { return m_schedule_count; @@ -372,7 +364,7 @@ public: m_schedule_count = count; } - void WaitCancel(); + void WaitCancel(KernelCore& kernel); bool IsWaitCancelled() const { return m_wait_cancelled; @@ -417,17 +409,17 @@ public: return reinterpret_cast(m_parent) | (m_resource_limit_release_hint ? 1 : 0); } - void Finalize() override; + void Finalize(KernelCore& kernel) override; - bool IsSignaled() const override; + bool IsSignaled(KernelCore& kernel) const override; - void OnTimer(); + void OnTimer(KernelCore& kernel); - void DoWorkerTaskImpl(); + void DoWorkerTaskImpl(KernelCore& kernel); - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); - static Result InitializeDummyThread(KThread* thread, KProcess* owner); + static Result InitializeDummyThread(Core::System& system, KThread* thread, KProcess* owner); static Result InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core); @@ -514,19 +506,18 @@ public: return this->GetStackParameters().disable_count; } - void DisableDispatch() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() >= 0); + void DisableDispatch(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0); this->GetStackParameters().disable_count++; } - void EnableDispatch() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() > 0); + void EnableDispatch(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() > 0); this->GetStackParameters().disable_count--; } - void Pin(s32 current_core); - - void Unpin(); + void Pin(KernelCore& kernel, s32 current_core); + void Unpin(KernelCore& kernel); void SetInExceptionHandler() { this->GetStackParameters().is_in_exception_handler = true; @@ -592,18 +583,18 @@ public: return this->GetThreadType() == ThreadType::Dummy; } - void AddWaiter(KThread* thread); + void AddWaiter(KernelCore& kernel, KThread* thread); - void RemoveWaiter(KThread* thread); + void RemoveWaiter(KernelCore& kernel, KThread* thread); - Result GetThreadContext3(Svc::ThreadContext* out); + Result GetThreadContext3(KernelCore& kernel, Svc::ThreadContext* out); - KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) { - return this->RemoveWaiterByKey(out_has_waiters, key, false); + KThread* RemoveUserWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key) { + return this->RemoveWaiterByKey(kernel, out_has_waiters, key, false); } - KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, KProcessAddress key) { - return this->RemoveWaiterByKey(out_has_waiters, key, true); + KThread* RemoveKernelWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key) { + return this->RemoveWaiterByKey(kernel, out_has_waiters, key, true); } KProcessAddress GetAddressKey() const { @@ -641,10 +632,10 @@ public: m_wait_queue = nullptr; } - void BeginWait(KThreadQueue* queue); - void NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result); - void EndWait(Result wait_result); - void CancelWait(Result wait_result, bool cancel_timer_task); + void BeginWait(KernelCore& kernel, KThreadQueue* queue); + void NotifyAvailable(KernelCore& kernel, KSynchronizationObject* signaled_object, Result wait_result); + void EndWait(KernelCore& kernel, Result wait_result); + void CancelWait(KernelCore& kernel, Result wait_result, bool cancel_timer_task); s32 GetNumKernelWaiters() const { return m_num_kernel_waiters; @@ -662,9 +653,9 @@ public: // therefore will not block on guest kernel synchronization primitives. These methods handle // blocking as needed. - void RequestDummyThreadWait(); - void DummyThreadBeginWait(); - void DummyThreadEndWait(); + void RequestDummyThreadWait(KernelCore& kernel); + void DummyThreadBeginWait(KernelCore& kernel); + void DummyThreadEndWait(KernelCore& kernel); uintptr_t GetArgument() const { return m_argument; @@ -690,8 +681,7 @@ public: } private: - KThread* RemoveWaiterByKey(bool* out_has_waiters, KProcessAddress key, - bool is_kernel_address_key); + KThread* RemoveWaiterByKey(KernelCore& kernel, bool* out_has_waiters, KProcessAddress key, bool is_kernel_address_key); static constexpr size_t PriorityInheritanceCountMax = 10; union SyncObjectBuffer { @@ -735,19 +725,19 @@ private: } }; - void AddWaiterImpl(KThread* thread); - void RemoveWaiterImpl(KThread* thread); + void AddWaiterImpl(KernelCore& kernel, KThread* thread); + void RemoveWaiterImpl(KernelCore& kernel, KThread* thread); static void RestorePriority(KernelCore& kernel, KThread* thread); - void StartTermination(); - void FinishTermination(); + void StartTermination(KernelCore& kernel); + void FinishTermination(KernelCore& kernel); - void IncreaseBasePriority(s32 priority); + void IncreaseBasePriority(KernelCore& kernel, s32 priority); - Result Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, + Result Initialize(KernelCore& kernel, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner, ThreadType type); - static Result InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, + static Result InitializeThread(KernelCore& kernel, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess* owner, ThreadType type, std::function&& init_func); @@ -878,9 +868,8 @@ public: return m_waiting_lock_info; } - void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info); - LockWithPriorityInheritanceInfo* FindHeldLock(KProcessAddress address_key, - bool is_kernel_address_key); + void AddHeldLock(KernelCore& kernel, LockWithPriorityInheritanceInfo* lock_info); + LockWithPriorityInheritanceInfo* FindHeldLock(KernelCore& kernel, KProcessAddress address_key, bool is_kernel_address_key); private: using LockWithPriorityInheritanceInfoList = @@ -996,7 +985,7 @@ public: if (m_kernel.IsShuttingDown()) { return; } - GetCurrentThread(kernel).DisableDispatch(); + GetCurrentThread(kernel).DisableDispatch(kernel); } ~KScopedDisableDispatch(); @@ -1005,8 +994,8 @@ private: KernelCore& m_kernel; }; -inline void KTimerTask::OnTimer() { - static_cast(this)->OnTimer(); +inline void KTimerTask::OnTimer(KernelCore& kernel) { + static_cast(this)->OnTimer(kernel); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp index 61488f4ce6..7c4bfe5a49 100644 --- a/src/core/hle/kernel/k_thread_queue.cpp +++ b/src/core/hle/kernel/k_thread_queue.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,17 +10,16 @@ namespace Kernel { -void KThreadQueue::NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - Result wait_result) { +void KThreadQueue::NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result) { UNREACHABLE(); } -void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { +void KThreadQueue::EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) { // Set the thread's wait result. waiting_thread->SetWaitResult(wait_result); // Set the thread as runnable. - waiting_thread->SetState(ThreadState::Runnable); + waiting_thread->SetState(kernel, ThreadState::Runnable); // Clear the thread's wait queue. waiting_thread->ClearWaitQueue(); @@ -28,12 +30,12 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { } } -void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { +void KThreadQueue::CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { // Set the thread's wait result. waiting_thread->SetWaitResult(wait_result); // Set the thread as runnable. - waiting_thread->SetState(ThreadState::Runnable); + waiting_thread->SetState(kernel, ThreadState::Runnable); // Clear the thread's wait queue. waiting_thread->ClearWaitQueue(); @@ -44,7 +46,7 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool } } -void KThreadQueueWithoutEndWait::EndWait(KThread* waiting_thread, Result wait_result) { +void KThreadQueueWithoutEndWait::EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) { UNREACHABLE(); } diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 117af0919a..953bb78ac6 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,28 +15,25 @@ class KHardwareTimer; class KThreadQueue { public: - explicit KThreadQueue(KernelCore& kernel) : m_kernel{kernel}, m_hardware_timer{} {} + explicit KThreadQueue(KernelCore& kernel) : m_hardware_timer{} {} virtual ~KThreadQueue() = default; void SetHardwareTimer(KHardwareTimer* timer) { m_hardware_timer = timer; } - virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, - Result wait_result); - virtual void EndWait(KThread* waiting_thread, Result wait_result); - virtual void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task); + virtual void NotifyAvailable(KernelCore& kernel, KThread* waiting_thread, KSynchronizationObject* signaled_object, Result wait_result); + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result); + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task); private: - KernelCore& m_kernel; KHardwareTimer* m_hardware_timer{}; }; class KThreadQueueWithoutEndWait : public KThreadQueue { public: explicit KThreadQueueWithoutEndWait(KernelCore& kernel) : KThreadQueue(kernel) {} - - void EndWait(KThread* waiting_thread, Result wait_result) override final; + void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override final; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_timer_task.h b/src/core/hle/kernel/k_timer_task.h index 66f0a5a908..7625c1fee1 100644 --- a/src/core/hle/kernel/k_timer_task.h +++ b/src/core/hle/kernel/k_timer_task.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,6 +10,7 @@ namespace Kernel { +class KernelCore; class KTimerTask : public Common::IntrusiveRedBlackTreeBaseNode { public: static constexpr int Compare(const KTimerTask& lhs, const KTimerTask& rhs) { @@ -30,7 +34,7 @@ public: // NOTE: This is virtual in Nintendo's kernel. Prior to 13.0.0, KWaitObject was also a // TimerTask; this is no longer the case. Since this is now KThread exclusive, we have // devirtualized (see inline declaration for this inside k_thread.h). - void OnTimer(); + void OnTimer(KernelCore& kernel); private: // Absolute time in nanoseconds diff --git a/src/core/hle/kernel/k_trace.h b/src/core/hle/kernel/k_trace.h index d61af48303..84dd4134e1 100644 --- a/src/core/hle/kernel/k_trace.h +++ b/src/core/hle/kernel/k_trace.h @@ -1,8 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once +#include "common/literals.h" + namespace Kernel { using namespace Common::Literals; diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index 09295e8ad8..a4ef530b5b 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,16 +17,15 @@ KTransferMemory::KTransferMemory(KernelCore& kernel) KTransferMemory::~KTransferMemory() = default; -Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, - Svc::MemoryPermission own_perm) { +Result KTransferMemory::Initialize(KernelCore& kernel, KProcessAddress addr, std::size_t size, Svc::MemoryPermission own_perm) { // Set members. - m_owner = GetCurrentProcessPointer(m_kernel); + m_owner = GetCurrentProcessPointer(kernel); // Get the owner page table. auto& page_table = m_owner->GetPageTable(); // Construct the page group, guarding to make sure our state is valid on exit. - m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); + m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); auto pg_guard = SCOPE_GUARD { m_page_group.reset(); }; @@ -33,7 +35,7 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, ConvertToKMemoryPermission(own_perm))); // Set remaining tracking members. - m_owner->Open(); + m_owner->Open(kernel); m_owner_perm = own_perm; m_address = addr; m_is_initialized = true; @@ -44,7 +46,7 @@ Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size, R_SUCCEED(); } -void KTransferMemory::Finalize() { +void KTransferMemory::Finalize(KernelCore& kernel) { // Unlock. if (!m_is_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; @@ -53,17 +55,17 @@ void KTransferMemory::Finalize() { } // Close the page group. - m_page_group->Close(); + m_page_group->Close(kernel); m_page_group->Finalize(); } -void KTransferMemory::PostDestroy(uintptr_t arg) { +void KTransferMemory::PostDestroy(KernelCore& kernel, uintptr_t arg) { KProcess* owner = reinterpret_cast(arg); - owner->GetResourceLimit()->Release(LimitableResource::TransferMemoryCountMax, 1); - owner->Close(); + owner->GetResourceLimit()->Release(kernel, LimitableResource::TransferMemoryCountMax, 1); + owner->Close(kernel); } -Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) { +Result KTransferMemory::Map(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -80,7 +82,7 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) ? KMemoryState::Transferred : KMemoryState::SharedTransferred; - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( + R_TRY(GetCurrentProcess(kernel).GetPageTable().MapPageGroup( address, *m_page_group, state, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -89,7 +91,7 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer R_SUCCEED(); } -Result KTransferMemory::Unmap(KProcessAddress address, size_t size) { +Result KTransferMemory::Unmap(KernelCore& kernel, KProcessAddress address, size_t size) { // Validate the size. R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); @@ -100,7 +102,7 @@ Result KTransferMemory::Unmap(KProcessAddress address, size_t size) { const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None) ? KMemoryState::Transferred : KMemoryState::SharedTransferred; - R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); + R_TRY(GetCurrentProcess(kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state)); // Mark ourselves as unmapped. ASSERT(m_is_mapped); diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index 530b452182..0753b4fd6d 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,9 +33,9 @@ public: explicit KTransferMemory(KernelCore& kernel); ~KTransferMemory() override; - Result Initialize(KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm); + Result Initialize(KernelCore& kernel, KProcessAddress address, std::size_t size, Svc::MemoryPermission owner_perm); - void Finalize() override; + void Finalize(KernelCore& kernel) override; bool IsInitialized() const override { return m_is_initialized; @@ -42,7 +45,7 @@ public: return reinterpret_cast(m_owner); } - static void PostDestroy(uintptr_t arg); + static void PostDestroy(KernelCore& kernel, uintptr_t arg); KProcess* GetOwner() const override { return m_owner; @@ -54,8 +57,8 @@ public: size_t GetSize() const; - Result Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm); - Result Unmap(KProcessAddress address, size_t size); + Result Map(KernelCore& kernel, KProcessAddress address, size_t size, Svc::MemoryPermission map_perm); + Result Unmap(KernelCore& kernel, KProcessAddress address, size_t size); private: std::optional m_page_group{}; diff --git a/src/core/hle/kernel/k_worker_task.h b/src/core/hle/kernel/k_worker_task.h index 9a230c03c4..a4820bc412 100644 --- a/src/core/hle/kernel/k_worker_task.h +++ b/src/core/hle/kernel/k_worker_task.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,8 +13,7 @@ namespace Kernel { class KWorkerTask : public KSynchronizationObject { public: explicit KWorkerTask(KernelCore& kernel); - - void DoWorkerTask(); + void DoWorkerTask(KernelCore& kernel); }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_worker_task_manager.cpp b/src/core/hle/kernel/k_worker_task_manager.cpp index 8ead395911..4427f9859a 100644 --- a/src/core/hle/kernel/k_worker_task_manager.cpp +++ b/src/core/hle/kernel/k_worker_task_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,14 +15,14 @@ namespace Kernel { KWorkerTask::KWorkerTask(KernelCore& kernel) : KSynchronizationObject{kernel} {} -void KWorkerTask::DoWorkerTask() { +void KWorkerTask::DoWorkerTask(KernelCore& kernel) { if (auto* const thread = this->DynamicCast(); thread != nullptr) { - return thread->DoWorkerTaskImpl(); + return thread->DoWorkerTaskImpl(kernel); } else { auto* const process = this->DynamicCast(); ASSERT(process != nullptr); - return process->DoWorkerTaskImpl(); + return process->DoWorkerTaskImpl(kernel); } } @@ -32,9 +35,9 @@ void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTas void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) { KScopedSchedulerLock sl(kernel); - m_waiting_thread.QueueWork([task]() { + m_waiting_thread.QueueWork([&kernel, task]() { // Do the task. - task->DoWorkerTask(); + task->DoWorkerTask(kernel); }); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 5f88fa498f..d25ac37df4 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -121,14 +121,14 @@ struct KernelCore::Impl { void TerminateAllProcesses() { std::scoped_lock lk{process_list_lock}; for (auto& process : process_list) { - process->Terminate(); - process->Close(); + process->Terminate(system.Kernel()); + process->Close(system.Kernel()); process = nullptr; } process_list.clear(); } - void Shutdown() { + void Shutdown(KernelCore& kernel) { is_shutting_down.store(true, std::memory_order_relaxed); SCOPE_EXIT { is_shutting_down.store(false, std::memory_order_relaxed); @@ -137,7 +137,7 @@ struct KernelCore::Impl { CloseServices(); if (application_process) { - application_process->Close(); + application_process->Close(system.Kernel()); application_process = nullptr; } @@ -149,9 +149,9 @@ struct KernelCore::Impl { preemption_event = nullptr; // Cleanup persistent kernel objects - auto CleanupObject = [](KAutoObject* obj) { + auto CleanupObject = [&kernel](KAutoObject* obj) { if (obj) { - obj->Close(); + obj->Close(kernel); obj = nullptr; } }; @@ -163,7 +163,7 @@ struct KernelCore::Impl { for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { if (shutdown_threads[core_id]) { - shutdown_threads[core_id]->Close(); + shutdown_threads[core_id]->Close(kernel); shutdown_threads[core_id] = nullptr; } @@ -178,7 +178,7 @@ struct KernelCore::Impl { std::scoped_lock lk{registered_in_use_objects_lock}; if (registered_in_use_objects.size()) { for (auto& object : registered_in_use_objects) { - object->Close(); + object->Close(kernel); } registered_in_use_objects.clear(); } @@ -226,7 +226,7 @@ struct KernelCore::Impl { ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, core).IsSuccess()); KThread::Register(system.Kernel(), idle_thread); - schedulers[i]->Initialize(main_thread, idle_thread, core); + schedulers[i]->Initialize(system.Kernel(), main_thread, idle_thread, core); } } @@ -247,19 +247,18 @@ struct KernelCore::Impl { ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133).IsSuccess()); - system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, kernel_size); + system_resource_limit->Reserve(kernel, LimitableResource::PhysicalMemoryMax, kernel_size); // Reserve secure applet memory, introduced in firmware 5.0.0 constexpr u64 secure_applet_memory_size{4_MiB}; - ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, - secure_applet_memory_size)); + ASSERT(system_resource_limit->Reserve(kernel, LimitableResource::PhysicalMemoryMax, secure_applet_memory_size)); } void InitializePreemption(KernelCore& kernel) { preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional { { KScopedSchedulerLock lock(kernel); - global_scheduler_context->PreemptThreads(); + global_scheduler_context->PreemptThreads(kernel); } return std::nullopt; }); @@ -350,9 +349,9 @@ struct KernelCore::Impl { object_name_global_data.emplace(kernel); } - void MakeApplicationProcess(KProcess* process) { + void MakeApplicationProcess(KernelCore& kernel, KProcess* process) { application_process = process; - application_process->Open(); + application_process->Open(kernel); } /// Sets the host thread ID for the caller. @@ -374,10 +373,10 @@ struct KernelCore::Impl { // Gets the dummy KThread for the caller, allocating a new one if this is the first time KThread* GetHostDummyThread(ThreadLocalData& t, KThread* existing_thread) { if (t.thread == nullptr) { - auto const initialize{[](KThread* thread) { - ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); + auto const initialize = [this](KThread* thread) { + ASSERT(KThread::InitializeDummyThread(system, thread, nullptr).IsSuccess()); return thread; - }}; + }; t.raw_thread.emplace(system.Kernel()); t.thread = existing_thread ? existing_thread : initialize(&*t.raw_thread); ASSERT(t.thread != nullptr); @@ -418,8 +417,7 @@ struct KernelCore::Impl { return is_shutting_down.load(std::memory_order_relaxed); } - KThread* GetCurrentEmuThread() { - auto& t = tls_data; + KThread* GetCurrentEmuThread(ThreadLocalData& t) { return t.current_thread ? t.current_thread : (t.current_thread = GetHostDummyThread(t, nullptr)); } @@ -742,19 +740,19 @@ struct KernelCore::Impl { time_shared_mem = KSharedMemory::Create(system.Kernel()); hidbus_shared_mem = KSharedMemory::Create(system.Kernel()); - font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, font_size); KSharedMemory::Register(kernel, font_shared_mem); - irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, irs_size); KSharedMemory::Register(kernel, irs_shared_mem); - time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, time_size); KSharedMemory::Register(kernel, time_shared_mem); - hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, + hidbus_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, Svc::MemoryPermission::Read, hidbus_size); KSharedMemory::Register(kernel, hidbus_shared_mem); } @@ -852,7 +850,7 @@ void KernelCore::Initialize() { } void KernelCore::Shutdown() { - impl->Shutdown(); + impl->Shutdown(*this); } void KernelCore::CloseServices() { @@ -868,7 +866,7 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() { } void KernelCore::AppendNewProcess(KProcess* process) { - process->Open(); + process->Open(*this); std::scoped_lock lk{impl->process_list_lock}; impl->process_list.push_back(process); @@ -877,12 +875,12 @@ void KernelCore::AppendNewProcess(KProcess* process) { void KernelCore::RemoveProcess(KProcess* process) { std::scoped_lock lk{impl->process_list_lock}; if (std::erase(impl->process_list, process)) { - process->Close(); + process->Close(*this); } } void KernelCore::MakeApplicationProcess(KProcess* process) { - impl->MakeApplicationProcess(process); + impl->MakeApplicationProcess(*this, process); } KProcess* KernelCore::ApplicationProcess() { @@ -896,11 +894,8 @@ const KProcess* KernelCore::ApplicationProcess() const { std::list> KernelCore::GetProcessList() { std::list> processes; std::scoped_lock lk{impl->process_list_lock}; - - for (auto* const process : impl->process_list) { - processes.emplace_back(process); - } - + for (auto* const process : impl->process_list) + processes.emplace_back(*this, process); return processes; } @@ -1029,15 +1024,14 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) { } } -static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, - std::string&& thread_name, std::function&& func) { +static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, std::string&& thread_name, std::function&& func) { // Reserve a new thread from the process resource limit. - KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(kernel, process, LimitableResource::ThreadCountMax); ASSERT(thread_reservation.Succeeded()); // Initialize the thread. KThread* thread = KThread::Create(kernel); - ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process))); + ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(kernel.System(), thread, process))); // Commit the thread reservation. thread_reservation.Commit(); @@ -1057,7 +1051,7 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, // Close the thread. // This will free the process if it is the last reference. - thread->Close(); + thread->Close(kernel); }); } @@ -1066,11 +1060,11 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name, // Make a new process. KProcess* process = KProcess::Create(*this); ASSERT(R_SUCCEEDED( - process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); + process->Initialize(*this, Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); // Ensure that we don't hold onto any extra references. SCOPE_EXIT { - process->Close(); + process->Close(*this); }; // Register the new process. @@ -1096,18 +1090,18 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function // Make a new process. KProcess* process = KProcess::Create(*this); ASSERT(R_SUCCEEDED( - process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); + process->Initialize(*this, Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false))); // Ensure that we don't hold onto any extra references. SCOPE_EXIT { - process->Close(); + process->Close(*this); }; // Register the new process. KProcess::Register(*this, process); // Reserve a new thread from the process resource limit. - KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(*this, process, LimitableResource::ThreadCountMax); ASSERT(thread_reservation.Succeeded()); // Initialize the thread. @@ -1122,7 +1116,7 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function KThread::Register(*this, thread); // Begin running the thread. - ASSERT(R_SUCCEEDED(thread->Run())); + ASSERT(R_SUCCEEDED(thread->Run(*this))); } u32 KernelCore::GetCurrentHostThreadID() const { @@ -1130,7 +1124,7 @@ u32 KernelCore::GetCurrentHostThreadID() const { } KThread* KernelCore::GetCurrentEmuThread() const { - return impl->GetCurrentEmuThread(); + return impl->GetCurrentEmuThread(Impl::tls_data); } void KernelCore::SetCurrentEmuThread(KThread* thread) { @@ -1206,9 +1200,9 @@ void KernelCore::SuspendEmulation(bool suspended) { for (auto& thread : process->GetThreadList()) { if (should_suspend) { - thread.RequestSuspend(SuspendType::System); + thread.RequestSuspend(*this, SuspendType::System); } else { - thread.Resume(SuspendType::System); + thread.Resume(*this, SuspendType::System); } } } @@ -1244,12 +1238,9 @@ void KernelCore::SuspendEmulation(bool suspended) { void KernelCore::ShutdownCores() { impl->TerminateAllProcesses(); - KScopedSchedulerLock lk{*this}; - - for (auto* thread : impl->shutdown_threads) { - void(thread->Run()); - } + for (auto* thread : impl->shutdown_threads) + void(thread->Run(*this)); } bool KernelCore::IsMulticore() const { diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index f394122764..a81c14f643 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -17,14 +17,15 @@ namespace Kernel { PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t core_index) - : m_kernel{kernel}, m_core_index{core_index} { + : m_core_index{core_index} +{ m_is_single_core = !kernel.IsMulticore(); } PhysicalCore::~PhysicalCore() = default; -void PhysicalCore::RunThread(Kernel::KThread* thread) { +void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) { auto* process = thread->GetOwnerProcess(); - auto& system = m_kernel.System(); + auto& system = kernel.System(); auto* interface = process->GetArmInterface(m_core_index); interface->Initialize(); @@ -72,14 +73,14 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { while (true) { // If the thread is scheduled for termination, exit. if (thread->HasDpc() && thread->IsTerminationRequested()) { - thread->Exit(); + thread->Exit(kernel); } // Notify the debugger and go to sleep if a step was performed // and this thread has been scheduled again. if (thread->GetStepState() == StepState::StepPerformed) { system.GetDebugger().NotifyThreadStopped(thread); - thread->RequestSuspend(SuspendType::Debug); + thread->RequestSuspend(kernel, SuspendType::Debug); return; } @@ -135,7 +136,7 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { } else { interface->LogBacktrace(process); } - thread->RequestSuspend(SuspendType::Debug); + thread->RequestSuspend(kernel, SuspendType::Debug); return; } @@ -144,7 +145,7 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { if (system.DebuggerEnabled()) { system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint()); } - thread->RequestSuspend(SuspendType::Debug); + thread->RequestSuspend(kernel, SuspendType::Debug); return; } @@ -208,8 +209,8 @@ void PhysicalCore::CloneFpuStatus(KThread* dst) const { dst->GetContext().fpsr = ctx.fpsr; } -void PhysicalCore::LogBacktrace() { - auto* process = GetCurrentProcessPointer(m_kernel); +void PhysicalCore::LogBacktrace(KernelCore& kernel) { + auto* process = GetCurrentProcessPointer(kernel); if (!process) { return; } diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index bae4fe5b88..b92201204a 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ public: YUZU_NON_MOVEABLE(PhysicalCore); // Execute guest code running on the given thread. - void RunThread(KThread* thread); + void RunThread(KernelCore& kernel, KThread* thread); // Copy context from thread to current core. void LoadContext(const KThread* thread); @@ -44,7 +47,7 @@ public: void CloneFpuStatus(KThread* dst) const; // Log backtrace of current processor state. - void LogBacktrace(); + void LogBacktrace(KernelCore& kernel); // Wait for an interrupt. void Idle(); @@ -63,9 +66,7 @@ public: } private: - KernelCore& m_kernel; const std::size_t m_core_index; - std::mutex m_guard; std::condition_variable m_on_interrupt; Core::ArmInterface* m_arm_interface{}; diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h index d1bbc76709..95e6b9f6e6 100644 --- a/src/core/hle/kernel/slab_helpers.h +++ b/src/core/hle/kernel/slab_helpers.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -69,16 +72,16 @@ public: explicit KAutoObjectWithSlabHeap(KernelCore& kernel) : Base(kernel) {} virtual ~KAutoObjectWithSlabHeap() = default; - virtual void Destroy() override { + virtual void Destroy(KernelCore& kernel) override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { arg = this->GetPostDestroyArgument(); - this->Finalize(); + this->Finalize(kernel); } - Free(Base::m_kernel, static_cast(this)); + Free(kernel, static_cast(this)); if (is_initialized) { - Derived::PostDestroy(arg); + Derived::PostDestroy(kernel, arg); } } @@ -89,8 +92,8 @@ public: return 0; } - size_t GetSlabIndex() const { - return SlabHeap(Base::m_kernel).GetObjectIndex(static_cast(this)); + size_t GetSlabIndex(KernelCore& kernel) const { + return SlabHeap(kernel).GetObjectIndex(static_cast(this)); } public: @@ -144,17 +147,17 @@ public: KAutoObjectWithSlabHeapAndContainer(KernelCore& kernel) : Base(kernel) {} virtual ~KAutoObjectWithSlabHeapAndContainer() {} - virtual void Destroy() override { + virtual void Destroy(KernelCore& kernel) override { const bool is_initialized = this->IsInitialized(); uintptr_t arg = 0; if (is_initialized) { - Base::m_kernel.ObjectListContainer().Unregister(this); + kernel.ObjectListContainer().Unregister(this); arg = this->GetPostDestroyArgument(); - this->Finalize(); + this->Finalize(kernel); } - Free(Base::m_kernel, static_cast(this)); + Free(kernel, static_cast(this)); if (is_initialized) { - Derived::PostDestroy(arg); + Derived::PostDestroy(kernel, arg); } } @@ -165,8 +168,8 @@ public: return 0; } - size_t GetSlabIndex() const { - return SlabHeap(Base::m_kernel).GetObjectIndex(static_cast(this)); + size_t GetSlabIndex(KernelCore& kernel) const { + return SlabHeap(kernel).GetObjectIndex(static_cast(this)); } public: @@ -177,9 +180,8 @@ public: static Derived* Create(KernelCore& kernel) { Derived* obj = Allocate(kernel); - if (obj != nullptr) { + if (obj != nullptr) KAutoObject::Create(obj); - } return obj; } diff --git a/src/core/hle/kernel/svc/svc_activity.cpp b/src/core/hle/kernel/svc/svc_activity.cpp index 63bc085554..c1ab3daab3 100644 --- a/src/core/hle/kernel/svc/svc_activity.cpp +++ b/src/core/hle/kernel/svc/svc_activity.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,17 +25,15 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle, R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Check that the activity is being set on a non-current thread for the current process. - R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), - ResultInvalidHandle); + R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), ResultInvalidHandle); R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); // Set the activity. - R_TRY(thread->SetActivity(thread_activity)); + R_TRY(thread->SetActivity(system.Kernel(), thread_activity)); return ResultSuccess; } diff --git a/src/core/hle/kernel/svc/svc_cache.cpp b/src/core/hle/kernel/svc/svc_cache.cpp index c2c8be10f5..24f64f28f1 100644 --- a/src/core/hle/kernel/svc/svc_cache.cpp +++ b/src/core/hle/kernel/svc/svc_cache.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -37,8 +40,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad R_UNLESS(size == static_cast(size), ResultInvalidCurrentMemory); // Get the process from its handle. - KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); + KScopedAutoObject process = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Verify the region is within range. diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp index 4e7af9f575..4133586d11 100644 --- a/src/core/hle/kernel/svc/svc_code_memory.cpp +++ b/src/core/hle/kernel/svc/svc_code_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -35,9 +35,6 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm) Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) { LOG_TRACE(Kernel_SVC, "called, address={:#X}, size=0x{:X}", address, size); - // Get kernel instance. - auto& kernel = system.Kernel(); - // Validate address / size. R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); @@ -46,24 +43,23 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t // Create the code memory. - KCodeMemory* code_mem = KCodeMemory::Create(kernel); + KCodeMemory* code_mem = KCodeMemory::Create(system.Kernel()); R_UNLESS(code_mem != nullptr, ResultOutOfResource); SCOPE_EXIT { - code_mem->Close(); + code_mem->Close(system.Kernel()); }; // Verify that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), - ResultInvalidCurrentMemory); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the code memory. - R_TRY(code_mem->Initialize(system.DeviceMemory(), address, size)); + R_TRY(code_mem->Initialize(system.Kernel(), system.DeviceMemory(), address, size)); // Register the code memory. - KCodeMemory::Register(kernel, code_mem); + KCodeMemory::Register(system.Kernel(), code_mem); // Add the code memory to the handle table. - R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, code_mem)); + R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(system.Kernel(), out, code_mem)); R_SUCCEED(); } @@ -85,8 +81,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, // Get the code memory from its handle. KScopedAutoObject code_mem = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(code_memory_handle); + .GetHandleTable() + .GetObject(system.Kernel(), code_memory_handle); R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle); // NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process. @@ -96,29 +92,23 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, switch (operation) { case CodeMemoryOperation::Map: { // Check that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()) - .GetPageTable() - .CanContain(address, size, KMemoryState::CodeOut), - ResultInvalidMemoryRegion); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); // Check the memory permission. R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Map the memory. - R_TRY(code_mem->Map(address, size)); + R_TRY(code_mem->Map(system.Kernel(), address, size)); } break; case CodeMemoryOperation::Unmap: { // Check that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()) - .GetPageTable() - .CanContain(address, size, KMemoryState::CodeOut), - ResultInvalidMemoryRegion); + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); // Check the memory permission. R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Unmap the memory. - R_TRY(code_mem->Unmap(address, size)); + R_TRY(code_mem->Unmap(system.Kernel(), address, size)); } break; case CodeMemoryOperation::MapToOwner: { // Check that the region is in range. @@ -130,7 +120,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, R_UNLESS(IsValidMapToOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Map the memory to its owner. - R_TRY(code_mem->MapToOwner(address, size, perm)); + R_TRY(code_mem->MapToOwner(system.Kernel(), address, size, perm)); } break; case CodeMemoryOperation::UnmapFromOwner: { // Check that the region is in range. @@ -142,7 +132,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, R_UNLESS(IsValidUnmapFromOwnerCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Unmap the memory from its owner. - R_TRY(code_mem->UnmapFromOwner(address, size)); + R_TRY(code_mem->UnmapFromOwner(system.Kernel(), address, size)); } break; default: R_THROW(ResultInvalidEnumValue); diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp index ac828320f4..2deb683d4b 100644 --- a/src/core/hle/kernel/svc/svc_device_address_space.cpp +++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -29,17 +32,17 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_ KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel()); R_UNLESS(das != nullptr, ResultOutOfResource); SCOPE_EXIT { - das->Close(); + das->Close(system.Kernel()); }; // Initialize the device address space. - R_TRY(das->Initialize(das_address, das_size)); + R_TRY(das->Initialize(system.Kernel(), das_address, das_size)); // Register the device address space. KDeviceAddressSpace::Register(system.Kernel(), das); // Add to the handle table. - R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, das)); + R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(system.Kernel(), out, das)); R_SUCCEED(); } @@ -47,8 +50,8 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) { // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(das_handle); + .GetHandleTable() + .GetObject(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Attach. @@ -58,8 +61,8 @@ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Ha Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) { // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(das_handle); + .GetHandleTable() + .GetObject(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Detach. @@ -99,13 +102,13 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(das_handle); + .GetHandleTable() + .GetObject(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. @@ -140,13 +143,13 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(das_handle); + .GetHandleTable() + .GetObject(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. @@ -172,13 +175,12 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p // Get the device address space. KScopedAutoObject das = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(das_handle); + .GetHandleTable() + .GetObject(system.Kernel(), das_handle); R_UNLESS(das.IsNotNull(), ResultInvalidHandle); // Get the process. - KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); + KScopedAutoObject process = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. diff --git a/src/core/hle/kernel/svc/svc_event.cpp b/src/core/hle/kernel/svc/svc_event.cpp index 586cb2b14e..36de3b9096 100644 --- a/src/core/hle/kernel/svc/svc_event.cpp +++ b/src/core/hle/kernel/svc/svc_event.cpp @@ -22,9 +22,9 @@ Result SignalEvent(Core::System& system, Handle event_handle) { // Fail-safe for system applets const auto program_id = GetCurrentProcess(system.Kernel()).GetProgramId(); if ((program_id & 0xFFFFFFFFFFFFFF00ull) == 0x0100000000001000ull) { - KScopedAutoObject event = handle_table.GetObject(event_handle); + KScopedAutoObject event = handle_table.GetObject(system.Kernel(), event_handle); if (event.IsNotNull()) { - event->Signal(); + event->Signal(system.Kernel()); } else { LOG_WARNING(Kernel_SVC, "SignalEvent best-effort unknown handle=0x{:08X} (ignored)", event_handle); @@ -34,10 +34,10 @@ Result SignalEvent(Core::System& system, Handle event_handle) { // Get the event. - KScopedAutoObject event = handle_table.GetObject(event_handle); + KScopedAutoObject event = handle_table.GetObject(system.Kernel(), event_handle); R_UNLESS(event.IsNotNull(), ResultInvalidHandle); - R_RETURN(event->Signal()); + R_RETURN(event->Signal(system.Kernel())); } Result ClearEvent(Core::System& system, Handle event_handle) { @@ -48,18 +48,18 @@ Result ClearEvent(Core::System& system, Handle event_handle) { // Try to clear the writable event. { - KScopedAutoObject event = handle_table.GetObject(event_handle); + KScopedAutoObject event = handle_table.GetObject(system.Kernel(), event_handle); if (event.IsNotNull()) { - event->Clear(); + event->Clear(system.Kernel()); R_SUCCEED(); } } // Try to clear the readable event. { - KScopedAutoObject readable_event = handle_table.GetObject(event_handle); + KScopedAutoObject readable_event = handle_table.GetObject(system.Kernel(), event_handle); if (readable_event.IsNotNull()) { - readable_event->Clear(); + readable_event->Clear(system.Kernel()); R_SUCCEED(); } } @@ -71,43 +71,42 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) { LOG_DEBUG(Kernel_SVC, "called"); // Get the kernel reference and handle table. - auto& kernel = system.Kernel(); - auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); + auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Reserve a new event from the process resource limit - KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel), + KScopedResourceReservation event_reservation(system.Kernel(), GetCurrentProcessPointer(system.Kernel()), LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Create a new event. - KEvent* event = KEvent::Create(kernel); + KEvent* event = KEvent::Create(system.Kernel()); R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(GetCurrentProcessPointer(kernel)); + event->Initialize(system.Kernel(), GetCurrentProcessPointer(system.Kernel())); // Commit the thread reservation. event_reservation.Commit(); // Ensure that we clean up the event (and its only references are handle table) on function end. SCOPE_EXIT { - event->GetReadableEvent().Close(); - event->Close(); + event->GetReadableEvent().Close(system.Kernel()); + event->Close(system.Kernel()); }; // Register the event. - KEvent::Register(kernel, event); + KEvent::Register(system.Kernel(), event); // Add the event to the handle table. - R_TRY(handle_table.Add(out_write, event)); + R_TRY(handle_table.Add(system.Kernel(), out_write, event)); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(*out_write); + handle_table.Remove(system.Kernel(), *out_write); }; // Add the readable event to the handle table. - R_RETURN(handle_table.Add(out_read, std::addressof(event->GetReadableEvent()))); + R_RETURN(handle_table.Add(system.Kernel(), out_read, std::addressof(event->GetReadableEvent()))); } Result SignalEvent64(Core::System& system, Handle event_handle) { diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp index bf09641bad..e1b0fa7b95 100644 --- a/src/core/hle/kernel/svc/svc_exception.cpp +++ b/src/core/hle/kernel/svc/svc_exception.cpp @@ -106,14 +106,14 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) { handle_debug_buffer(info1, info2); - system.CurrentPhysicalCore().LogBacktrace(); + system.CurrentPhysicalCore().LogBacktrace(system.Kernel()); } const bool should_break = !notification_only; if (system.DebuggerEnabled() && should_break) { auto* thread = system.Kernel().GetCurrentEmuThread(); system.GetDebugger().NotifyThreadStopped(thread); - thread->RequestSuspend(Kernel::SuspendType::Debug); + thread->RequestSuspend(system.Kernel(), Kernel::SuspendType::Debug); } } diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 9e651e1171..62f203476e 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -46,7 +46,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_UNLESS(info_sub_id == 0, ResultInvalidEnumValue); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(handle); + KScopedAutoObject process = handle_table.GetObject(system.Kernel(), handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); switch (info_id_type) { @@ -90,11 +90,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::TotalMemorySize: - *result = process->GetTotalUserPhysicalMemorySize(); + *result = process->GetTotalUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::UsedMemorySize: - *result = process->GetUsedUserPhysicalMemorySize(); + *result = process->GetUsedUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::SystemResourceSizeTotal: @@ -114,11 +114,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::TotalNonSystemMemorySize: - *result = process->GetTotalNonSystemUserPhysicalMemorySize(); + *result = process->GetTotalNonSystemUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::UsedNonSystemMemorySize: - *result = process->GetUsedNonSystemUserPhysicalMemorySize(); + *result = process->GetUsedNonSystemUserPhysicalMemorySize(system.Kernel()); R_SUCCEED(); case InfoType::IsApplication: @@ -175,7 +175,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } Handle resource_handle{}; - R_TRY(handle_table.Add(std::addressof(resource_handle), resource_limit)); + R_TRY(handle_table.Add(system.Kernel(), std::addressof(resource_handle), resource_limit)); *result = resource_handle; R_SUCCEED(); @@ -203,8 +203,8 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } KScopedAutoObject thread = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(static_cast(handle)); + .GetHandleTable() + .GetObject(system.Kernel(), Handle(handle)); if (thread.IsNull()) { LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", static_cast(handle)); @@ -256,7 +256,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle // Get a new handle for the current process. Handle tmp; - R_TRY(handle_table.Add(std::addressof(tmp), current_process)); + R_TRY(handle_table.Add(system.Kernel(), std::addressof(tmp), current_process)); // Set the output. *result = tmp; diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index db912b71fb..875590d6f7 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -20,19 +20,17 @@ namespace Kernel::Svc { namespace { -Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, - Handle session_handle) { +Result SendSyncRequestImpl(KernelCore& kernel, uintptr_t message, size_t buffer_size, Handle session_handle) { // Get the client session. - KScopedAutoObject session = - GetCurrentProcess(kernel).GetHandleTable().GetObject(session_handle); + KScopedAutoObject session = GetCurrentProcess(kernel).GetHandleTable().GetObject(kernel, session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Get the parent, and persist a reference to it until we're done. - KScopedAutoObject parent = session->GetParent(); + KScopedAutoObject parent = {kernel, session->GetParent()}; ASSERT(parent.IsNotNull()); // Send the request. - R_RETURN(session->SendSyncRequest(message, buffer_size)); + R_RETURN(session->SendSyncRequest(kernel, message, buffer_size)); } Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t message, @@ -41,8 +39,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes int64_t timeout_ns) { // Reply to the target, if one is specified. if (reply_target != InvalidHandle) { - KScopedAutoObject session = - GetCurrentProcess(kernel).GetHandleTable().GetObject(reply_target); + KScopedAutoObject session = GetCurrentProcess(kernel).GetHandleTable().GetObject(kernel, reply_target); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // If we fail to reply, we want to set the output index to -1. @@ -51,7 +48,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes }; // Send the reply. - R_TRY(session->SendReply(message, buffer_size, message_paddr)); + R_TRY(session->SendReply(kernel, message, buffer_size, message_paddr)); } // Receive a message. @@ -77,8 +74,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes while (true) { // Wait for an object. s32 index; - Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, - num_objects, timeout); + Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs, num_objects, timeout); if (ResultTimedOut == result) { R_THROW(result); } @@ -87,7 +83,7 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes if (R_SUCCEEDED(result)) { KServerSession* session = objs[index]->DynamicCast(); if (session != nullptr) { - result = session->ReceiveRequest(message, buffer_size, message_paddr); + result = session->ReceiveRequest(kernel, message, buffer_size, message_paddr); if (ResultNotFound == result) { continue; } @@ -127,14 +123,14 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes // Convert the handles to objects. R_UNLESS( - handle_table.GetMultipleObjects(objs, handles, num_handles), + handle_table.GetMultipleObjects(kernel, objs, handles, num_handles), ResultInvalidHandle); } // Ensure handles are closed when we're done. SCOPE_EXIT { for (auto i = 0; i < num_handles; ++i) { - objs[i]->Close(); + objs[i]->Close(kernel); } }; @@ -188,16 +184,15 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha auto& handle_table = process.GetHandleTable(); // Reserve a new event from the process resource limit. - KScopedResourceReservation event_reservation(std::addressof(process), - Svc::LimitableResource::EventCountMax); + KScopedResourceReservation event_reservation(system.Kernel(), std::addressof(process), Svc::LimitableResource::EventCountMax); R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); // Get the client session. - KScopedAutoObject session = process.GetHandleTable().GetObject(session_handle); + KScopedAutoObject session = process.GetHandleTable().GetObject(system.Kernel(), session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Get the parent, and persist a reference to it until we're done. - KScopedAutoObject parent = session->GetParent(); + KScopedAutoObject parent = {system.Kernel(), session->GetParent()}; ASSERT(parent.IsNotNull()); // Create a new event. @@ -205,30 +200,30 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize(std::addressof(process)); + event->Initialize(system.Kernel(), std::addressof(process)); // Commit our reservation. event_reservation.Commit(); // At end of scope, kill the standing references to the sub events. SCOPE_EXIT { - event->GetReadableEvent().Close(); - event->Close(); + event->GetReadableEvent().Close(system.Kernel()); + event->Close(system.Kernel()); }; // Register the event. KEvent::Register(system.Kernel(), event); // Add the readable event to the handle table. - R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent()))); + R_TRY(handle_table.Add(system.Kernel(), out_event_handle, std::addressof(event->GetReadableEvent()))); // Ensure that if we fail to send the request, we close the readable handle. ON_RESULT_FAILURE { - handle_table.Remove(*out_event_handle); + handle_table.Remove(system.Kernel(), *out_event_handle); }; // Send the async request. - R_RETURN(session->SendAsyncRequest(event, message, buffer_size)); + R_RETURN(session->SendAsyncRequest(system.Kernel(), event, message, buffer_size)); } Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles, s32 num_handles, diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp index 4772cbda17..ae3ff85a88 100644 --- a/src/core/hle/kernel/svc/svc_light_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,12 +17,12 @@ namespace Kernel::Svc { Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { // Get the light client session from its handle. KScopedAutoObject session = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(session_handle); + .GetHandleTable() + .GetObject(system.Kernel(), session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Send the request. - R_TRY(session->SendSyncRequest(args)); + R_TRY(session->SendSyncRequest(system.Kernel(), args)); R_SUCCEED(); } @@ -27,12 +30,12 @@ Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* ar Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { // Get the light server session from its handle. KScopedAutoObject session = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(session_handle); + .GetHandleTable() + .GetObject(system.Kernel(), session_handle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle); // Handle the request. - R_TRY(session->ReplyAndReceive(args)); + R_TRY(session->ReplyAndReceive(system.Kernel(), args)); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp index 9a22dadaf7..bddd57e8f9 100644 --- a/src/core/hle/kernel/svc/svc_port.cpp +++ b/src/core/hle/kernel/svc/svc_port.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,18 +36,18 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, u64 user_name) { // Reserve a handle for the port. // NOTE: Nintendo really does write directly to the output handle here. - R_TRY(handle_table.Reserve(out)); + R_TRY(handle_table.Reserve(system.Kernel(), out)); ON_RESULT_FAILURE { - handle_table.Unreserve(*out); + handle_table.Unreserve(system.Kernel(), *out); }; // Create a session. KClientSession* session; - R_TRY(port->CreateSession(std::addressof(session))); + R_TRY(port->CreateSession(system.Kernel(), std::addressof(session))); // Register the session in the table, close the extra reference. - handle_table.Register(*out, session); - session->Close(); + handle_table.Register(system.Kernel(), *out, session); + session->Close(system.Kernel()); // We succeeded. R_SUCCEED(); @@ -65,27 +68,27 @@ Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client, R_UNLESS(port != nullptr, ResultOutOfResource); // Initialize the port. - port->Initialize(max_sessions, is_light, name); + port->Initialize(system.Kernel(), max_sessions, is_light, name); // Ensure that we clean up the port (and its only references are handle table) on function end. SCOPE_EXIT { - port->GetServerPort().Close(); - port->GetClientPort().Close(); + port->GetServerPort().Close(system.Kernel()); + port->GetClientPort().Close(system.Kernel()); }; // Register the port. KPort::Register(kernel, port); // Add the client to the handle table. - R_TRY(handle_table.Add(out_client, std::addressof(port->GetClientPort()))); + R_TRY(handle_table.Add(system.Kernel(), out_client, std::addressof(port->GetClientPort()))); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(*out_client); + handle_table.Remove(system.Kernel(), *out_client); }; // Add the server to the handle table. - R_RETURN(handle_table.Add(out_server, std::addressof(port->GetServerPort()))); + R_RETURN(handle_table.Add(system.Kernel(), out_server, std::addressof(port->GetServerPort()))); } Result ConnectToPort(Core::System& system, Handle* out, Handle port) { @@ -93,36 +96,33 @@ Result ConnectToPort(Core::System& system, Handle* out, Handle port) { auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Get the client port. - KScopedAutoObject client_port = handle_table.GetObject(port); + KScopedAutoObject client_port = handle_table.GetObject(system.Kernel(), port); R_UNLESS(client_port.IsNotNull(), ResultInvalidHandle); // Reserve a handle for the port. // NOTE: Nintendo really does write directly to the output handle here. - R_TRY(handle_table.Reserve(out)); + R_TRY(handle_table.Reserve(system.Kernel(), out)); ON_RESULT_FAILURE { - handle_table.Unreserve(*out); + handle_table.Unreserve(system.Kernel(), *out); }; // Create the session. KAutoObject* session; - if (client_port->IsLight()) { - R_TRY(client_port->CreateLightSession( - reinterpret_cast(std::addressof(session)))); + if (client_port->IsLight(system.Kernel())) { + R_TRY(client_port->CreateLightSession(system.Kernel(), reinterpret_cast(std::addressof(session)))); } else { - R_TRY(client_port->CreateSession( - reinterpret_cast(std::addressof(session)))); + R_TRY(client_port->CreateSession(system.Kernel(), reinterpret_cast(std::addressof(session)))); } // Register the session. - handle_table.Register(*out, session); - session->Close(); + handle_table.Register(system.Kernel(), *out, session); + session->Close(system.Kernel()); // We succeeded. R_SUCCEED(); } -Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, - int32_t max_sessions) { +Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, int32_t max_sessions) { // Copy the provided name from user memory to kernel memory. auto string_name = GetCurrentMemory(system.Kernel()).ReadCString(user_name, KObjectName::NameLengthMax); @@ -144,21 +144,21 @@ Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t R_UNLESS(port != nullptr, ResultOutOfResource); // Initialize the new port. - port->Initialize(max_sessions, false, 0); + port->Initialize(system.Kernel(), max_sessions, false, 0); // Register the port. KPort::Register(system.Kernel(), port); // Ensure that our only reference to the port is in the handle table when we're done. SCOPE_EXIT { - port->GetClientPort().Close(); - port->GetServerPort().Close(); + port->GetClientPort().Close(system.Kernel()); + port->GetServerPort().Close(system.Kernel()); }; // Register the handle in the table. - R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort()))); + R_TRY(handle_table.Add(system.Kernel(), out_server_handle, std::addressof(port->GetServerPort()))); ON_RESULT_FAILURE { - handle_table.Remove(*out_server_handle); + handle_table.Remove(system.Kernel(), *out_server_handle); }; // Create a new object name. diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index 6d63892a94..dc2566e85a 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -27,8 +27,8 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) { // Get the object from the handle table. KScopedAutoObject obj = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(static_cast(handle)); + .GetHandleTable() + .GetObject(system.Kernel(), Handle(handle)); R_UNLESS(obj.IsNotNull(), ResultInvalidHandle); // Get the process from the object. @@ -98,7 +98,7 @@ Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle, LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type={:#X}", process_handle, info_type); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/kernel/svc/svc_process_memory.cpp b/src/core/hle/kernel/svc/svc_process_memory.cpp index 3313118dfa..0c18be91ba 100644 --- a/src/core/hle/kernel/svc/svc_process_memory.cpp +++ b/src/core/hle/kernel/svc/svc_process_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -48,7 +48,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u // Get the process from its handle. KScopedAutoObject process = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(process_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), process_handle); R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the address is in range. @@ -76,7 +76,7 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha // Get the processes. KProcess* dst_process = GetCurrentProcessPointer(system.Kernel()); KScopedAutoObject src_process = - dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(process_handle); + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(system.Kernel(), process_handle); R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. @@ -117,7 +117,7 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_ // Get the processes. KProcess* dst_process = GetCurrentProcessPointer(system.Kernel()); KScopedAutoObject src_process = - dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(process_handle); + dst_process->GetHandleTable().GetObjectWithoutPseudoHandle(system.Kernel(), process_handle); R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. @@ -174,7 +174,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst } const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); @@ -234,7 +234,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d } const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).", process_handle); diff --git a/src/core/hle/kernel/svc/svc_query_memory.cpp b/src/core/hle/kernel/svc/svc_query_memory.cpp index 816dcb8d0f..ad7a667bb5 100644 --- a/src/core/hle/kernel/svc/svc_query_memory.cpp +++ b/src/core/hle/kernel/svc/svc_query_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,7 +26,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn Handle process_handle, uint64_t address) { LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); - KScopedAutoObject process = handle_table.GetObject(process_handle); + KScopedAutoObject process = handle_table.GetObject(system.Kernel(), process_handle); if (process.IsNull()) { LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}", process_handle); diff --git a/src/core/hle/kernel/svc/svc_resource_limit.cpp b/src/core/hle/kernel/svc/svc_resource_limit.cpp index 6f3972482f..7f78aa8b10 100644 --- a/src/core/hle/kernel/svc/svc_resource_limit.cpp +++ b/src/core/hle/kernel/svc/svc_resource_limit.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,7 +22,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { // Ensure we don't leak a reference to the limit. SCOPE_EXIT { - resource_limit->Close(); + resource_limit->Close(system.Kernel()); }; // Initialize the resource limit. @@ -29,7 +32,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { KResourceLimit::Register(kernel, resource_limit); // Add the limit to the handle table. - R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(out_handle, resource_limit)); + R_RETURN(GetCurrentProcess(kernel).GetHandleTable().Add(system.Kernel(), out_handle, resource_limit)); } Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value, @@ -42,8 +45,8 @@ Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value, // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(resource_limit_handle); + .GetHandleTable() + .GetObject(system.Kernel(), resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Get the limit value. @@ -62,8 +65,8 @@ Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) - .GetHandleTable() - .GetObject(resource_limit_handle); + .GetHandleTable() + .GetObject(system.Kernel(), resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Get the current value. @@ -83,7 +86,7 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha // Get the resource limit. KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject(resource_limit_handle); + .GetObject(system.Kernel(), resource_limit_handle); R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); // Set the limit value. diff --git a/src/core/hle/kernel/svc/svc_session.cpp b/src/core/hle/kernel/svc/svc_session.cpp index b034d21d15..4d04f0c5a3 100644 --- a/src/core/hle/kernel/svc/svc_session.cpp +++ b/src/core/hle/kernel/svc/svc_session.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -23,7 +26,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // Reserve a new session from the process resource limit. // TODO: Dynamic resource limits - KScopedResourceReservation session_reservation(std::addressof(process), + KScopedResourceReservation session_reservation(system.Kernel(), std::addressof(process), LimitableResource::SessionCountMax); if (session_reservation.Succeeded()) { session = T::Create(system.Kernel()); @@ -62,7 +65,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien R_UNLESS(session != nullptr, ResultOutOfResource); // Initialize the session. - session->Initialize(nullptr, name); + session->Initialize(system.Kernel(), nullptr, name); // Commit the session reservation. session_reservation.Commit(); @@ -70,23 +73,23 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien // Ensure that we clean up the session (and its only references are handle table) on function // end. SCOPE_EXIT { - session->GetClientSession().Close(); - session->GetServerSession().Close(); + session->GetClientSession().Close(system.Kernel()); + session->GetServerSession().Close(system.Kernel()); }; // Register the session. T::Register(system.Kernel(), session); // Add the server session to the handle table. - R_TRY(handle_table.Add(out_server, std::addressof(session->GetServerSession()))); + R_TRY(handle_table.Add(system.Kernel(), out_server, std::addressof(session->GetServerSession()))); // Ensure that we maintain a clean handle state on exit. ON_RESULT_FAILURE { - handle_table.Remove(*out_server); + handle_table.Remove(system.Kernel(), *out_server); }; // Add the client session to the handle table. - R_RETURN(handle_table.Add(out_client, std::addressof(session->GetClientSession()))); + R_RETURN(handle_table.Add(system.Kernel(), out_client, std::addressof(session->GetClientSession()))); } } // namespace @@ -105,29 +108,29 @@ Result AcceptSession(Core::System& system, Handle* out, Handle port_handle) { auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); // Get the server port. - KScopedAutoObject port = handle_table.GetObject(port_handle); + KScopedAutoObject port = handle_table.GetObject(system.Kernel(), port_handle); R_UNLESS(port.IsNotNull(), ResultInvalidHandle); // Reserve an entry for the new session. - R_TRY(handle_table.Reserve(out)); + R_TRY(handle_table.Reserve(system.Kernel(), out)); ON_RESULT_FAILURE { - handle_table.Unreserve(*out); + handle_table.Unreserve(system.Kernel(), *out); }; // Accept the session. KAutoObject* session; - if (port->IsLight()) { - session = port->AcceptLightSession(); + if (port->IsLight(system.Kernel())) { + session = port->AcceptLightSession(system.Kernel()); } else { - session = port->AcceptSession(); + session = port->AcceptSession(system.Kernel()); } // Ensure we accepted successfully. R_UNLESS(session != nullptr, ResultNotFound); // Register the session. - handle_table.Register(*out, session); - session->Close(); + handle_table.Register(system.Kernel(), *out, session); + session->Close(system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp index 3ca07abe8b..66cf5902ec 100644 --- a/src/core/hle/kernel/svc/svc_shared_memory.cpp +++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -49,18 +49,18 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u auto& page_table = process.GetPageTable(); // Get the shared memory. - KScopedAutoObject shmem = process.GetHandleTable().GetObject(shmem_handle); + KScopedAutoObject shmem = process.GetHandleTable().GetObject(system.Kernel(), shmem_handle); R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. R_UNLESS(page_table.CanContain(address, size, KMemoryState::Shared), ResultInvalidMemoryRegion); // Add the shared memory to the process. - R_TRY(process.AddSharedMemory(shmem.GetPointerUnsafe(), address, size)); + R_TRY(process.AddSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size)); // Ensure that we clean up the shared memory if we fail to map it. ON_RESULT_FAILURE { - process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); + process.RemoveSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size); }; // Map the shared memory. @@ -79,7 +79,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, auto& page_table = process.GetPageTable(); // Get the shared memory. - KScopedAutoObject shmem = process.GetHandleTable().GetObject(shmem_handle); + KScopedAutoObject shmem = process.GetHandleTable().GetObject(system.Kernel(), shmem_handle); R_UNLESS(shmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -89,7 +89,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, R_TRY(shmem->Unmap(process, address, size)); // Remove the shared memory from the process. - process.RemoveSharedMemory(shmem.GetPointerUnsafe(), address, size); + process.RemoveSharedMemory(system.Kernel(), shmem.GetPointerUnsafe(), address, size); R_SUCCEED(); } diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index fdd4408d4d..1b29fd5865 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -20,7 +20,7 @@ Result CloseHandle(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); // Remove the handle. - R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(handle), + R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(system.Kernel(), handle), ResultInvalidHandle); R_SUCCEED(); @@ -35,17 +35,17 @@ Result ResetSignal(Core::System& system, Handle handle) { // Try to reset as readable event. { - KScopedAutoObject readable_event = handle_table.GetObject(handle); + KScopedAutoObject readable_event = handle_table.GetObject(system.Kernel(), handle); if (readable_event.IsNotNull()) { - R_RETURN(readable_event->Reset()); + R_RETURN(readable_event->Reset(system.Kernel())); } } // Try to reset as process. { - KScopedAutoObject process = handle_table.GetObject(handle); + KScopedAutoObject process = handle_table.GetObject(system.Kernel(), handle); if (process.IsNotNull()) { - R_RETURN(process->Reset()); + R_RETURN(process->Reset(system.Kernel())); } } @@ -62,35 +62,30 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange); // Get the synchronization context. - auto& kernel = system.Kernel(); - auto& handle_table = GetCurrentProcess(kernel).GetHandleTable(); - auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer(); - auto handles = GetCurrentThread(kernel).GetHandleBuffer(); + auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); + auto objs = GetCurrentThread(system.Kernel()).GetSynchronizationObjectBuffer(); + auto handles = GetCurrentThread(system.Kernel()).GetHandleBuffer(); // Copy user handles. if (num_handles > 0) { // Get the handles. - R_UNLESS(GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), - sizeof(Handle) * num_handles), - ResultInvalidPointer); + R_UNLESS(GetCurrentMemory(system.Kernel()).ReadBlock(user_handles, handles.data(), sizeof(Handle) * num_handles), ResultInvalidPointer); // Convert the handles to objects. - R_UNLESS(handle_table.GetMultipleObjects( - objs.data(), handles.data(), num_handles), - ResultInvalidHandle); + R_UNLESS(handle_table.GetMultipleObjects(system.Kernel(), objs.data(), handles.data(), num_handles), ResultInvalidHandle); } // Ensure handles are closed when we're done. SCOPE_EXIT { for (auto i = 0; i < num_handles; ++i) { - objs[i]->Close(); + objs[i]->Close(system.Kernel()); } }; // Convert the timeout from nanoseconds to ticks. s64 timeout; if (timeout_ns > 0) { - u64 ticks = kernel.HardwareTimer().GetTick(); + u64 ticks = system.Kernel().HardwareTimer().GetTick(); ticks += timeout_ns; ticks += 2; @@ -100,7 +95,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha } // Wait on the objects. - Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout); + Result res = KSynchronizationObject::Wait(system.Kernel(), out_index, objs.data(), num_handles, timeout); R_SUCCEED_IF(res == ResultSessionClosed); R_RETURN(res); @@ -111,31 +106,28 @@ Result CancelSynchronization(Core::System& system, Handle handle) { LOG_TRACE(Kernel_SVC, "called handle={:#X}", handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Cancel the thread's wait. - thread->WaitCancel(); + thread->WaitCancel(system.Kernel()); R_SUCCEED(); } void SynchronizePreemptionState(Core::System& system) { - auto& kernel = system.Kernel(); - // Lock the scheduler. - KScopedSchedulerLock sl{kernel}; + KScopedSchedulerLock sl{system.Kernel()}; // If the current thread is pinned, unpin it. - KProcess* cur_process = GetCurrentProcessPointer(kernel); - const auto core_id = GetCurrentCoreId(kernel); + KProcess* cur_process = GetCurrentProcessPointer(system.Kernel()); + const auto core_id = GetCurrentCoreId(system.Kernel()); - if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) { + if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(system.Kernel())) { // Clear the current thread's interrupt flag. - GetCurrentThread(kernel).ClearInterruptFlag(); + GetCurrentThread(system.Kernel()).ClearInterruptFlag(system.Kernel()); // Unpin the current thread. - cur_process->UnpinCurrentThread(); + cur_process->UnpinCurrentThread(system.Kernel()); } } diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 1aa6f87c04..b1159020d3 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -46,7 +46,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Reserve a new thread from the process resource limit (waiting up to 100ms). - KScopedResourceReservation thread_reservation(std::addressof(process), + KScopedResourceReservation thread_reservation(system.Kernel(), std::addressof(process), LimitableResource::ThreadCountMax, 1, kernel.HardwareTimer().GetTick() + 100000000); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); @@ -55,7 +55,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u KThread* thread = KThread::Create(kernel); R_UNLESS(thread != nullptr, ResultOutOfResource) SCOPE_EXIT { - thread->Close(); + thread->Close(system.Kernel()); }; // Initialize the thread. @@ -69,13 +69,13 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u thread_reservation.Commit(); // Clone the current fpu status to the new thread. - thread->CloneFpuStatus(); + thread->CloneFpuStatus(system.Kernel()); // Register the new thread. KThread::Register(kernel, thread); // Add the thread to the handle table. - R_TRY(process.GetHandleTable().Add(out_handle, thread)); + R_TRY(process.GetHandleTable().Add(system.Kernel(), out_handle, thread)); // Pass the thread handle to the thread local region. process.GetMemory().Write32(GetInteger(thread->GetTlsAddress()) + 0x110, *out_handle); @@ -88,12 +88,11 @@ Result StartThread(Core::System& system, Handle thread_handle) { LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Try to start the thread. - R_TRY(thread->Run()); + R_TRY(thread->Run(system.Kernel())); R_SUCCEED(); } @@ -102,7 +101,7 @@ Result StartThread(Core::System& system, Handle thread_handle) { void ExitThread(Core::System& system) { auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); system.GlobalSchedulerContext().RemoveThread(current_thread); - current_thread->Exit(); + current_thread->Exit(system.Kernel()); } /// Sleep the current thread @@ -130,7 +129,7 @@ void SleepThread(Core::System& system, s64 ns) { // Sleep. // NOTE: Nintendo does not check the result of this sleep. - static_cast(GetCurrentThread(kernel).Sleep(timeout)); + static_cast(GetCurrentThread(kernel).Sleep(kernel, timeout)); } else if (yield_type == Svc::YieldType::WithoutCoreMigration) { KScheduler::YieldWithoutCoreMigration(kernel); } else if (yield_type == Svc::YieldType::WithCoreMigration) { @@ -144,27 +143,23 @@ void SleepThread(Core::System& system, s64 ns) { /// Gets the thread context Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) { - LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, - thread_handle); - - auto& kernel = system.Kernel(); + LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(kernel).GetHandleTable().GetObject(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Require the handle be to a non-current thread in the current process. - R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(kernel), ResultInvalidHandle); - R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultBusy); + R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()), ResultInvalidHandle); + R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy); // Get the thread context. Svc::ThreadContext context{}; - R_TRY(thread->GetThreadContext3(std::addressof(context))); + R_TRY(thread->GetThreadContext3(system.Kernel(), std::addressof(context))); // Copy the thread context to user space. R_UNLESS( - GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)), + GetCurrentMemory(system.Kernel()).WriteBlock(out_context, std::addressof(context), sizeof(context)), ResultInvalidPointer); R_SUCCEED(); @@ -175,8 +170,7 @@ Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle) LOG_TRACE(Kernel_SVC, "called"); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's priority. @@ -195,11 +189,11 @@ Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priorit R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Get the thread from its handle. - KScopedAutoObject thread = process.GetHandleTable().GetObject(thread_handle); + KScopedAutoObject thread = process.GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the thread priority. - thread->SetBasePriority(priority); + thread->SetBasePriority(system.Kernel(), priority); R_SUCCEED(); } @@ -248,12 +242,11 @@ Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affini LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the core mask. - R_RETURN(thread->GetCoreMask(out_core_id, out_affinity_mask)); + R_RETURN(thread->GetCoreMask(system.Kernel(), out_core_id, out_affinity_mask)); } Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, @@ -279,18 +272,17 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id // Get the thread from its handle. KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); + GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Set the core mask. - R_RETURN(thread->SetCoreMask(core_id, affinity_mask)); + R_RETURN(thread->SetCoreMask(system.Kernel(), core_id, affinity_mask)); } /// Get the ID for the specified thread. Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { // Get the thread from its handle. - KScopedAutoObject thread = - GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(thread_handle); + KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject(system.Kernel(), thread_handle); R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); // Get the thread's id. diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp index 2ea0d44215..e539eee911 100644 --- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -43,8 +46,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 auto& handle_table = process.GetHandleTable(); // Reserve a new transfer memory from the process resource limit. - KScopedResourceReservation trmem_reservation(std::addressof(process), - LimitableResource::TransferMemoryCountMax); + KScopedResourceReservation trmem_reservation(system.Kernel(), std::addressof(process), LimitableResource::TransferMemoryCountMax); R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); // Create the transfer memory. @@ -53,14 +55,14 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 // Ensure the only reference is in the handle table when we're done. SCOPE_EXIT { - trmem->Close(); + trmem->Close(system.Kernel()); }; // Ensure that the region is in range. R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the transfer memory. - R_TRY(trmem->Initialize(address, size, map_perm)); + R_TRY(trmem->Initialize(system.Kernel(), address, size, map_perm)); // Commit the reservation. trmem_reservation.Commit(); @@ -69,7 +71,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 KTransferMemory::Register(kernel, trmem); // Add the transfer memory to the handle table. - R_RETURN(handle_table.Add(out, trmem)); + R_RETURN(handle_table.Add(system.Kernel(), out, trmem)); } Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, @@ -86,7 +88,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add // Get the transfer memory. KScopedAutoObject trmem = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject(trmem_handle); + .GetObject(system.Kernel(), trmem_handle); R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -96,7 +98,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add ResultInvalidMemoryRegion); // Map the transfer memory. - R_TRY(trmem->Map(address, size, map_perm)); + R_TRY(trmem->Map(system.Kernel(), address, size, map_perm)); // We succeeded. R_SUCCEED(); @@ -113,7 +115,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a // Get the transfer memory. KScopedAutoObject trmem = GetCurrentProcess(system.Kernel()) .GetHandleTable() - .GetObject(trmem_handle); + .GetObject(system.Kernel(), trmem_handle); R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle); // Verify that the mapping is in range. @@ -123,7 +125,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a ResultInvalidMemoryRegion); // Unmap the transfer memory. - R_TRY(trmem->Unmap(address, size)); + R_TRY(trmem->Unmap(system.Kernel(), address, size)); R_SUCCEED(); } diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp index c9e0af90ce..c767e46e8f 100644 --- a/src/core/hle/service/acc/async_context.cpp +++ b/src/core/hle/service/acc/async_context.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -64,7 +67,7 @@ void IAsyncContext::GetResult(HLERequestContext& ctx) { void IAsyncContext::MarkComplete() { is_complete.store(true); - completion_event->Signal(); + completion_event->Signal(system.Kernel()); } } // namespace Service::Account diff --git a/src/core/hle/service/am/applet.cpp b/src/core/hle/service/am/applet.cpp index 2ae3102aff..efedcc5692 100644 --- a/src/core/hle/service/am/applet.cpp +++ b/src/core/hle/service/am/applet.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator @@ -52,7 +52,7 @@ void Applet::UpdateSuspensionStateLocked(bool force_message) { // Signal if the focus state was changed or the process state was changed. if (update_requested_focus_state || was_changed || force_message) { - lifecycle_manager.SignalSystemEventIfNeeded(); + lifecycle_manager.SignalSystemEventIfNeeded(context.kernel); } } @@ -76,7 +76,7 @@ void Applet::SetInteractibleLocked(bool interactible) { void Applet::OnProcessTerminatedLocked() { is_completed = true; - state_changed_event.Signal(); + state_changed_event.Signal(context.kernel); } } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_data_broker.cpp b/src/core/hle/service/am/applet_data_broker.cpp index fff78c5afb..f75baac282 100644 --- a/src/core/hle/service/am/applet_data_broker.cpp +++ b/src/core/hle/service/am/applet_data_broker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,22 +14,23 @@ namespace Service::AM { AppletStorageChannel::AppletStorageChannel(KernelHelpers::ServiceContext& context) - : m_event(context) {} + : m_event(context) +{} AppletStorageChannel::~AppletStorageChannel() = default; -void AppletStorageChannel::Push(std::shared_ptr storage) { +void AppletStorageChannel::Push(Kernel::KernelCore& kernel, std::shared_ptr storage) { std::scoped_lock lk{m_lock}; m_data.emplace_back(std::move(storage)); - m_event.Signal(); + m_event.Signal(kernel); } -Result AppletStorageChannel::Pop(std::shared_ptr* out_storage) { +Result AppletStorageChannel::Pop(Kernel::KernelCore& kernel, std::shared_ptr* out_storage) { std::scoped_lock lk{m_lock}; SCOPE_EXIT { if (m_data.empty()) { - m_event.Clear(); + m_event.Clear(kernel); } }; diff --git a/src/core/hle/service/am/applet_data_broker.h b/src/core/hle/service/am/applet_data_broker.h index 2718f608ad..36ce8a24d4 100644 --- a/src/core/hle/service/am/applet_data_broker.h +++ b/src/core/hle/service/am/applet_data_broker.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,8 +25,8 @@ public: explicit AppletStorageChannel(KernelHelpers::ServiceContext& ctx); ~AppletStorageChannel(); - void Push(std::shared_ptr storage); - Result Pop(std::shared_ptr* out_storage); + void Push(Kernel::KernelCore& kernel, std::shared_ptr storage); + Result Pop(Kernel::KernelCore& kernel, std::shared_ptr* out_storage); Kernel::KReadableEvent* GetEvent(); private: diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp index c2920f91ae..2388faa541 100644 --- a/src/core/hle/service/am/applet_manager.cpp +++ b/src/core/hle/service/am/applet_manager.cpp @@ -34,8 +34,7 @@ struct LaunchParameterAccountPreselectedUser { }; static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); -AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, - std::shared_ptr& applet) { +AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system, std::shared_ptr& applet) { applet->caller_applet_broker = std::make_shared(system); return applet->caller_applet_broker->GetInData(); } @@ -52,7 +51,7 @@ void PushInShowQlaunch(Core::System& system, AppletStorageChannel& channel) { std::vector argument_data(sizeof(arguments)); std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - channel.Push(std::make_shared(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); } void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { @@ -68,8 +67,8 @@ void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) { std::vector argument_data(sizeof(arguments)); std::vector settings_data{2}; std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); - channel.Push(std::make_shared(system, std::move(argument_data))); - channel.Push(std::make_shared(system, std::move(settings_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(settings_data))); } void PushInShowController(Core::System& system, AppletStorageChannel& channel) { @@ -116,9 +115,9 @@ void PushInShowController(Core::System& system, AppletStorageChannel& channel) { std::memcpy(private_args_data.data(), &private_args, sizeof(private_args)); std::memcpy(user_args_data.data(), &user_args, sizeof(user_args)); - channel.Push(std::make_shared(system, std::move(common_args_data))); - channel.Push(std::make_shared(system, std::move(private_args_data))); - channel.Push(std::make_shared(system, std::move(user_args_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(common_args_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(private_args_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(user_args_data))); } void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) { @@ -146,8 +145,8 @@ void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) std::vector settings_data(sizeof(amiibo_settings)); std::memcpy(argument_data.data(), &arguments, sizeof(arguments)); std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings)); - channel.Push(std::make_shared(system, std::move(argument_data))); - channel.Push(std::make_shared(system, std::move(settings_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(settings_data))); } void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) { @@ -169,7 +168,7 @@ void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) std::vector argument_data(sizeof(mii_arguments)); std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments)); - channel.Push(std::make_shared(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); } void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) { @@ -222,9 +221,9 @@ void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& chan std::memcpy(work_buffer.data(), initial_string.data(), swkbd_config.initial_string_length * sizeof(char16_t)); - channel.Push(std::make_shared(system, std::move(argument_data))); - channel.Push(std::make_shared(system, std::move(swkbd_data))); - channel.Push(std::make_shared(system, std::move(work_buffer))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(argument_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(swkbd_data))); + channel.Push(system.Kernel(), std::make_shared(system, std::move(work_buffer))); } } // namespace @@ -268,7 +267,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { if (Settings::values.enable_overlay && m_window_system->GetOverlayDisplayApplet() == nullptr) { if (auto overlay_process = CreateProcess(m_system, static_cast(AppletProgramId::OverlayDisplay), 0, 0)) { - auto overlay_applet = std::make_shared(m_system, std::move(overlay_process), false); + auto overlay_applet = std::make_shared(m_system, std::make_unique(*std::move(overlay_process)), false); overlay_applet->program_id = static_cast(AppletProgramId::OverlayDisplay); overlay_applet->applet_id = AppletId::OverlayDisplay; overlay_applet->type = AppletType::OverlayApplet; @@ -340,7 +339,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) { } // Applet was started by frontend, so it is foreground. - applet->lifecycle_manager.SetFocusState(FocusState::InFocus); + applet->lifecycle_manager.SetFocusState(m_system.Kernel(), FocusState::InFocus); if (applet->applet_id == AppletId::QLaunch) { applet->lifecycle_manager.SetFocusHandlingMode(false); diff --git a/src/core/hle/service/am/button_poller.cpp b/src/core/hle/service/am/button_poller.cpp index 069a1934d4..6999acfa12 100644 --- a/src/core/hle/service/am/button_poller.cpp +++ b/src/core/hle/service/am/button_poller.cpp @@ -1,9 +1,11 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include "common/thread.h" #include "core/core.h" #include "core/hle/service/am/am_types.h" #include "core/hle/service/am/button_poller.h" @@ -34,16 +36,15 @@ ButtonPressDuration ClassifyPressDuration(std::chrono::steady_clock::time_point } // namespace -ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) - : m_window_system(window_system) { +ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) { // TODO: am reads this from the home button state in hid, which is controller-agnostic. Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = - [this](Core::HID::ControllerTriggerType type) { - if (type == Core::HID::ControllerTriggerType::Button) { - this->OnButtonStateChanged(); - } - }, + .on_change = [this, &window_system](Core::HID::ControllerTriggerType type) { + if (type == Core::HID::ControllerTriggerType::Button) { + std::unique_lock lk{m_mutex}; + OnButtonStateChanged(window_system); + } + }, .is_npad_service = true, }; @@ -52,25 +53,35 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); m_player1_key = m_player1->SetCallback(engine_callback); - m_thread = std::thread([this] { this->ThreadLoop(); }); + m_thread = std::jthread([this, &window_system](std::stop_token stop_token) { + Common::SetCurrentThreadName("ButtonPoller"); + while (!stop_token.stop_requested()) { + using namespace std::chrono_literals; + std::unique_lock lk{m_mutex}; + m_cv.wait_for(lk, 50ms); + if (stop_token.stop_requested()) + break; + OnButtonStateChanged(window_system); + std::this_thread::sleep_for(5ms); + } + }); } ButtonPoller::~ButtonPoller() { m_handheld->DeleteCallback(m_handheld_key); m_player1->DeleteCallback(m_player1_key); - m_stop = true; m_cv.notify_all(); if (m_thread.joinable()) { + m_thread.request_stop(); m_thread.join(); } } -void ButtonPoller::OnButtonStateChanged() { - std::lock_guard lk{m_mutex}; - const bool home_button = - m_handheld->GetHomeButtons().home.Value() || m_player1->GetHomeButtons().home.Value(); - const bool capture_button = m_handheld->GetCaptureButtons().capture.Value() || - m_player1->GetCaptureButtons().capture.Value(); +void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) { + auto const home_button = m_handheld->GetHomeButtons().home.Value() + || m_player1->GetHomeButtons().home.Value(); + auto const capture_button = m_handheld->GetCaptureButtons().capture.Value() + || m_player1->GetCaptureButtons().capture.Value(); // Buttons pressed which were not previously pressed if (home_button && !m_home_button_press_start) { @@ -90,7 +101,7 @@ void ButtonPoller::OnButtonStateChanged() { if (home_button && m_home_button_press_start && !m_home_button_long_sent) { const auto duration = ClassifyPressDuration(*m_home_button_press_start); if (duration != ButtonPressDuration::ShortPressing) { - m_window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); + window_system.OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); m_home_button_long_sent = true; } } @@ -98,7 +109,7 @@ void ButtonPoller::OnButtonStateChanged() { if (capture_button && m_capture_button_press_start && !m_capture_button_long_sent) { const auto duration = ClassifyPressDuration(*m_capture_button_press_start); if (duration != ButtonPressDuration::ShortPressing) { - m_window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing); + window_system.OnSystemButtonPress(SystemButtonType::CaptureButtonLongPressing); m_capture_button_long_sent = true; } } @@ -107,9 +118,8 @@ void ButtonPoller::OnButtonStateChanged() { if (!home_button && m_home_button_press_start) { if(!m_home_button_long_sent) { const auto duration = ClassifyPressDuration(*m_home_button_press_start); - m_window_system.OnSystemButtonPress( - duration == ButtonPressDuration::ShortPressing ? SystemButtonType::HomeButtonShortPressing - : SystemButtonType::HomeButtonLongPressing); + window_system.OnSystemButtonPress(duration == ButtonPressDuration::ShortPressing + ? SystemButtonType::HomeButtonShortPressing : SystemButtonType::HomeButtonLongPressing); } m_home_button_press_start = std::nullopt; m_home_button_long_sent = false; @@ -117,9 +127,8 @@ void ButtonPoller::OnButtonStateChanged() { if (!capture_button && m_capture_button_press_start) { if (!m_capture_button_long_sent) { const auto duration = ClassifyPressDuration(*m_capture_button_press_start); - m_window_system.OnSystemButtonPress( - duration == ButtonPressDuration::ShortPressing ? SystemButtonType::CaptureButtonShortPressing - : SystemButtonType::CaptureButtonLongPressing); + window_system.OnSystemButtonPress(duration == ButtonPressDuration::ShortPressing + ? SystemButtonType::CaptureButtonShortPressing : SystemButtonType::CaptureButtonLongPressing); } m_capture_button_press_start = std::nullopt; m_capture_button_long_sent = false; @@ -130,16 +139,4 @@ void ButtonPoller::OnButtonStateChanged() { // } } -void ButtonPoller::ThreadLoop() { - using namespace std::chrono_literals; - std::unique_lock lk{m_mutex}; - while (!m_stop) { - m_cv.wait_for(lk, 50ms); - if (m_stop) break; - lk.unlock(); - OnButtonStateChanged(); - lk.lock(); - } -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/button_poller.h b/src/core/hle/service/am/button_poller.h index 12e7035aa1..11d147d328 100644 --- a/src/core/hle/service/am/button_poller.h +++ b/src/core/hle/service/am/button_poller.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -30,31 +30,23 @@ class ButtonPoller { public: explicit ButtonPoller(Core::System& system, WindowSystem& window_system); ~ButtonPoller(); + void OnButtonStateChanged(WindowSystem& window_system); private: - void OnButtonStateChanged(); - void ThreadLoop(); - -private: - WindowSystem& m_window_system; - - Core::HID::EmulatedController* m_handheld{}; - int m_handheld_key{}; - Core::HID::EmulatedController* m_player1{}; - int m_player1_key{}; - + std::mutex m_mutex; + std::condition_variable m_cv; + std::jthread m_thread; std::optional m_home_button_press_start{}; std::optional m_capture_button_press_start{}; std::optional m_power_button_press_start{}; - bool m_home_button_long_sent{}; - bool m_capture_button_long_sent{}; - bool m_power_button_long_sent{}; - - std::thread m_thread; - std::atomic m_stop{false}; - std::condition_variable m_cv; - std::mutex m_mutex; + Core::HID::EmulatedController* m_handheld{}; + Core::HID::EmulatedController* m_player1{}; + int32_t m_handheld_key{}; + int32_t m_player1_key{}; + bool m_home_button_long_sent : 1 = false; + bool m_capture_button_long_sent : 1 = false; + bool m_power_button_long_sent : 1 = false; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.cpp b/src/core/hle/service/am/event_observer.cpp index 5d1d303ed3..32cb35ee30 100644 --- a/src/core/hle/service/am/event_observer.cpp +++ b/src/core/hle/service/am/event_observer.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,18 +18,30 @@ enum class UserDataTag : u32 { }; EventObserver::EventObserver(Core::System& system, WindowSystem& window_system) - : m_system(system), m_context(system, "am:EventObserver"), m_window_system(window_system), - m_wakeup_event(m_context), m_wakeup_holder(m_wakeup_event.GetHandle()) { + : m_system(system), m_context(system, "am:EventObserver") + , m_window_system(window_system) + , m_wakeup_event(m_context) + , m_wakeup_holder(m_wakeup_event.GetHandle()) +{ m_window_system.SetEventObserver(this); m_wakeup_holder.SetUserData(static_cast(UserDataTag::WakeupEvent)); m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait)); - m_thread = std::thread([&] { this->ThreadFunc(); }); + m_thread = std::thread([this] { + Common::SetCurrentThreadName("am:EventObserver"); + while (true) { + auto* signaled_holder = this->WaitSignaled(); + if (!signaled_holder) { + break; + } + this->Process(signaled_holder); + } + }); } EventObserver::~EventObserver() { // Signal thread and wait for processing to finish. m_stop_source.request_stop(); - m_wakeup_event.Signal(); + m_wakeup_event.Signal(m_system.Kernel()); m_thread.join(); // Free remaining owned sessions. @@ -61,11 +76,11 @@ void EventObserver::TrackAppletProcess(Applet& applet) { } // Signal wakeup. - m_wakeup_event.Signal(); + m_wakeup_event.Signal(m_system.Kernel()); } void EventObserver::RequestUpdate() { - m_wakeup_event.Signal(); + m_wakeup_event.Signal(m_system.Kernel()); } void EventObserver::LinkDeferred() { @@ -106,7 +121,7 @@ void EventObserver::Process(MultiWaitHolder* holder) { } void EventObserver::OnWakeupEvent(MultiWaitHolder* holder) { - m_wakeup_event.Clear(); + m_wakeup_event.Clear(m_system.Kernel()); // Perform recalculation. m_window_system.Update(); @@ -146,17 +161,4 @@ void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) { delete holder; } -void EventObserver::ThreadFunc() { - Common::SetCurrentThreadName("am:EventObserver"); - - while (true) { - auto* signaled_holder = this->WaitSignaled(); - if (!signaled_holder) { - break; - } - - this->Process(signaled_holder); - } -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/event_observer.h b/src/core/hle/service/am/event_observer.h index 3e52e8494d..a0fa13f823 100644 --- a/src/core/hle/service/am/event_observer.h +++ b/src/core/hle/service/am/event_observer.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,9 +44,6 @@ private: private: void DestroyAppletProcessHolderLocked(ProcessHolder* holder); -private: - void ThreadFunc(); - private: // System reference and context. Core::System& m_system; diff --git a/src/core/hle/service/am/frontend/applet_general.cpp b/src/core/hle/service/am/frontend/applet_general.cpp index 5345fdec33..22cad54b66 100644 --- a/src/core/hle/service/am/frontend/applet_general.cpp +++ b/src/core/hle/service/am/frontend/applet_general.cpp @@ -20,16 +20,16 @@ namespace Service::AM::Frontend { constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; -static void LogCurrentStorage(std::shared_ptr applet, std::string_view prefix) { +static void LogCurrentStorage(Kernel::KernelCore& kernel, std::shared_ptr applet, std::string_view prefix) { std::shared_ptr storage; - while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(&storage))) { + while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(kernel, &storage))) { const auto data = storage->GetData(); LOG_INFO(Service_AM, "called (STUBBED), during {} received normal data with size={:08X}, data={}", prefix, data.size(), Common::HexToString(data)); } - while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(&storage))) { + while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(kernel, &storage))) { const auto data = storage->GetData(); LOG_INFO(Service_AM, "called (STUBBED), during {} received interactive data with size={:08X}, data={}", @@ -219,7 +219,7 @@ void StubApplet::Initialize() { LOG_WARNING(Service_AM, "called (STUBBED)"); FrontendApplet::Initialize(); - LogCurrentStorage(applet.lock(), "Initialize"); + LogCurrentStorage(system.Kernel(), applet.lock(), "Initialize"); } Result StubApplet::GetStatus() const { @@ -229,7 +229,7 @@ Result StubApplet::GetStatus() const { void StubApplet::ExecuteInteractive() { LOG_WARNING(Service_AM, "called (STUBBED)"); - LogCurrentStorage(applet.lock(), "ExecuteInteractive"); + LogCurrentStorage(system.Kernel(), applet.lock(), "ExecuteInteractive"); PushOutData(std::make_shared(system, std::vector(0x1000))); PushInteractiveOutData(std::make_shared(system, std::vector(0x1000))); @@ -238,7 +238,7 @@ void StubApplet::ExecuteInteractive() { void StubApplet::Execute() { LOG_WARNING(Service_AM, "called (STUBBED)"); - LogCurrentStorage(applet.lock(), "Execute"); + LogCurrentStorage(system.Kernel(), applet.lock(), "Execute"); PushOutData(std::make_shared(system, std::vector(0x1000))); PushInteractiveOutData(std::make_shared(system, std::vector(0x1000))); diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp index 2ff2bcdbb6..407ca10602 100644 --- a/src/core/hle/service/am/frontend/applets.cpp +++ b/src/core/hle/service/am/frontend/applets.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include @@ -52,22 +52,22 @@ void FrontendApplet::Initialize() { std::shared_ptr FrontendApplet::PopInData() { std::shared_ptr ret; - applet.lock()->caller_applet_broker->GetInData().Pop(&ret); + applet.lock()->caller_applet_broker->GetInData().Pop(system.Kernel(), &ret); return ret; } std::shared_ptr FrontendApplet::PopInteractiveInData() { std::shared_ptr ret; - applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(&ret); + applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(system.Kernel(), &ret); return ret; } void FrontendApplet::PushOutData(std::shared_ptr storage) { - applet.lock()->caller_applet_broker->GetOutData().Push(storage); + applet.lock()->caller_applet_broker->GetOutData().Push(system.Kernel(), storage); } void FrontendApplet::PushInteractiveOutData(std::shared_ptr storage) { - applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(storage); + applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(system.Kernel(), storage); } void FrontendApplet::Exit() { @@ -75,7 +75,7 @@ void FrontendApplet::Exit() { std::scoped_lock lk{applet_->lock}; applet_->is_completed = true; - applet_->state_changed_event.Signal(); + applet_->state_changed_event.Signal(system.Kernel()); } FrontendAppletSet::FrontendAppletSet() = default; diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp index 0412c215d5..8b14511c72 100644 --- a/src/core/hle/service/am/library_applet_storage.cpp +++ b/src/core/hle/service/am/library_applet_storage.cpp @@ -1,7 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/service/am/am_results.h" #include "core/hle/service/am/library_applet_storage.h" #include "core/memory.h" @@ -55,15 +59,18 @@ private: class TransferMemoryLibraryAppletStorage : public LibraryAppletStorage { public: - explicit TransferMemoryLibraryAppletStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, bool is_writable, - s64 size) - : m_memory(memory), m_trmem(trmem), m_is_writable(is_writable), m_size(size) { - m_trmem->Open(); + explicit TransferMemoryLibraryAppletStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size) + : m_kernel{kernel} + , m_memory(memory) + , m_trmem(trmem) + , m_is_writable(is_writable) + , m_size(size) + { + m_trmem->Open(m_kernel); } ~TransferMemoryLibraryAppletStorage() { - m_trmem->Close(); + m_trmem->Close(m_kernel); m_trmem = nullptr; } @@ -93,6 +100,7 @@ public: } protected: + Kernel::KernelCore& m_kernel; Core::Memory::Memory& m_memory; Kernel::KTransferMemory* m_trmem; bool m_is_writable; @@ -101,9 +109,9 @@ protected: class HandleLibraryAppletStorage : public TransferMemoryLibraryAppletStorage { public: - explicit HandleLibraryAppletStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, s64 size) - : TransferMemoryLibraryAppletStorage(memory, trmem, true, size) {} + explicit HandleLibraryAppletStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size) + : TransferMemoryLibraryAppletStorage(kernel, memory, trmem, true, size) + {} ~HandleLibraryAppletStorage() = default; Kernel::KTransferMemory* GetHandle() override { @@ -125,16 +133,12 @@ std::shared_ptr CreateStorage(std::vector&& data) { return std::make_shared(std::move(data)); } -std::shared_ptr CreateTransferMemoryStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, - bool is_writable, s64 size) { - return std::make_shared(memory, trmem, is_writable, size); +std::shared_ptr CreateTransferMemoryStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size) { + return std::make_shared(kernel, memory, trmem, is_writable, size); } -std::shared_ptr CreateHandleStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, - s64 size) { - return std::make_shared(memory, trmem, size); +std::shared_ptr CreateHandleStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size) { + return std::make_shared(kernel, memory, trmem, size); } } // namespace Service::AM diff --git a/src/core/hle/service/am/library_applet_storage.h b/src/core/hle/service/am/library_applet_storage.h index 7f53f3a9cd..cfdbef96d0 100644 --- a/src/core/hle/service/am/library_applet_storage.h +++ b/src/core/hle/service/am/library_applet_storage.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,6 +13,7 @@ class Memory; } namespace Kernel { +class KernelCore; class KTransferMemory; } @@ -27,10 +31,7 @@ public: }; std::shared_ptr CreateStorage(std::vector&& data); -std::shared_ptr CreateTransferMemoryStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, - bool is_writable, s64 size); -std::shared_ptr CreateHandleStorage(Core::Memory::Memory& memory, - Kernel::KTransferMemory* trmem, s64 size); +std::shared_ptr CreateTransferMemoryStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, bool is_writable, s64 size); +std::shared_ptr CreateHandleStorage(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KTransferMemory* trmem, s64 size); } // namespace Service::AM diff --git a/src/core/hle/service/am/lifecycle_manager.cpp b/src/core/hle/service/am/lifecycle_manager.cpp index a79ef6f5f5..8d6965a06c 100644 --- a/src/core/hle/service/am/lifecycle_manager.cpp +++ b/src/core/hle/service/am/lifecycle_manager.cpp @@ -28,9 +28,9 @@ Event& LifecycleManager::GetHDCPStateChangedEvent() { return m_hdcp_state_changed_event; } -void LifecycleManager::PushUnorderedMessage(AppletMessage message) { +void LifecycleManager::PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message) { m_unordered_messages.push_back(message); - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } AppletMessage LifecycleManager::PopMessageInOrderOfPriority() { @@ -144,36 +144,36 @@ bool LifecycleManager::ShouldSignalSystemEvent() { m_has_album_screen_shot_taken || m_has_album_recording_saved; } -void LifecycleManager::OnOperationAndPerformanceModeChanged() { +void LifecycleManager::OnOperationAndPerformanceModeChanged(Kernel::KernelCore& kernel) { if (m_operation_mode_changed_notification_enabled) { m_has_operation_mode_changed = true; } if (m_performance_mode_changed_notification_enabled) { m_has_performance_mode_changed = true; } - m_operation_mode_changed_system_event.Signal(); - this->SignalSystemEventIfNeeded(); + m_operation_mode_changed_system_event.Signal(kernel); + this->SignalSystemEventIfNeeded(kernel); } -void LifecycleManager::SignalSystemEventIfNeeded() { +void LifecycleManager::SignalSystemEventIfNeeded(Kernel::KernelCore& kernel) { // Check our cached value for the system event. const bool applet_message_available = m_applet_message_available; // If it's not current, we need to do an update, either clearing or signaling. if (applet_message_available != this->ShouldSignalSystemEvent()) { if (!applet_message_available) { - m_system_event.Signal(); + m_system_event.Signal(kernel); m_applet_message_available = true; } else { - m_system_event.Clear(); + m_system_event.Clear(kernel); m_applet_message_available = false; } } } -bool LifecycleManager::PopMessage(AppletMessage* out_message) { +bool LifecycleManager::PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message) { const auto message = this->PopMessageInOrderOfPriority(); - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); *out_message = message; return message != AppletMessage::None; diff --git a/src/core/hle/service/am/lifecycle_manager.h b/src/core/hle/service/am/lifecycle_manager.h index a1ddb9e2df..615aeed591 100644 --- a/src/core/hle/service/am/lifecycle_manager.h +++ b/src/core/hle/service/am/lifecycle_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -66,17 +69,17 @@ public: return m_acknowledged_focus_state; } - void SetFocusState(FocusState state) { + void SetFocusState(Kernel::KernelCore& kernel, FocusState state) { if (m_requested_focus_state != state) { m_has_focus_state_changed = true; } m_requested_focus_state = state; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } - void RequestExit() { + void RequestExit(Kernel::KernelCore& kernel) { m_has_requested_exit = true; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } void RequestResumeNotification() { @@ -89,22 +92,22 @@ public: } } - void OnOperationAndPerformanceModeChanged(); + void OnOperationAndPerformanceModeChanged(Kernel::KernelCore& kernel); public: - void SetFocusStateChangedNotificationEnabled(bool enabled) { + void SetFocusStateChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { m_focus_state_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } - void SetOperationModeChangedNotificationEnabled(bool enabled) { + void SetOperationModeChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { m_operation_mode_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } - void SetPerformanceModeChangedNotificationEnabled(bool enabled) { + void SetPerformanceModeChangedNotificationEnabled(Kernel::KernelCore& kernel, bool enabled) { m_performance_mode_changed_notification_enabled = enabled; - this->SignalSystemEventIfNeeded(); + this->SignalSystemEventIfNeeded(kernel); } void SetResumeNotificationEnabled(bool enabled) { @@ -129,11 +132,11 @@ public: void RemoveForceResumeIfPossible(); bool IsRunnable() const; bool UpdateRequestedFocusState(); - void SignalSystemEventIfNeeded(); + void SignalSystemEventIfNeeded(Kernel::KernelCore& kernel); public: - void PushUnorderedMessage(AppletMessage message); - bool PopMessage(AppletMessage* out_message); + void PushUnorderedMessage(Kernel::KernelCore& kernel, AppletMessage message); + bool PopMessage(Kernel::KernelCore& kernel, AppletMessage* out_message); private: FocusState GetFocusStateWhileForegroundObscured() const; diff --git a/src/core/hle/service/am/process_creation.cpp b/src/core/hle/service/am/process_creation.cpp index b5e31353a2..e34e86a82c 100644 --- a/src/core/hle/service/am/process_creation.cpp +++ b/src/core/hle/service/am/process_creation.cpp @@ -1,6 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include "core/core.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/nca_metadata.h" @@ -16,7 +20,7 @@ namespace Service::AM { namespace { -FileSys::StorageId GetStorageIdForFrontendSlot( +[[nodiscard]] FileSys::StorageId GetStorageIdForFrontendSlot( std::optional slot) { if (!slot.has_value()) { return FileSys::StorageId::None; @@ -36,31 +40,23 @@ FileSys::StorageId GetStorageIdForFrontendSlot( } } -std::unique_ptr CreateProcessImpl(std::unique_ptr& out_loader, - Loader::ResultStatus& out_load_result, - Core::System& system, FileSys::VirtualFile file, - u64 program_id, u64 program_index) { +[[nodiscard]] inline std::optional CreateProcessImpl(std::unique_ptr& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) { // Get the appropriate loader to parse this NCA. out_loader = Loader::GetLoader(system, file, program_id, program_index); - // Ensure we have a loader which can parse the NCA. - if (!out_loader) { - return nullptr; + if (out_loader) { + // Try to load the process. + auto process = std::make_optional(system); + if (process->Initialize(*out_loader, out_load_result)) { + return process; + } } - - // Try to load the process. - auto process = std::make_unique(system); - if (process->Initialize(*out_loader, out_load_result)) { - return process; - } - - return nullptr; + return std::nullopt; } } // Anonymous namespace -std::unique_ptr CreateProcess(Core::System& system, u64 program_id, - u8 minimum_key_generation, u8 maximum_key_generation) { +std::optional CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation) { // Attempt to load program NCA. FileSys::VirtualFile nca_raw{}; @@ -70,7 +66,7 @@ std::unique_ptr CreateProcess(Core::System& system, u64 program_id, // Ensure we retrieved a program NCA. if (!nca_raw) { - return nullptr; + return std::nullopt; } // Ensure we have a suitable version. @@ -79,9 +75,8 @@ std::unique_ptr CreateProcess(Core::System& system, u64 program_id, if (nca.GetStatus() == Loader::ResultStatus::Success && (nca.GetKeyGeneration() < minimum_key_generation || nca.GetKeyGeneration() > maximum_key_generation)) { - LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, - nca.GetKeyGeneration()); - return nullptr; + LOG_WARNING(Service_LDR, "Skipping program {:016X} with generation {}", program_id, nca.GetKeyGeneration()); + return std::nullopt; } } @@ -90,42 +85,32 @@ std::unique_ptr CreateProcess(Core::System& system, u64 program_id, return CreateProcessImpl(loader, status, system, nca_raw, program_id, 0); } -std::unique_ptr CreateApplicationProcess(std::vector& out_control, - std::unique_ptr& out_loader, - Loader::ResultStatus& out_load_result, - Core::System& system, FileSys::VirtualFile file, - u64 program_id, u64 program_index) { - auto process = - CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); - if (!process) { - return nullptr; +std::optional CreateApplicationProcess(std::vector& out_control, std::unique_ptr& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index) { + if (auto process = CreateProcessImpl(out_loader, out_load_result, system, file, program_id, program_index); process) { + FileSys::NACP nacp; + if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { + out_control = nacp.GetRawBytes(); + } else { + out_control.resize(sizeof(FileSys::RawNACP)); + std::fill(out_control.begin(), out_control.end(), (u8) 0); + } + + auto& storage = system.GetContentProviderUnion(); + Service::Glue::ApplicationLaunchProperty launch{}; + launch.title_id = process->GetProgramId(); + + FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage}; + launch.version = pm.GetGameVersion().value_or(0); + + // TODO(DarkLordZach): When FSController/Game Card Support is added, if + // current_process_game_card use correct StorageId + launch.base_game_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program)); + launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); + + system.GetARPManager().Register(launch.title_id, launch, out_control); + return process; } - - FileSys::NACP nacp; - if (out_loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { - out_control = nacp.GetRawBytes(); - } else { - out_control.resize(sizeof(FileSys::RawNACP)); - std::fill(out_control.begin(), out_control.end(), (u8) 0); - } - - auto& storage = system.GetContentProviderUnion(); - Service::Glue::ApplicationLaunchProperty launch{}; - launch.title_id = process->GetProgramId(); - - FileSys::PatchManager pm{launch.title_id, system.GetFileSystemController(), storage}; - launch.version = pm.GetGameVersion().value_or(0); - - // TODO(DarkLordZach): When FSController/Game Card Support is added, if - // current_process_game_card use correct StorageId - launch.base_game_storage_id = GetStorageIdForFrontendSlot( - storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program)); - launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry( - FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); - - system.GetARPManager().Register(launch.title_id, launch, out_control); - - return process; + return std::nullopt; } } // namespace Service::AM diff --git a/src/core/hle/service/am/process_creation.h b/src/core/hle/service/am/process_creation.h index 8cfb9e0c9e..57d8b8f815 100644 --- a/src/core/hle/service/am/process_creation.h +++ b/src/core/hle/service/am/process_creation.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -24,12 +27,7 @@ class Process; namespace Service::AM { -std::unique_ptr CreateProcess(Core::System& system, u64 program_id, - u8 minimum_key_generation, u8 maximum_key_generation); -std::unique_ptr CreateApplicationProcess(std::vector& out_control, - std::unique_ptr& out_loader, - Loader::ResultStatus& out_load_result, - Core::System& system, FileSys::VirtualFile file, - u64 program_id, u64 program_index); +std::optional CreateProcess(Core::System& system, u64 program_id, u8 minimum_key_generation, u8 maximum_key_generation); +std::optional CreateApplicationProcess(std::vector& out_control, std::unique_ptr& out_loader, Loader::ResultStatus& out_load_result, Core::System& system, FileSys::VirtualFile file, u64 program_id, u64 program_index); } // namespace Service::AM diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp index 88a1724fc6..f357871706 100644 --- a/src/core/hle/service/am/service/application_accessor.cpp +++ b/src/core/hle/service/am/service/application_accessor.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -69,7 +69,7 @@ Result IApplicationAccessor::RequestExit() { std::scoped_lock lk{m_applet->lock}; if (m_applet->exit_locked) { - m_applet->lifecycle_manager.RequestExit(); + m_applet->lifecycle_manager.RequestExit(system.Kernel()); m_applet->UpdateSuspensionStateLocked(true); } else { m_applet->process->Terminate(); diff --git a/src/core/hle/service/am/service/application_creator.cpp b/src/core/hle/service/am/service/application_creator.cpp index 81620a5067..983ac700bc 100644 --- a/src/core/hle/service/am/service/application_creator.cpp +++ b/src/core/hle/service/am/service/application_creator.cpp @@ -21,8 +21,7 @@ namespace Service::AM { namespace { -Result CreateGuestApplication(SharedPointer* out_application_accessor, - Core::System& system, WindowSystem& window_system, u64 program_id) { +Result CreateGuestApplication(SharedPointer* out_application_accessor, Core::System& system, WindowSystem& window_system, u64 program_id) { FileSys::VirtualFile nca_raw{}; // Get the program NCA from storage. @@ -35,11 +34,10 @@ Result CreateGuestApplication(SharedPointer* out_applicati std::vector control; std::unique_ptr loader; Loader::ResultStatus result; - auto process = - CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0); - R_UNLESS(process != nullptr, ResultUnknown); + auto process = CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0); + R_UNLESS(process != std::nullopt, ResultUnknown); - const auto applet = std::make_shared(system, std::move(process), true); + const auto applet = std::make_shared(system, std::make_unique(*std::move(process)), true); applet->program_id = program_id; applet->applet_id = AppletId::Application; applet->type = AppletType::Application; @@ -47,8 +45,7 @@ Result CreateGuestApplication(SharedPointer* out_applicati window_system.TrackApplet(applet, true); - *out_application_accessor = - std::make_shared(system, applet, window_system); + *out_application_accessor = std::make_shared(system, applet, window_system); R_SUCCEED(); } @@ -90,12 +87,10 @@ Result IApplicationCreator::CreateSystemApplication( std::vector control; std::unique_ptr loader; + auto process = CreateProcess(system, application_id, 1, 22); + R_UNLESS(process != std::nullopt, ResultUnknown); - auto process = - CreateProcess(system, application_id, 1, 22); - R_UNLESS(process != nullptr, ResultUnknown); - - const auto applet = std::make_shared(system, std::move(process), true); + const auto applet = std::make_shared(system, std::make_unique(*std::move(process)), true); applet->program_id = application_id; applet->applet_id = AppletId::Starter; applet->type = AppletType::LibraryApplet; @@ -103,8 +98,7 @@ Result IApplicationCreator::CreateSystemApplication( m_window_system.TrackApplet(applet, true); - *out_application_accessor = - std::make_shared(system, applet, m_window_system); + *out_application_accessor = std::make_shared(system, applet, m_window_system); Core::LaunchTimestampCache::SaveLaunchTimestamp(application_id); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index 5b5e21b8e0..23f67dcf17 100644 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -99,7 +99,7 @@ Result ICommonStateGetter::GetEventHandle(OutCopyHandle Result ICommonStateGetter::ReceiveMessage(Out out_applet_message) { LOG_DEBUG(Service_AM, "called"); - if (!m_applet->lifecycle_manager.PopMessage(out_applet_message)) { + if (!m_applet->lifecycle_manager.PopMessage(system.Kernel(), out_applet_message)) { LOG_ERROR(Service_AM, "Tried to pop message but none was available!"); R_THROW(AM::ResultNoMessages); } @@ -123,21 +123,21 @@ Result ICommonStateGetter::RequestToAcquireSleepLock() { LOG_WARNING(Service_AM, "(STUBBED) called"); // Sleep lock is acquired immediately. - m_applet->sleep_lock_event.Signal(); + m_applet->sleep_lock_event.Signal(system.Kernel()); R_SUCCEED(); } Result ICommonStateGetter::ReleaseSleepLock() { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->sleep_lock_event.Clear(); + m_applet->sleep_lock_event.Clear(system.Kernel()); R_SUCCEED(); } Result ICommonStateGetter::ReleaseSleepLockTransiently() { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->sleep_lock_event.Clear(); + m_applet->sleep_lock_event.Clear(system.Kernel()); R_SUCCEED(); } @@ -281,25 +281,25 @@ Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType switch (type) { case SystemButtonType::HomeButtonShortPressing: if (!m_applet->home_button_short_pressed_blocked) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectShortPressingHomeButton); } break; case SystemButtonType::HomeButtonLongPressing: if (!m_applet->home_button_long_pressed_blocked) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectLongPressingHomeButton); } break; case SystemButtonType::CaptureButtonShortPressing: if (m_applet->handling_capture_button_short_pressed_message_enabled_for_applet) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectShortPressingCaptureButton); } break; case SystemButtonType::CaptureButtonLongPressing: if (m_applet->handling_capture_button_long_pressed_message_enabled_for_applet) { - m_applet->lifecycle_manager.PushUnorderedMessage( + m_applet->lifecycle_manager.PushUnorderedMessage(system.Kernel(), AppletMessage::DetectLongPressingCaptureButton); } break; diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp index ef91f69c23..366a26de0a 100644 --- a/src/core/hle/service/am/service/library_applet_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -123,7 +123,7 @@ Result ILibraryAppletAccessor::RequestExit() { LOG_DEBUG(Service_AM, "called"); { std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.RequestExit(); + m_applet->lifecycle_manager.RequestExit(system.Kernel()); } FrontendRequestExit(); R_SUCCEED(); @@ -157,7 +157,7 @@ Result ILibraryAppletAccessor::PushInData(SharedPointer storage) { } } - m_broker->GetInData().Push(storage); + m_broker->GetInData().Push(system.Kernel(), storage); R_SUCCEED(); } @@ -165,13 +165,13 @@ Result ILibraryAppletAccessor::PopOutData(Out> out_stora LOG_DEBUG(Service_AM, "called"); if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet) { - caller_applet->lifecycle_manager.GetSystemEvent().Signal(); + caller_applet->lifecycle_manager.GetSystemEvent().Signal(system.Kernel()); caller_applet->lifecycle_manager.RequestResumeNotification(); - caller_applet->lifecycle_manager.GetSystemEvent().Clear(); + caller_applet->lifecycle_manager.GetSystemEvent().Clear(system.Kernel()); caller_applet->lifecycle_manager.UpdateRequestedFocusState(); } - R_TRY(m_broker->GetOutData().Pop(out_storage.Get())); + R_TRY(m_broker->GetOutData().Pop(system.Kernel(), out_storage.Get())); if (m_applet->applet_id == AppletId::ProfileSelect && *out_storage) { auto impl = (*out_storage)->GetImpl(); @@ -186,14 +186,14 @@ Result ILibraryAppletAccessor::PopOutData(Out> out_stora Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer storage) { LOG_DEBUG(Service_AM, "called"); - m_broker->GetInteractiveInData().Push(storage); + m_broker->GetInteractiveInData().Push(system.Kernel(), storage); FrontendExecuteInteractive(); R_SUCCEED(); } Result ILibraryAppletAccessor::PopInteractiveOutData(Out> out_storage) { LOG_DEBUG(Service_AM, "called"); - R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get())); + R_RETURN(m_broker->GetInteractiveOutData().Pop(system.Kernel(), out_storage.Get())); } Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle out_event) { diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 3de5740237..92c9fd4ad9 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -122,26 +122,23 @@ std::shared_ptr CreateGuestApplet(Core::System& system, }; auto process = CreateProcess(system, program_id, Firmware1400, Firmware2200); - if (!process) { - // Couldn't initialize the guest process - return {}; + if (process) { + const auto applet = std::make_shared(system, std::make_unique(*std::move(process)), false); + applet->program_id = program_id; + applet->applet_id = applet_id; + applet->type = AppletType::LibraryApplet; + applet->library_applet_mode = mode; + applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; + + auto broker = std::make_shared(system); + applet->caller_applet = caller_applet; + applet->caller_applet_broker = broker; + caller_applet->child_applets.push_back(applet); + window_system.TrackApplet(applet, false); + return std::make_shared(system, broker, applet); } - - const auto applet = std::make_shared(system, std::move(process), false); - applet->program_id = program_id; - applet->applet_id = applet_id; - applet->type = AppletType::LibraryApplet; - applet->library_applet_mode = mode; - applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; - - auto broker = std::make_shared(system); - applet->caller_applet = caller_applet; - applet->caller_applet_broker = broker; - caller_applet->child_applets.push_back(applet); - - window_system.TrackApplet(applet, false); - - return std::make_shared(system, broker, applet); + // Couldn't initialize the guest process + return {}; } std::shared_ptr CreateFrontendApplet(Core::System& system, @@ -210,7 +207,7 @@ Result ILibraryAppletCreator::CreateLibraryApplet( } // Applet is created, can now be launched. - m_applet->library_applet_launchable_event.Signal(); + m_applet->library_applet_launchable_event.Signal(system.Kernel()); *out_library_applet_accessor = library_applet; R_SUCCEED(); } @@ -236,7 +233,7 @@ Result ILibraryAppletCreator::CreateLibraryAppletEx( } // Applet is created, can now be launched. - m_applet->library_applet_launchable_event.Signal(); + m_applet->library_applet_launchable_event.Signal(system.Kernel()); *out_library_applet_accessor = library_applet; R_SUCCEED(); } @@ -269,7 +266,7 @@ Result ILibraryAppletCreator::CreateTransferMemoryStorage( } *out_storage = std::make_shared( - system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(), + system, AM::CreateTransferMemoryStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(), transfer_memory_handle.Get(), is_writable, size)); R_SUCCEED(); } @@ -290,7 +287,7 @@ Result ILibraryAppletCreator::CreateHandleStorage( } *out_storage = std::make_shared( - system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(), + system, AM::CreateHandleStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(), transfer_memory_handle.Get(), size)); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp index 4a1d1f97d3..473a4bc955 100644 --- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -93,23 +93,23 @@ ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; Result ILibraryAppletSelfAccessor::PopInData(Out> out_storage) { LOG_INFO(Service_AM, "called"); - R_RETURN(m_broker->GetInData().Pop(out_storage)); + R_RETURN(m_broker->GetInData().Pop(system.Kernel(), out_storage)); } Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer storage) { LOG_INFO(Service_AM, "called"); - m_broker->GetOutData().Push(storage); + m_broker->GetOutData().Push(system.Kernel(), storage); R_SUCCEED(); } Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out> out_storage) { LOG_INFO(Service_AM, "called"); - R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage)); + R_RETURN(m_broker->GetInteractiveInData().Pop(system.Kernel(), out_storage)); } Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer storage) { LOG_INFO(Service_AM, "called"); - m_broker->GetInteractiveOutData().Push(storage); + m_broker->GetInteractiveOutData().Push(system.Kernel(), storage); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/lock_accessor.cpp b/src/core/hle/service/am/service/lock_accessor.cpp index 8e556fdd68..0341254449 100644 --- a/src/core/hle/service/am/service/lock_accessor.cpp +++ b/src/core/hle/service/am/service/lock_accessor.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -20,7 +23,7 @@ ILockAccessor::ILockAccessor(Core::System& system_) RegisterHandlers(functions); - m_event.Signal(); + m_event.Signal(system.Kernel()); } ILockAccessor::~ILockAccessor() = default; @@ -55,7 +58,7 @@ Result ILockAccessor::Unlock() { m_is_locked = false; } - m_event.Signal(); + m_event.Signal(system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 89e393bb97..4279483727 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -151,7 +151,7 @@ Result ISelfController::GetLibraryAppletLaunchableEvent( OutCopyHandle out_event) { LOG_WARNING(Service_AM, "(STUBBED) called"); - m_applet->library_applet_launchable_event.Signal(); + m_applet->library_applet_launchable_event.Signal(system.Kernel()); *out_event = m_applet->library_applet_launchable_event.GetHandle(); R_SUCCEED(); @@ -170,7 +170,7 @@ Result ISelfController::SetOperationModeChangedNotification(bool enabled) { LOG_INFO(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(enabled); + m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(system.Kernel(), enabled); R_SUCCEED(); } @@ -179,7 +179,7 @@ Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) { LOG_INFO(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(enabled); + m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(system.Kernel(), enabled); R_SUCCEED(); } @@ -188,7 +188,7 @@ Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool LOG_INFO(Service_AM, "called, notify={} background={} suspend={}", notify, background, suspend); std::scoped_lock lk{m_applet->lock}; - m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(notify); + m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(system.Kernel(), notify); m_applet->lifecycle_manager.SetFocusHandlingMode(suspend); m_applet->UpdateSuspensionStateLocked(true); diff --git a/src/core/hle/service/am/window_system.cpp b/src/core/hle/service/am/window_system.cpp index 5f20a98322..90115d73be 100644 --- a/src/core/hle/service/am/window_system.cpp +++ b/src/core/hle/service/am/window_system.cpp @@ -154,7 +154,7 @@ void WindowSystem::OnOperationModeChanged() { for (const auto& [aruid, applet] : m_applets) { std::scoped_lock lk2{applet->lock}; - applet->lifecycle_manager.OnOperationAndPerformanceModeChanged(); + applet->lifecycle_manager.OnOperationAndPerformanceModeChanged(m_system.Kernel()); } } @@ -163,22 +163,22 @@ void WindowSystem::OnExitRequested() { for (const auto& [aruid, applet] : m_applets) { std::scoped_lock lk2{applet->lock}; - applet->lifecycle_manager.RequestExit(); + applet->lifecycle_manager.RequestExit(m_system.Kernel()); } } void WindowSystem::SendButtonAppletMessageLocked(AppletMessage message) { if (m_home_menu) { std::scoped_lock lk_home{m_home_menu->lock}; - m_home_menu->lifecycle_manager.PushUnorderedMessage(message); + m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); } if (m_overlay_display) { std::scoped_lock lk_overlay{m_overlay_display->lock}; - m_overlay_display->lifecycle_manager.PushUnorderedMessage(message); + m_overlay_display->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); } if (m_application) { std::scoped_lock lk_application{m_application->lock}; - m_application->lifecycle_manager.PushUnorderedMessage(message); + m_application->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), message); } if (m_event_observer) { m_event_observer->RequestUpdate(); @@ -277,8 +277,7 @@ void WindowSystem::PruneTerminatedAppletsLocked() { // If we have a home menu, send it the application exited message. if (m_home_menu) { - m_home_menu->lifecycle_manager.PushUnorderedMessage( - AppletMessage::ApplicationExited); + m_home_menu->lifecycle_manager.PushUnorderedMessage(m_system.Kernel(), AppletMessage::ApplicationExited); } } diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp index eb64892ed8..e9f7e074a1 100644 --- a/src/core/hle/service/audio/audio_device.cpp +++ b/src/core/hle/service/audio/audio_device.cpp @@ -42,7 +42,7 @@ IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u }; RegisterHandlers(functions); - event->Signal(); + event->Signal(system.Kernel()); } IAudioDevice::~IAudioDevice() { @@ -128,7 +128,7 @@ Result IAudioDevice::GetActiveAudioDeviceNameAuto( Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle out_event) { LOG_DEBUG(Service_Audio, "(STUBBED) called"); - event->Signal(); + event->Signal(system.Kernel()); *out_event = &event->GetReadableEvent(); R_SUCCEED(); } diff --git a/src/core/hle/service/audio/audio_in.cpp b/src/core/hle/service/audio/audio_in.cpp index 416803acc3..6208c2d104 100644 --- a/src/core/hle/service/audio/audio_in.cpp +++ b/src/core/hle/service/audio/audio_in.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -37,7 +40,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, RegisterHandlers(functions); - process->Open(); + process->Open(system.Kernel()); if (impl->GetSystem() .Initialize(device_name, in_params, handle, applet_resource_user_id) @@ -49,7 +52,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, IAudioIn::~IAudioIn() { impl->Free(); service_context.CloseEvent(event); - process->Close(); + process->Close(system.Kernel()); } Result IAudioIn::GetAudioInState(Out out_state) { diff --git a/src/core/hle/service/audio/audio_out.cpp b/src/core/hle/service/audio/audio_out.cpp index 53009d5d74..996eeede58 100644 --- a/src/core/hle/service/audio/audio_out.cpp +++ b/src/core/hle/service/audio/audio_out.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -39,13 +42,13 @@ IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id, // clang-format on RegisterHandlers(functions); - process->Open(); + process->Open(system.Kernel()); } IAudioOut::~IAudioOut() { impl->Free(); service_context.CloseEvent(event); - process->Close(); + process->Close(system.Kernel()); } Result IAudioOut::GetAudioOutState(Out out_state) { diff --git a/src/core/hle/service/audio/audio_out_manager.cpp b/src/core/hle/service/audio/audio_out_manager.cpp index 0a8e1ec256..3b2087932c 100644 --- a/src/core/hle/service/audio/audio_out_manager.cpp +++ b/src/core/hle/service/audio/audio_out_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -14,7 +14,9 @@ namespace Service::Audio { using namespace AudioCore::AudioOut; IAudioOutManager::IAudioOutManager(Core::System& system_) - : ServiceFramework{system_, "audout:u"}, impl{std::make_unique(system_)} { + : ServiceFramework{system_, "audout:u"} + , impl(system_) +{ // clang-format off static const FunctionInfo functions[] = { {0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"}, diff --git a/src/core/hle/service/audio/audio_out_manager.h b/src/core/hle/service/audio/audio_out_manager.h index 791274d5e9..ec974aaba4 100644 --- a/src/core/hle/service/audio/audio_out_manager.h +++ b/src/core/hle/service/audio/audio_out_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -43,7 +43,7 @@ private: AudioCore::AudioOut::AudioOutParameter parameter, InCopyHandle process_handle, ClientAppletResourceUserId aruid); - std::unique_ptr impl; + std::optional impl; }; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp index 21cc742b69..49c6083109 100644 --- a/src/core/hle/service/audio/audio_renderer.cpp +++ b/src/core/hle/service/audio/audio_renderer.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -39,7 +39,7 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, // clang-format on RegisterHandlers(functions); - process_handle->Open(); + process_handle->Open(system_.Kernel()); impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, applet_resource_user_id, session_id); } @@ -47,7 +47,7 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, IAudioRenderer::~IAudioRenderer() { impl->Finalize(); service_context.CloseEvent(rendered_event); - process_handle->Close(); + process_handle->Close(system.Kernel()); } Result IAudioRenderer::GetSampleRate(Out out_sample_rate) { diff --git a/src/core/hle/service/audio/audio_renderer_manager.cpp b/src/core/hle/service/audio/audio_renderer_manager.cpp index 6a1345c074..972e930a89 100644 --- a/src/core/hle/service/audio/audio_renderer_manager.cpp +++ b/src/core/hle/service/audio/audio_renderer_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,7 +18,9 @@ namespace Service::Audio { using namespace AudioCore::Renderer; IAudioRendererManager::IAudioRendererManager(Core::System& system_) - : ServiceFramework{system_, "audren:u"}, impl{std::make_unique(system_)} { + : ServiceFramework{system_, "audren:u"} + , impl(system_) +{ // clang-format off static const FunctionInfo functions[] = { {0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"}, diff --git a/src/core/hle/service/audio/audio_renderer_manager.h b/src/core/hle/service/audio/audio_renderer_manager.h index 69eee664c3..fdce8b6ffa 100644 --- a/src/core/hle/service/audio/audio_renderer_manager.h +++ b/src/core/hle/service/audio/audio_renderer_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ private: Result GetAudioDeviceServiceWithRevisionInfo(Out> out_audio_device, u32 revision, ClientAppletResourceUserId aruid); - std::unique_ptr impl; + std::optional impl; u32 num_audio_devices{0}; }; diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp index 491416254c..3ef70aaacc 100644 --- a/src/core/hle/service/bcat/backend/backend.cpp +++ b/src/core/hle/service/bcat/backend/backend.cpp @@ -13,9 +13,9 @@ namespace Service::BCAT { ProgressServiceBackend::ProgressServiceBackend(Core::System& system, std::string_view event_name) - : service_context{system, "ProgressServiceBackend"} { - update_event = service_context.CreateEvent("ProgressServiceBackend:UpdateEvent:" + - std::string(event_name)); + : service_context{system, "ProgressServiceBackend"} +{ + update_event = service_context.CreateEvent("ProgressServiceBackend:UpdateEvent:" + std::string(event_name)); } ProgressServiceBackend::~ProgressServiceBackend() { @@ -30,103 +30,90 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() { return impl; } -void ProgressServiceBackend::SetTotalSize(u64 size) { +void ProgressServiceBackend::SetTotalSize(Kernel::KernelCore& kernel, u64 size) { impl.total_bytes = size; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::StartConnecting() { +void ProgressServiceBackend::StartConnecting(Kernel::KernelCore& kernel) { impl.status = DeliveryCacheProgressStatus::Connecting; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::StartProcessingDataList() { +void ProgressServiceBackend::StartProcessingDataList(Kernel::KernelCore& kernel) { impl.status = DeliveryCacheProgressStatus::ProcessingDataList; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::StartDownloadingFile(std::string_view dir_name, - std::string_view file_name, u64 file_size) { +void ProgressServiceBackend::StartDownloadingFile(Kernel::KernelCore& kernel, std::string_view dir_name, std::string_view file_name, u64 file_size) { impl.status = DeliveryCacheProgressStatus::Downloading; impl.current_downloaded_bytes = 0; impl.current_total_bytes = file_size; - std::memcpy(impl.current_directory.data(), dir_name.data(), - std::min(dir_name.size(), 0x31ull)); - std::memcpy(impl.current_file.data(), file_name.data(), - std::min(file_name.size(), 0x31ull)); - SignalUpdate(); + std::memcpy(impl.current_directory.data(), dir_name.data(), std::min(dir_name.size(), 0x31ull)); + std::memcpy(impl.current_file.data(), file_name.data(), std::min(file_name.size(), 0x31ull)); + SignalUpdate(kernel); } -void ProgressServiceBackend::UpdateFileProgress(u64 downloaded) { +void ProgressServiceBackend::UpdateFileProgress(Kernel::KernelCore& kernel, u64 downloaded) { impl.current_downloaded_bytes = downloaded; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::FinishDownloadingFile() { +void ProgressServiceBackend::FinishDownloadingFile(Kernel::KernelCore& kernel) { impl.total_downloaded_bytes += impl.current_total_bytes; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::CommitDirectory(std::string_view dir_name) { +void ProgressServiceBackend::CommitDirectory(Kernel::KernelCore& kernel, std::string_view dir_name) { impl.status = DeliveryCacheProgressStatus::Committing; impl.current_file.fill(0); impl.current_downloaded_bytes = 0; impl.current_total_bytes = 0; - std::memcpy(impl.current_directory.data(), dir_name.data(), - std::min(dir_name.size(), 0x31ull)); - SignalUpdate(); + std::memcpy(impl.current_directory.data(), dir_name.data(), std::min(dir_name.size(), 0x31ull)); + SignalUpdate(kernel); } -void ProgressServiceBackend::FinishDownload(Result result) { +void ProgressServiceBackend::FinishDownload(Kernel::KernelCore& kernel, Result result) { impl.total_downloaded_bytes = impl.total_bytes; impl.status = DeliveryCacheProgressStatus::Done; impl.result = result; - SignalUpdate(); + SignalUpdate(kernel); } -void ProgressServiceBackend::SignalUpdate() { - update_event->Signal(); +void ProgressServiceBackend::SignalUpdate(Kernel::KernelCore& kernel) { + update_event->Signal(kernel); } BcatBackend::BcatBackend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} - BcatBackend::~BcatBackend() = default; NullBcatBackend::NullBcatBackend(DirectoryGetter getter) : BcatBackend(std::move(getter)) {} - NullBcatBackend::~NullBcatBackend() = default; -bool NullBcatBackend::Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, - title.build_id); - - progress.FinishDownload(ResultSuccess); +bool NullBcatBackend::Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, title.build_id); + progress.FinishDownload(kernel, ResultSuccess); return true; } -bool NullBcatBackend::SynchronizeDirectory(TitleIDVersion title, std::string name, - ProgressServiceBackend& progress) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}, name={}", title.title_id, - title.build_id, name); - - progress.FinishDownload(ResultSuccess); +bool NullBcatBackend::SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}, name={}", title.title_id, title.build_id, name); + progress.FinishDownload(kernel, ResultSuccess); return true; } -bool NullBcatBackend::Clear(u64 title_id) { +bool NullBcatBackend::Clear(Kernel::KernelCore& kernel, u64 title_id) { LOG_DEBUG(Service_BCAT, "called, title_id={:016X}", title_id); return true; } -void NullBcatBackend::SetPassphrase(u64 title_id, const Passphrase& passphrase) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id, - Common::HexToString(passphrase)); +void NullBcatBackend::SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, passphrase={}", title_id, Common::HexToString(passphrase)); } -std::optional> NullBcatBackend::GetLaunchParameter(TitleIDVersion title) { - LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, - title.build_id); +std::optional> NullBcatBackend::GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) { + LOG_DEBUG(Service_BCAT, "called, title_id={:016X}, build_id={:016X}", title.title_id, title.build_id); return std::nullopt; } diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h index 3680f6c9c8..8419399a62 100644 --- a/src/core/hle/service/bcat/backend/backend.h +++ b/src/core/hle/service/bcat/backend/backend.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -34,26 +37,26 @@ public: ~ProgressServiceBackend(); // Sets the number of bytes total in the entire download. - void SetTotalSize(u64 size); + void SetTotalSize(Kernel::KernelCore& kernel, u64 size); // Notifies the application that the backend has started connecting to the server. - void StartConnecting(); + void StartConnecting(Kernel::KernelCore& kernel); // Notifies the application that the backend has begun accumulating and processing metadata. - void StartProcessingDataList(); + void StartProcessingDataList(Kernel::KernelCore& kernel); // Notifies the application that a file is starting to be downloaded. - void StartDownloadingFile(std::string_view dir_name, std::string_view file_name, u64 file_size); + void StartDownloadingFile(Kernel::KernelCore& kernel, std::string_view dir_name, std::string_view file_name, u64 file_size); // Updates the progress of the current file to the size passed. - void UpdateFileProgress(u64 downloaded); + void UpdateFileProgress(Kernel::KernelCore& kernel, u64 downloaded); // Notifies the application that the current file has completed download. - void FinishDownloadingFile(); + void FinishDownloadingFile(Kernel::KernelCore& kernel); // Notifies the application that all files in this directory have completed and are being // finalized. - void CommitDirectory(std::string_view dir_name); + void CommitDirectory(Kernel::KernelCore& kernel, std::string_view dir_name); // Notifies the application that the operation completed with result code result. - void FinishDownload(Result result); + void FinishDownload(Kernel::KernelCore& kernel, Result result); private: explicit ProgressServiceBackend(Core::System& system, std::string_view event_name); @@ -61,7 +64,7 @@ private: Kernel::KReadableEvent& GetEvent(); DeliveryCacheProgressImpl& GetImpl(); - void SignalUpdate(); + void SignalUpdate(Kernel::KernelCore& kernel); KernelHelpers::ServiceContext service_context; @@ -74,25 +77,19 @@ class BcatBackend { public: explicit BcatBackend(DirectoryGetter getter); virtual ~BcatBackend(); - // Called when the backend is needed to synchronize the data for the game with title ID and // version in title. A ProgressServiceBackend object is provided to alert the application of // status. - virtual bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) = 0; + virtual bool Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) = 0; // Very similar to Synchronize, but only for the directory provided. Backends should not alter // the data for any other directories. - virtual bool SynchronizeDirectory(TitleIDVersion title, std::string name, - ProgressServiceBackend& progress) = 0; - + virtual bool SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) = 0; // Removes all cached data associated with title id provided. - virtual bool Clear(u64 title_id) = 0; - + virtual bool Clear(Kernel::KernelCore& kernel, u64 title_id) = 0; // Sets the BCAT Passphrase to be used with the associated title ID. - virtual void SetPassphrase(u64 title_id, const Passphrase& passphrase) = 0; - + virtual void SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) = 0; // Gets the launch parameter used by AM associated with the title ID and version provided. - virtual std::optional> GetLaunchParameter(TitleIDVersion title) = 0; - + virtual std::optional> GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) = 0; protected: DirectoryGetter dir_getter; }; @@ -103,18 +100,13 @@ public: explicit NullBcatBackend(DirectoryGetter getter); ~NullBcatBackend() override; - bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) override; - bool SynchronizeDirectory(TitleIDVersion title, std::string name, - ProgressServiceBackend& progress) override; - - bool Clear(u64 title_id) override; - - void SetPassphrase(u64 title_id, const Passphrase& passphrase) override; - - std::optional> GetLaunchParameter(TitleIDVersion title) override; + bool Synchronize(Kernel::KernelCore& kernel, TitleIDVersion title, ProgressServiceBackend& progress) override; + bool SynchronizeDirectory(Kernel::KernelCore& kernel, TitleIDVersion title, std::string name, ProgressServiceBackend& progress) override; + bool Clear(Kernel::KernelCore& kernel, u64 title_id) override; + void SetPassphrase(Kernel::KernelCore& kernel, u64 title_id, const Passphrase& passphrase) override; + std::optional> GetLaunchParameter(Kernel::KernelCore& kernel, TitleIDVersion title) override; }; -std::unique_ptr CreateBackendFromSettings(Core::System& system, - DirectoryGetter getter); +std::unique_ptr CreateBackendFromSettings(Core::System& system, DirectoryGetter getter); } // namespace Service::BCAT diff --git a/src/core/hle/service/bcat/bcat_service.cpp b/src/core/hle/service/bcat/bcat_service.cpp index 849bf8d0d9..210fd77094 100644 --- a/src/core/hle/service/bcat/bcat_service.cpp +++ b/src/core/hle/service/bcat/bcat_service.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -70,7 +70,7 @@ Result IBcatService::RequestSyncDeliveryCache( LOG_DEBUG(Service_BCAT, "called"); auto& progress_backend{GetProgressBackend(SyncType::Normal)}; - backend.Synchronize({system.GetApplicationProcessProgramID(), + backend.Synchronize(system.Kernel(), {system.GetApplicationProcessProgramID(), GetCurrentBuildID(system.GetApplicationProcessBuildID())}, GetProgressBackend(SyncType::Normal)); @@ -86,7 +86,7 @@ Result IBcatService::RequestSyncDeliveryCacheWithDirectoryName( LOG_DEBUG(Service_BCAT, "called, name={}", name); auto& progress_backend{GetProgressBackend(SyncType::Directory)}; - backend.SynchronizeDirectory({system.GetApplicationProcessProgramID(), + backend.SynchronizeDirectory(system.Kernel(), {system.GetApplicationProcessProgramID(), GetCurrentBuildID(system.GetApplicationProcessBuildID())}, name, progress_backend); @@ -107,7 +107,7 @@ Result IBcatService::SetPassphrase(u64 application_id, std::memcpy(passphrase.data(), passphrase_buffer.data(), (std::min)(passphrase.size(), passphrase_buffer.size())); - backend.SetPassphrase(application_id, passphrase); + backend.SetPassphrase(system.Kernel(), application_id, passphrase); R_SUCCEED(); } @@ -120,7 +120,7 @@ Result IBcatService::ClearDeliveryCacheStorage(u64 application_id) { LOG_DEBUG(Service_BCAT, "called, title_id={:016X}", application_id); R_UNLESS(application_id != 0, ResultInvalidArgument); - R_UNLESS(backend.Clear(application_id), FileSys::ResultPermissionDenied); + R_UNLESS(backend.Clear(system.Kernel(), application_id), FileSys::ResultPermissionDenied); R_SUCCEED(); } diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index 79578956b1..6885a7be7d 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -183,7 +183,7 @@ private: auto& readable_event = completion_event->GetReadableEvent(); IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(readable_event.Signal()); + rb.Push(readable_event.Signal(system.Kernel())); rb.PushCopyObjects(readable_event); } diff --git a/src/core/hle/service/glue/time/alarm_worker.cpp b/src/core/hle/service/glue/time/alarm_worker.cpp index 3ff071f4a0..770dc62f5c 100644 --- a/src/core/hle/service/glue/time/alarm_worker.cpp +++ b/src/core/hle/service/glue/time/alarm_worker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -28,7 +31,7 @@ void AlarmWorker::Initialize(std::shared_ptr "Glue:AlarmWorker::AlarmTimer", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional { - m_timer_event->Signal(); + m_timer_event->Signal(m_system.Kernel()); return std::nullopt; }); @@ -57,7 +60,7 @@ void AlarmWorker::OnPowerStateChanged() { s64 closest_time{}; if (!GetClosestAlarmInfo(closest_alarm_info, closest_time)) { m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event); - m_timer_event->Clear(); + m_timer_event->Clear(m_system.Kernel()); return; } @@ -67,7 +70,7 @@ void AlarmWorker::OnPowerStateChanged() { auto next_time{closest_alarm_info.alert_time - closest_time}; m_system.CoreTiming().UnscheduleEvent(m_timer_timing_event); - m_timer_event->Clear(); + m_timer_event->Clear(m_system.Kernel()); m_system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds(next_time), m_timer_timing_event); diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index c358cfbf28..3543e1938b 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -89,7 +89,7 @@ Result TimeZoneService::SetDeviceLocationName( std::scoped_lock m{m_list_mutex}; for (auto& operation_event : m_list_nodes) { - operation_event.m_event->Signal(); + operation_event.m_event->Signal(m_system.Kernel()); } R_SUCCEED(); } diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index 1dab3e9dcb..5025efc717 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady "Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional { - m_timer_steady_clock->Signal(); + m_timer_steady_clock->Signal(m_system.Kernel()); return std::nullopt; }); @@ -38,19 +41,19 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady "Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional { - m_timer_file_system->Signal(); + m_timer_file_system->Signal(m_system.Kernel()); return std::nullopt; }); } TimeWorker::~TimeWorker() { - m_local_clock_event->Signal(); - m_network_clock_event->Signal(); - m_ephemeral_clock_event->Signal(); + m_local_clock_event->Signal(m_system.Kernel()); + m_network_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(); - m_event->Signal(); + m_event->Signal(m_system.Kernel()); m_thread.join(); m_ctx.CloseEvent(m_event); @@ -167,19 +170,19 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { return; case EventType::PowerStateChange: - m_alarm_worker.GetEvent().Clear(); + 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: - m_alarm_worker.GetTimerEvent().Clear(); + m_alarm_worker.GetTimerEvent().Clear(m_system.Kernel()); m_time_m->CheckAndSignalAlarms(); break; case EventType::UpdateLocalSystemClock: { - m_local_clock_event->Clear(); + m_local_clock_event->Clear(m_system.Kernel()); Service::PSC::Time::SystemClockContext context{}; R_ASSERT(m_local_clock->GetSystemClockContext(&context)); @@ -190,7 +193,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateNetworkSystemClock: { - m_network_clock_event->Clear(); + m_network_clock_event->Clear(m_system.Kernel()); Service::PSC::Time::SystemClockContext context{}; R_ASSERT(m_network_clock->GetSystemClockContext(&context)); @@ -218,7 +221,7 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateEphemeralSystemClock: { - m_ephemeral_clock_event->Clear(); + m_ephemeral_clock_event->Clear(m_system.Kernel()); Service::PSC::Time::SystemClockContext context{}; auto res = m_ephemeral_clock->GetSystemClockContext(&context); @@ -247,20 +250,20 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) { } case EventType::UpdateSteadyClock: - m_timer_steady_clock->Clear(); + 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_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_standard_user_auto_correct_clock_event->Clear(m_system.Kernel()); bool automatic_correction{}; R_ASSERT(m_time_sm->IsStandardUserSystemClockAutomaticCorrectionEnabled( diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index f29cf4e3d7..cd69829472 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp @@ -650,8 +650,7 @@ Result IHidServer::SetSupportedNpadStyleSet(Core::HID::NpadStyleSet supported_st LOG_DEBUG(Service_HID, "called, supported_style_set={}, applet_resource_user_id={}", supported_style_set, aruid.pid); - R_TRY( - GetResourceManager()->GetNpad()->SetSupportedNpadStyleSet(aruid.pid, supported_style_set)); + R_TRY(GetResourceManager()->GetNpad()->SetSupportedNpadStyleSet(system.Kernel(), aruid.pid, supported_style_set)); Core::HID::NpadStyleTag style_tag{supported_style_set}; const auto revision = GetResourceManager()->GetNpad()->GetRevision(aruid.pid); @@ -667,7 +666,7 @@ Result IHidServer::GetSupportedNpadStyleSet(Out out_sup ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->GetSupportedNpadStyleSet(aruid.pid, + R_RETURN(GetResourceManager()->GetNpad()->GetSupportedNpadStyleSet(system.Kernel(), aruid.pid, *out_supported_style_set)); } @@ -677,7 +676,7 @@ Result IHidServer::SetSupportedNpadIdType( LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); R_RETURN( - GetResourceManager()->GetNpad()->SetSupportedNpadIdType(aruid.pid, supported_npad_list)); + GetResourceManager()->GetNpad()->SetSupportedNpadIdType(system.Kernel(), aruid.pid, supported_npad_list)); } Result IHidServer::ActivateNpad(ClientAppletResourceUserId aruid) { @@ -702,14 +701,13 @@ Result IHidServer::AcquireNpadStyleSetUpdateEventHandle( LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", npad_id, aruid.pid, unknown); - R_RETURN(GetResourceManager()->GetNpad()->AcquireNpadStyleSetUpdateEventHandle( - aruid.pid, out_event, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->AcquireNpadStyleSetUpdateEventHandle(system.Kernel(), aruid.pid, out_event, npad_id)); } Result IHidServer::DisconnectNpad(Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); - R_RETURN(GetResourceManager()->GetNpad()->DisconnectNpad(aruid.pid, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->DisconnectNpad(system.Kernel(), aruid.pid, npad_id)); } Result IHidServer::GetPlayerLedPattern(Out out_led_pattern, @@ -779,7 +777,7 @@ Result IHidServer::SetNpadJoyAssignmentModeSingleByDefault(Core::HID::NpadIdType LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode( + GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, NpadJoyDeviceType::Left, NpadJoyAssignmentMode::Single); R_SUCCEED(); } @@ -791,7 +789,7 @@ Result IHidServer::SetNpadJoyAssignmentModeSingle(Core::HID::NpadIdType npad_id, npad_id, aruid.pid, npad_joy_device_type); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode( + GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); R_SUCCEED(); } @@ -801,7 +799,7 @@ Result IHidServer::SetNpadJoyAssignmentModeDual(Core::HID::NpadIdType npad_id, LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); Core::HID::NpadIdType new_npad_id{}; - GetResourceManager()->GetNpad()->SetNpadMode(aruid.pid, new_npad_id, npad_id, {}, + GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, new_npad_id, npad_id, {}, NpadJoyAssignmentMode::Dual); R_SUCCEED(); } @@ -813,7 +811,7 @@ Result IHidServer::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, npad_id_1, npad_id_2, aruid.pid); R_RETURN( - GetResourceManager()->GetNpad()->MergeSingleJoyAsDualJoy(aruid.pid, npad_id_1, npad_id_2)); + GetResourceManager()->GetNpad()->MergeSingleJoyAsDualJoy(system.Kernel(), aruid.pid, npad_id_1, npad_id_2)); } Result IHidServer::StartLrAssignmentMode(ClientAppletResourceUserId aruid) { @@ -840,67 +838,40 @@ Result IHidServer::SetNpadHandheldActivationMode(ClientAppletResourceUserId arui ASSERT_MSG(false, "Activation mode should be always None, Single or Dual"); R_SUCCEED(); } - - R_RETURN( - GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(aruid.pid, activation_mode)); + R_RETURN(GetResourceManager()->GetNpad()->SetNpadHandheldActivationMode(system.Kernel(), aruid.pid, activation_mode)); } Result IHidServer::GetNpadHandheldActivationMode( Out out_activation_mode, ClientAppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", aruid.pid); - - R_RETURN(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode(aruid.pid, - *out_activation_mode)); + R_RETURN(GetResourceManager()->GetNpad()->GetNpadHandheldActivationMode(system.Kernel(), aruid.pid, *out_activation_mode)); } -Result IHidServer::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2, - ClientAppletResourceUserId aruid) { - LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", - npad_id_1, npad_id_2, aruid.pid); - - R_RETURN(GetResourceManager()->GetNpad()->SwapNpadAssignment(aruid.pid, npad_id_1, npad_id_2)) +Result IHidServer::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2, ClientAppletResourceUserId aruid) { + LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", npad_id_1, npad_id_2, aruid.pid); + R_RETURN(GetResourceManager()->GetNpad()->SwapNpadAssignment(system.Kernel(), aruid.pid, npad_id_1, npad_id_2)) } -Result IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(Out out_is_enabled, - Core::HID::NpadIdType npad_id, - ClientAppletResourceUserId aruid) { +Result IHidServer::IsUnintendedHomeButtonInputProtectionEnabled(Out out_is_enabled, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, aruid.pid); - R_UNLESS(IsNpadIdValid(npad_id), ResultInvalidNpadId); - R_RETURN(GetResourceManager()->GetNpad()->IsUnintendedHomeButtonInputProtectionEnabled( - *out_is_enabled, aruid.pid, npad_id)); + R_RETURN(GetResourceManager()->GetNpad()->IsUnintendedHomeButtonInputProtectionEnabled(*out_is_enabled, aruid.pid, npad_id)); } -Result IHidServer::EnableUnintendedHomeButtonInputProtection(bool is_enabled, - Core::HID::NpadIdType npad_id, - ClientAppletResourceUserId aruid) { - LOG_DEBUG(Service_HID, "called, is_enabled={}, npad_id={}, applet_resource_user_id={}", - is_enabled, npad_id, aruid.pid); - +Result IHidServer::EnableUnintendedHomeButtonInputProtection(bool is_enabled, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid) { + LOG_DEBUG(Service_HID, "called, is_enabled={}, npad_id={}, applet_resource_user_id={}",is_enabled, npad_id, aruid.pid); R_UNLESS(IsNpadIdValid(npad_id), ResultInvalidNpadId); - R_RETURN(GetResourceManager()->GetNpad()->EnableUnintendedHomeButtonInputProtection( - aruid.pid, npad_id, is_enabled)); + R_RETURN(GetResourceManager()->GetNpad()->EnableUnintendedHomeButtonInputProtection(aruid.pid, npad_id, is_enabled)); } -Result IHidServer::SetNpadJoyAssignmentModeSingleWithDestination( - Out out_is_reassigned, Out out_new_npad_id, - Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid, - NpadJoyDeviceType npad_joy_device_type) { - LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", - npad_id, aruid.pid, npad_joy_device_type); - - *out_is_reassigned = GetResourceManager()->GetNpad()->SetNpadMode( - aruid.pid, *out_new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); - +Result IHidServer::SetNpadJoyAssignmentModeSingleWithDestination(Out out_is_reassigned, Out out_new_npad_id, Core::HID::NpadIdType npad_id, ClientAppletResourceUserId aruid, NpadJoyDeviceType npad_joy_device_type) { + LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", npad_id, aruid.pid, npad_joy_device_type); + *out_is_reassigned = GetResourceManager()->GetNpad()->SetNpadMode(system.Kernel(), aruid.pid, *out_new_npad_id, npad_id, npad_joy_device_type, NpadJoyAssignmentMode::Single); R_SUCCEED(); } -Result IHidServer::SetNpadAnalogStickUseCenterClamp(bool use_center_clamp, - ClientAppletResourceUserId aruid) { - LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}", - use_center_clamp, aruid.pid); - +Result IHidServer::SetNpadAnalogStickUseCenterClamp(bool use_center_clamp, ClientAppletResourceUserId aruid) { + LOG_INFO(Service_HID, "called, use_center_clamp={}, applet_resource_user_id={}", use_center_clamp, aruid.pid); GetResourceManager()->GetNpad()->SetNpadAnalogStickUseCenterClamp(aruid.pid, use_center_clamp); R_SUCCEED(); } diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 1de5dd6f28..dbc8310c08 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -281,7 +281,7 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(applet_resource_user_id); + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicy(system.Kernel(), applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -328,7 +328,7 @@ void IHidSystemServer::ApplyNpadSystemCommonPolicyFull(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(applet_resource_user_id); + GetResourceManager()->GetNpad()->ApplyNpadSystemCommonPolicyFull(system.Kernel(), applet_resource_user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -358,9 +358,8 @@ void IHidSystemServer::GetMaskedSupportedNpadStyleSet(HLERequestContext& ctx) { LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); Core::HID::NpadStyleSet supported_styleset{}; - const auto& npad = GetResourceManager()->GetNpad(); - const Result result = - npad->GetMaskedSupportedNpadStyleSet(applet_resource_user_id, supported_styleset); + const auto npad = GetResourceManager()->GetNpad(); + const Result result = npad->GetMaskedSupportedNpadStyleSet(system.Kernel(), applet_resource_user_id, supported_styleset); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(result); @@ -373,9 +372,8 @@ void IHidSystemServer::SetSupportedNpadStyleSetAll(HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); - const auto& npad = GetResourceManager()->GetNpad(); - const auto result = - npad->SetSupportedNpadStyleSet(applet_resource_user_id, Core::HID::NpadStyleSet::All); + const auto npad = GetResourceManager()->GetNpad(); + const auto result = npad->SetSupportedNpadStyleSet(system.Kernel(), applet_resource_user_id, Core::HID::NpadStyleSet::All); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result); diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index 8db8f8538c..ce7591656a 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp @@ -275,17 +275,17 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer() { for (auto& object : outgoing_copy_objects) { Handle handle{}; if (object) { - R_TRY(handle_table.Add(&handle, object)); + R_TRY(handle_table.Add(kernel, &handle, object)); } cmd_buf[current_offset++] = handle; } for (auto& object : outgoing_move_objects) { Handle handle{}; if (object) { - R_TRY(handle_table.Add(&handle, object)); + R_TRY(handle_table.Add(kernel, &handle, object)); // Close our reference to the object, as it is being moved to the caller. - object->Close(); + object->Close(kernel); } cmd_buf[current_offset++] = handle; } @@ -503,11 +503,10 @@ bool HLERequestContext::CanWriteBuffer(std::size_t buffer_index) const { } void HLERequestContext::AddMoveInterface(SessionRequestHandlerPtr s) { - ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve( - Kernel::LimitableResource::SessionCountMax, 1)); + ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1)); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(nullptr, 0); + session->Initialize(kernel, nullptr, 0); Kernel::KSession::Register(kernel, session); auto& server = manager.lock()->GetServerManager(); diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index ec8185a09e..eeb5bf3547 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h @@ -373,11 +373,10 @@ public: template Kernel::KScopedAutoObject GetObjectFromHandle(u32 handle) { - auto obj = client_handle_table->GetObjectForIpc(handle, thread); - if (obj.IsNotNull()) { - return obj->DynamicCast(); - } - return nullptr; + auto obj = client_handle_table->GetObjectForIpc(kernel, handle, thread); + if (obj.IsNotNull()) + return {kernel, obj->DynamicCast()}; + return {kernel, nullptr}; } [[nodiscard]] std::shared_ptr GetManager() const { diff --git a/src/core/hle/service/ipc_helpers.h b/src/core/hle/service/ipc_helpers.h index 8aee17db8d..c37b0c2e05 100644 --- a/src/core/hle/service/ipc_helpers.h +++ b/src/core/hle/service/ipc_helpers.h @@ -151,11 +151,10 @@ public: if (manager->IsDomain()) { context->AddDomainObject(std::move(iface)); } else { - ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve( - Kernel::LimitableResource::SessionCountMax, 1)); + ASSERT(Kernel::GetCurrentProcess(kernel).GetResourceLimit()->Reserve(kernel, Kernel::LimitableResource::SessionCountMax, 1)); auto* session = Kernel::KSession::Create(kernel); - session->Initialize(nullptr, 0); + session->Initialize(kernel, nullptr, 0); Kernel::KSession::Register(kernel, session); auto next_manager = std::make_shared( diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 1179e8b61d..626b643c00 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -30,12 +30,13 @@ static_assert(sizeof(Struct32) == 32, "Struct32 has wrong size"); class IJitEnvironment final : public ServiceFramework { public: - explicit IJitEnvironment(Core::System& system_, - Kernel::KScopedAutoObject process_, - CodeMemory&& user_rx_, CodeMemory&& user_ro_) - : ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)}, - user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)}, - context{system_.ApplicationMemory()} { + explicit IJitEnvironment(Core::System& system_, Kernel::KProcess* process_, CodeMemory&& user_rx_, CodeMemory&& user_ro_) + : ServiceFramework{system_, "IJitEnvironment"} + , process{kernel, process_} + , user_rx{std::move(user_rx_)} + , user_ro{std::move(user_ro_)} + , context{system_.ApplicationMemory()} + { // clang-format off static const FunctionInfo functions[] = { @@ -58,6 +59,11 @@ public: configuration.sys_ro_memory = configuration.user_ro_memory; } + ~IJitEnvironment() { + user_rx.Finalize(system.Kernel()); + user_ro.Finalize(system.Kernel()); + } + Result GenerateCode(Out out_return_value, Out out_range0, Out out_range1, OutBuffer out_buffer, u32 data_size, u64 command, CodeRange range0, CodeRange range1, @@ -281,14 +287,9 @@ private: } CodeMemory rx, ro; - - R_TRY(rx.Initialize(*process, *rx_mem, rx_size, Kernel::Svc::MemoryPermission::ReadExecute, - generate_random)); - R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, - generate_random)); - - *out_jit_environment = - std::make_shared(system, process.Get(), std::move(rx), std::move(ro)); + R_TRY(rx.Initialize(system.Kernel(), *process, *rx_mem, rx_size, Kernel::Svc::MemoryPermission::ReadExecute, generate_random)); + R_TRY(ro.Initialize(system.Kernel(), *process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, generate_random)); + *out_jit_environment = std::make_shared(system, process.Get(), std::move(rx), std::move(ro)); R_SUCCEED(); } diff --git a/src/core/hle/service/jit/jit_code_memory.cpp b/src/core/hle/service/jit/jit_code_memory.cpp index 2b480488a8..3218512af4 100644 --- a/src/core/hle/service/jit/jit_code_memory.cpp +++ b/src/core/hle/service/jit/jit_code_memory.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -5,12 +8,9 @@ namespace Service::JIT { -Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, - size_t size, Kernel::Svc::MemoryPermission perm, - std::mt19937_64& generate_random) { +Result CodeMemory::Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random) { auto& page_table = process.GetPageTable(); - const u64 alias_code_start = - GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; + const u64 alias_code_start = GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; const u64 alias_code_size = page_table.GetAliasCodeRegionSize() / Kernel::PageSize; // NOTE: This will retry indefinitely until mapping the code memory succeeds. @@ -20,7 +20,7 @@ Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& co (alias_code_start + (generate_random() % alias_code_size)) * Kernel::PageSize; // Try to map the address - R_TRY_CATCH(code_memory.MapToOwner(mapped_address, size, perm)) { + R_TRY_CATCH(code_memory.MapToOwner(kernel, mapped_address, size, perm)) { R_CATCH(Kernel::ResultInvalidMemoryRegion) { // If we could not map here, retry. continue; @@ -35,17 +35,17 @@ Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& co m_perm = perm; // Open a new reference to the code memory. - m_code_memory->Open(); + m_code_memory->Open(kernel); // We succeeded. R_SUCCEED(); } } -void CodeMemory::Finalize() { +void CodeMemory::Finalize(Kernel::KernelCore& kernel) { if (m_code_memory) { - R_ASSERT(m_code_memory->UnmapFromOwner(m_address, m_size)); - m_code_memory->Close(); + R_ASSERT(m_code_memory->UnmapFromOwner(kernel, m_address, m_size)); + m_code_memory->Close(kernel); } m_code_memory = nullptr; diff --git a/src/core/hle/service/jit/jit_code_memory.h b/src/core/hle/service/jit/jit_code_memory.h index 6376d4c4eb..d741520aeb 100644 --- a/src/core/hle/service/jit/jit_code_memory.h +++ b/src/core/hle/service/jit/jit_code_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,29 +10,16 @@ #include "core/hle/kernel/k_code_memory.h" +namespace Kernel { +class KernelCore; +} + namespace Service::JIT { class CodeMemory { public: - YUZU_NON_COPYABLE(CodeMemory); - - explicit CodeMemory() = default; - - CodeMemory(CodeMemory&& rhs) { - std::swap(m_code_memory, rhs.m_code_memory); - std::swap(m_size, rhs.m_size); - std::swap(m_address, rhs.m_address); - std::swap(m_perm, rhs.m_perm); - } - - ~CodeMemory() { - this->Finalize(); - } - -public: - Result Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, - Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); - void Finalize(); + Result Initialize(Kernel::KernelCore& kernel, Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); + void Finalize(Kernel::KernelCore& kernel); size_t GetSize() const { return m_size; @@ -39,7 +29,6 @@ public: return m_address; } -private: Kernel::KCodeMemory* m_code_memory{}; size_t m_size{}; u64 m_address{}; diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index f080f7ffa2..f7a5cb7049 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,15 +17,15 @@ namespace Service::KernelHelpers { ServiceContext::ServiceContext(Core::System& system_, std::string name_) - : kernel(system_.Kernel()) { + : kernel(system_.Kernel()) +{ if (process = Kernel::GetCurrentProcessPointer(kernel); process != nullptr) { return; } // Create the process. process = Kernel::KProcess::Create(kernel); - ASSERT(R_SUCCEEDED(process->Initialize(Kernel::Svc::CreateProcessParameter{}, - kernel.GetSystemResourceLimit(), false))); + ASSERT(R_SUCCEEDED(process->Initialize(kernel, Kernel::Svc::CreateProcessParameter{}, kernel.GetSystemResourceLimit(), false))); // Register the process. Kernel::KProcess::Register(kernel, process); @@ -31,14 +34,14 @@ ServiceContext::ServiceContext(Core::System& system_, std::string name_) ServiceContext::~ServiceContext() { if (process_created) { - process->Close(); + process->Close(kernel); process = nullptr; } } Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { // Reserve a new event from the process resource limit - Kernel::KScopedResourceReservation event_reservation(process, + Kernel::KScopedResourceReservation event_reservation(kernel, process, Kernel::LimitableResource::EventCountMax); if (!event_reservation.Succeeded()) { LOG_CRITICAL(Service, "Resource limit reached!"); @@ -53,7 +56,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } // Initialize the event. - event->Initialize(process); + event->Initialize(kernel, process); // Commit the thread reservation. event_reservation.Commit(); @@ -65,11 +68,10 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } void ServiceContext::CloseEvent(Kernel::KEvent* event) { - if (!event) { - return; + if (event) { + event->GetReadableEvent().Close(kernel); + event->Close(kernel); } - event->GetReadableEvent().Close(); - event->Close(); } } // namespace Service::KernelHelpers diff --git a/src/core/hle/service/kernel_helpers.h b/src/core/hle/service/kernel_helpers.h index eca9aefb52..4e21c8857f 100644 --- a/src/core/hle/service/kernel_helpers.h +++ b/src/core/hle/service/kernel_helpers.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,7 +29,6 @@ public: void CloseEvent(Kernel::KEvent* event); -private: Kernel::KernelCore& kernel; Kernel::KProcess* process{}; bool process_created{false}; diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp index 1e984a9782..572aea6314 100644 --- a/src/core/hle/service/ldn/user_local_communication_service.cpp +++ b/src/core/hle/service/ldn/user_local_communication_service.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -322,7 +322,7 @@ void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacke } void IUserLocalCommunicationService::OnEventFired() { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } // namespace Service::LDN diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index faa2b1f584..2876c6f739 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -71,13 +71,13 @@ NfcDevice::~NfcDevice() { void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) { if (type == Core::HID::ControllerTriggerType::Connected) { Initialize(); - availability_change_event->Signal(); + availability_change_event->Signal(system.Kernel()); return; } if (type == Core::HID::ControllerTriggerType::Disconnected) { Finalize(); - availability_change_event->Signal(); + availability_change_event->Signal(system.Kernel()); return; } @@ -138,8 +138,8 @@ bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSeria }; device_state = DeviceState::TagFound; - deactivate_event->GetReadableEvent().Clear(); - activate_event->Signal(); + deactivate_event->GetReadableEvent().Clear(system.Kernel()); + activate_event->Signal(system.Kernel()); return true; } @@ -192,8 +192,8 @@ void NfcDevice::CloseNfcTag() { device_state = DeviceState::TagRemoved; encrypted_tag_data = {}; tag_data = {}; - activate_event->GetReadableEvent().Clear(); - deactivate_event->Signal(); + activate_event->GetReadableEvent().Clear(system.Kernel()); + deactivate_event->Signal(system.Kernel()); } Kernel::KReadableEvent& NfcDevice::GetActivateEvent() const { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 7bd06e2e0f..87e806d86b 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -275,7 +275,7 @@ private: } state.store(State::Processing); - evt_processing->Signal(); + evt_processing->Signal(system.Kernel()); worker = std::thread([this]() { using namespace std::chrono_literals; @@ -321,7 +321,7 @@ private: void Finish(Result rc) { worker_result.store(rc); state.store(State::Finished); - evt_scan_complete->Signal(); + evt_scan_complete->Signal(system.Kernel()); } KernelHelpers::ServiceContext svc_ctx; @@ -486,7 +486,7 @@ private: void UpdateState(RequestState new_state) { LOG_DEBUG(Service_NIFM, "(STUBBED) called"); state = new_state; - event1->Signal(); + event1->Signal(system.Kernel()); } KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 4f465c5da7..5f85302713 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -429,7 +429,7 @@ private: void StartTask(HLERequestContext& ctx) { // No need to connect to the internet, just finish the task straight away. LOG_DEBUG(Service_NIM, "called"); - finished_event->Signal(); + finished_event->Signal(system.Kernel()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -451,7 +451,7 @@ private: void Cancel(HLERequestContext& ctx) { LOG_DEBUG(Service_NIM, "called"); - finished_event->Clear(); + finished_event->Clear(system.Kernel()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp index 5490c09d03..485eac0afa 100644 --- a/src/core/hle/service/ns/application_manager_interface.cpp +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -610,7 +610,7 @@ Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent( OutCopyHandle out_event) { LOG_WARNING(Service_NS, "(STUBBED) called"); - record_update_system_event.Signal(); + record_update_system_event.Signal(system.Kernel()); *out_event = record_update_system_event.GetHandle(); R_SUCCEED(); @@ -820,14 +820,14 @@ Result IApplicationManagerInterface::RequestDownloadApplicationControlDataInBack LOG_INFO(Service_NS, "called, control_source={} app={:016X}", control_source, application_id); - unknown_event.Signal(); + unknown_event.Signal(system.Kernel()); R_SUCCEED(); } Result IApplicationManagerInterface::Unknown4022( OutCopyHandle out_event) { LOG_WARNING(Service_NS, "(STUBBED) called"); - unknown_event.Signal(); + unknown_event.Signal(system.Kernel()); *out_event = unknown_event.GetHandle(); R_SUCCEED(); } diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp index 03f0a17865..f12d9b03d2 100644 --- a/src/core/hle/service/ns/read_only_application_control_data_interface.cpp +++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp @@ -87,7 +87,7 @@ public: RegisterHandlers(functions); completion_event = service_context.CreateEvent("IAsyncValue:Completion"); - completion_event->GetReadableEvent().Signal(); + completion_event->GetReadableEvent().Signal(system.Kernel()); } ~IAsyncValueForListApplicationTitle() override { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 3bfef0c29c..1238a21f85 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -138,8 +138,7 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { static_cast((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)}; vm.big_page_allocator.emplace(start_big_pages, end_big_pages); - gmmu = std::make_shared(system, max_big_page_bits, vm.va_range_split, - vm.big_page_size_bits, VM::PAGE_SIZE_BITS); + gmmu = std::make_unique(system, max_big_page_bits, vm.va_range_split, vm.big_page_size_bits, VM::PAGE_SIZE_BITS); system.GPU().InitAddressSpace(*gmmu); vm.initialised = true; @@ -416,7 +415,7 @@ NvResult nvhost_as_gpu::BindChannel(IoctlBindChannel& params) { LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); auto gpu_channel_device = module.GetDevice(params.fd); - gpu_channel_device->channel_state->memory_manager = gmmu; + gpu_channel_device->channel_state->memory_manager = gmmu.get(); return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 44892ee368..b8ae57e1b4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -219,7 +219,7 @@ private: bool initialised{}; } vm; - std::shared_ptr gmmu; + std::unique_ptr gmmu; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index b2580f2bb9..6ef32b890f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -203,7 +203,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(IocCtrlEventWaitParams& params, bool is_a auto& event_ = events[slot]; if (event_.status.exchange(EventState::Signalling, std::memory_order_acq_rel) == EventState::Waiting) { - event_.kevent->Signal(); + event_.kevent->Signal(system.Kernel()); } event_.status.store(EventState::Signalled, std::memory_order_release); }); @@ -292,7 +292,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(IocCtrlEventClearParams& params) { } event.fails++; event.status.store(EventState::Cancelled, std::memory_order_release); - event.kevent->Clear(); + event.kevent->Clear(system.Kernel()); return NvResult::Success; } diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 5bd53fb99e..c3eb2796e3 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -111,7 +111,7 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) { core->override_max_buffer_count = buffer_count; core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); listener = core->consumer_listener; } @@ -576,7 +576,7 @@ void BufferQueueProducer::CancelBuffer(s32 slot, const Fence& fence) { slots[slot].fence = fence; core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); } Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { @@ -714,7 +714,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { core->connected_producer_listener = nullptr; core->connected_api = NativeWindowApi::NoConnectedApi; core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); listener = core->consumer_listener; } else { LOG_ERROR(Service_Nvnflinger, @@ -764,7 +764,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, } core->SignalDequeueCondition(); - buffer_wait_event->Signal(); + buffer_wait_event->Signal(service_context.kernel); return Status::NoError; } diff --git a/src/core/hle/service/olsc/native_handle_holder.cpp b/src/core/hle/service/olsc/native_handle_holder.cpp index d381714bc3..1e50195539 100644 --- a/src/core/hle/service/olsc/native_handle_holder.cpp +++ b/src/core/hle/service/olsc/native_handle_holder.cpp @@ -32,7 +32,7 @@ INativeHandleHolder::~INativeHandleHolder() { Result INativeHandleHolder::GetNativeHandle(OutCopyHandle out_event) { LOG_WARNING(Service_OLSC, "(STUBBED) called"); if (event) { - event->Signal(); + event->Signal(system.Kernel()); *out_event = std::addressof(event->GetReadableEvent()); } else { *out_event = nullptr; diff --git a/src/core/hle/service/os/event.cpp b/src/core/hle/service/os/event.cpp index ec52c17fd8..8808c5b4f0 100644 --- a/src/core/hle/service/os/event.cpp +++ b/src/core/hle/service/os/event.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,25 +10,27 @@ namespace Service { -Event::Event(KernelHelpers::ServiceContext& ctx) { +Event::Event(KernelHelpers::ServiceContext& ctx_) + : ctx{ctx_} +{ m_event = ctx.CreateEvent("Event"); } Event::~Event() { - m_event->GetReadableEvent().Close(); - m_event->Close(); + m_event->GetReadableEvent().Close(ctx.kernel); + m_event->Close(ctx.kernel); } -void Event::Signal() { - m_event->Signal(); +void Event::Signal(Kernel::KernelCore& kernel) noexcept { + m_event->Signal(kernel); } -void Event::Clear() { - m_event->Clear(); +void Event::Clear(Kernel::KernelCore& kernel) noexcept { + m_event->Clear(kernel); } -Kernel::KReadableEvent* Event::GetHandle() { - return &m_event->GetReadableEvent(); +Kernel::KReadableEvent* Event::GetHandle() noexcept { + return std::addressof(m_event->GetReadableEvent()); } } // namespace Service diff --git a/src/core/hle/service/os/event.h b/src/core/hle/service/os/event.h index cdbc4635a6..bc23598b58 100644 --- a/src/core/hle/service/os/event.h +++ b/src/core/hle/service/os/event.h @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once namespace Kernel { +class KernelCore; class KEvent; class KReadableEvent; } // namespace Kernel @@ -19,12 +23,12 @@ public: explicit Event(KernelHelpers::ServiceContext& ctx); ~Event(); - void Signal(); - void Clear(); - - Kernel::KReadableEvent* GetHandle(); + void Signal(Kernel::KernelCore& kernel) noexcept; + void Clear(Kernel::KernelCore& kernel) noexcept; + Kernel::KReadableEvent* GetHandle() noexcept; private: + KernelHelpers::ServiceContext& ctx; Kernel::KEvent* m_event; }; diff --git a/src/core/hle/service/os/mutex.cpp b/src/core/hle/service/os/mutex.cpp index 6009f48668..12b872b57f 100644 --- a/src/core/hle/service/os/mutex.cpp +++ b/src/core/hle/service/os/mutex.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,22 +13,22 @@ namespace Service { Mutex::Mutex(Core::System& system) : m_system(system) { m_event = Kernel::KEvent::Create(system.Kernel()); - m_event->Initialize(nullptr); + m_event->Initialize(system.Kernel(), nullptr); // Register the event. Kernel::KEvent::Register(system.Kernel(), m_event); - ASSERT(R_SUCCEEDED(m_event->Signal())); + ASSERT(R_SUCCEEDED(m_event->Signal(system.Kernel()))); } Mutex::~Mutex() { - m_event->GetReadableEvent().Close(); - m_event->Close(); + m_event->GetReadableEvent().Close(m_system.Kernel()); + m_event->Close(m_system.Kernel()); } void Mutex::lock() { // Infinitely retry until we successfully clear the event. - while (R_FAILED(m_event->GetReadableEvent().Reset())) { + while (R_FAILED(m_event->GetReadableEvent().Reset(m_system.Kernel()))) { s32 index; Kernel::KSynchronizationObject* obj = &m_event->GetReadableEvent(); @@ -40,7 +43,7 @@ void Mutex::lock() { void Mutex::unlock() { // Unlock. - ASSERT(R_SUCCEEDED(m_event->Signal())); + ASSERT(R_SUCCEEDED(m_event->Signal(m_system.Kernel()))); } } // namespace Service diff --git a/src/core/hle/service/os/process.cpp b/src/core/hle/service/os/process.cpp index 0dbadc315e..5e46de245d 100644 --- a/src/core/hle/service/os/process.cpp +++ b/src/core/hle/service/os/process.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,14 +13,6 @@ namespace Service { -Process::Process(Core::System& system) - : m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(), - m_process_started() {} - -Process::~Process() { - this->Finalize(); -} - bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result) { // First, ensure we are not holding another process. this->Finalize(); @@ -28,7 +23,7 @@ bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_lo // On exit, ensure we free the additional reference to the process. SCOPE_EXIT { - process->Close(); + process->Close(m_system.Kernel()); }; // Insert process modules into memory. @@ -52,7 +47,7 @@ bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_lo // Take ownership of the process object. m_process = process; - m_process->Open(); + m_process->Open(m_system.Kernel()); // We succeeded. return true; @@ -64,8 +59,7 @@ void Process::Finalize() { // Close the process. if (m_process) { - m_process->Close(); - + m_process->Close(m_system.Kernel()); // TODO: remove this, kernel already tracks this m_system.Kernel().RemoveProcess(m_process); } @@ -85,7 +79,7 @@ bool Process::Run() { // Start. if (m_process) { - m_process->Run(m_main_thread_priority, m_main_thread_stack_size); + m_process->Run(m_system.Kernel(), m_main_thread_priority, m_main_thread_stack_size); } // Mark as started. @@ -97,13 +91,13 @@ bool Process::Run() { void Process::Terminate() { if (m_process) { - m_process->Terminate(); + m_process->Terminate(m_system.Kernel()); } } void Process::ResetSignal() { if (m_process) { - m_process->Reset(); + m_process->Reset(m_system.Kernel()); } } @@ -144,8 +138,7 @@ u64 Process::GetProgramId() const { void Process::Suspend(bool suspended) { if (m_process) { - m_process->SetActivity(suspended ? Kernel::Svc::ProcessActivity::Paused - : Kernel::Svc::ProcessActivity::Runnable); + m_process->SetActivity(m_system.Kernel(), suspended ? Kernel::Svc::ProcessActivity::Paused : Kernel::Svc::ProcessActivity::Runnable); } } diff --git a/src/core/hle/service/os/process.h b/src/core/hle/service/os/process.h index 9109b7d0a5..ca10945f84 100644 --- a/src/core/hle/service/os/process.h +++ b/src/core/hle/service/os/process.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,8 +25,8 @@ namespace Service { class Process { public: - explicit Process(Core::System& system); - ~Process(); + inline explicit Process(Core::System& system) noexcept : m_system(system) {} + inline ~Process() { this->Finalize(); } bool Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result); void Finalize(); @@ -50,8 +53,8 @@ public: private: Core::System& m_system; Kernel::KProcess* m_process{}; - s32 m_main_thread_priority{}; u64 m_main_thread_stack_size{}; + s32 m_main_thread_priority{}; bool m_process_started{}; }; diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index b52468e419..5f94984f4e 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -25,19 +28,15 @@ constexpr u64 NO_PROCESS_FOUND_PID{0}; using ProcessList = std::list>; template -Kernel::KScopedAutoObject SearchProcessList(ProcessList& process_list, - F&& predicate) { - const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); - - if (iter == process_list.end()) { - return nullptr; - } - - return iter->GetPointerUnsafe(); +Kernel::KScopedAutoObject SearchProcessList(Kernel::KernelCore& kernel, ProcessList& process_list, F&& predicate) { + auto const it = std::find_if(process_list.begin(), process_list.end(), predicate); + if (it == process_list.end()) + return {kernel, nullptr}; + return {kernel, it->GetPointerUnsafe()}; } -void GetApplicationPidGeneric(HLERequestContext& ctx, ProcessList& process_list) { - auto process = SearchProcessList(process_list, [](auto& p) { return p->IsApplication(); }); +void GetApplicationPidGeneric(Kernel::KernelCore& kernel, HLERequestContext& ctx, ProcessList& process_list) { + auto process = SearchProcessList(kernel, process_list, [](auto& p) { return p->IsApplication(); }); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); @@ -105,7 +104,7 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); auto list = kernel.GetProcessList(); - auto process = SearchProcessList( + auto process = SearchProcessList(system.Kernel(), list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); if (process.IsNull()) { @@ -122,7 +121,7 @@ private: void GetApplicationProcessId(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); + GetApplicationPidGeneric(system.Kernel(), ctx, list); } void AtmosphereGetProcessInfo(HLERequestContext& ctx) { @@ -134,7 +133,7 @@ private: LOG_WARNING(Service_PM, "(Partial Implementation) called, pid={:016X}", pid); auto list = kernel.GetProcessList(); - auto process = SearchProcessList(list, [pid](auto& p) { return p->GetProcessId() == pid; }); + auto process = SearchProcessList(system.Kernel(), list, [pid](auto& p) { return p->GetProcessId() == pid; }); if (process.IsNull()) { IPC::ResponseBuilder rb{ctx, 2}; @@ -188,7 +187,7 @@ private: LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); auto list = kernel.GetProcessList(); - auto process = SearchProcessList( + auto process = SearchProcessList(system.Kernel(), list, [process_id](auto& p) { return p->GetProcessId() == process_id; }); if (process.IsNull()) { @@ -209,7 +208,7 @@ private: LOG_DEBUG(Service_PM, "called, program_id={:016X}", program_id); auto list = system.Kernel().GetProcessList(); - auto process = SearchProcessList( + auto process = SearchProcessList(system.Kernel(), list, [program_id](auto& p) { return p->GetProgramId() == program_id; }); if (process.IsNull()) { @@ -249,7 +248,7 @@ private: void GetApplicationProcessIdForShell(HLERequestContext& ctx) { LOG_DEBUG(Service_PM, "called"); auto list = kernel.GetProcessList(); - GetApplicationPidGeneric(ctx, list); + GetApplicationPidGeneric(system.Kernel(), ctx, list); } }; diff --git a/src/core/hle/service/psc/ovln/receiver.cpp b/src/core/hle/service/psc/ovln/receiver.cpp index f7d3882a05..f43d705126 100644 --- a/src/core/hle/service/psc/ovln/receiver.cpp +++ b/src/core/hle/service/psc/ovln/receiver.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -100,7 +100,7 @@ Result IReceiver::ReceiveWithTick(Out out_notification, } } if (!has_messages) { - receive_event->Clear(); + receive_event->Clear(system.Kernel()); } R_SUCCEED(); diff --git a/src/core/hle/service/psc/time/alarms.cpp b/src/core/hle/service/psc/time/alarms.cpp index 5e52c19f82..c2de95f653 100644 --- a/src/core/hle/service/psc/time/alarms.cpp +++ b/src/core/hle/service/psc/time/alarms.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,8 +10,10 @@ namespace Service::PSC::Time { Alarm::Alarm(Core::System& system, KernelHelpers::ServiceContext& ctx, AlarmType type) - : m_ctx{ctx}, m_event{ctx.CreateEvent("Psc:Alarm:Event")} { - m_event->Clear(); + : m_ctx{ctx} + , m_event{ctx.CreateEvent("Psc:Alarm:Event")} +{ + m_event->Clear(system.Kernel()); switch (type) { case WakeupAlarm: @@ -37,7 +42,7 @@ Alarms::~Alarms() { m_ctx.CloseEvent(m_event); } -Result Alarms::Enable(Alarm& alarm, s64 time) { +Result Alarms::Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time) { R_UNLESS(m_steady_clock.IsInitialized(), ResultClockUninitialized); std::scoped_lock l{m_mutex}; @@ -49,21 +54,21 @@ Result Alarms::Enable(Alarm& alarm, s64 time) { time_ns = Common::AlignUp(time_ns, one_second_ns); alarm.SetAlertTime(time_ns); - Insert(alarm); - R_RETURN(UpdateClosestAndSignal()); + Insert(kernel, alarm); + R_RETURN(UpdateClosestAndSignal(kernel)); } -void Alarms::Disable(Alarm& alarm) { +void Alarms::Disable(Kernel::KernelCore& kernel, Alarm& alarm) { std::scoped_lock l{m_mutex}; if (!alarm.IsLinked()) { return; } - Erase(alarm); - UpdateClosestAndSignal(); + Erase(kernel, alarm); + UpdateClosestAndSignal(kernel); } -void Alarms::CheckAndSignal() { +void Alarms::CheckAndSignal(Kernel::KernelCore& kernel) { std::scoped_lock l{m_mutex}; if (m_alarms.empty()) { return; @@ -72,9 +77,9 @@ void Alarms::CheckAndSignal() { bool alarm_signalled{false}; for (auto& alarm : m_alarms) { if (m_steady_clock.GetRawTime() >= alarm.GetAlertTime()) { - alarm.Signal(); + alarm.Signal(kernel); alarm.Lock(); - Erase(alarm); + Erase(kernel, alarm); m_power_state_request_manager.UpdatePendingPowerStateRequestPriority( alarm.GetPriority()); @@ -87,7 +92,7 @@ void Alarms::CheckAndSignal() { } m_power_state_request_manager.SignalPowerStateRequestAvailability(); - UpdateClosestAndSignal(); + UpdateClosestAndSignal(kernel); } bool Alarms::GetClosestAlarm(Alarm** out_alarm) { @@ -97,7 +102,7 @@ bool Alarms::GetClosestAlarm(Alarm** out_alarm) { return alarm != nullptr; } -void Alarms::Insert(Alarm& alarm) { +void Alarms::Insert(Kernel::KernelCore& kernel, Alarm& alarm) { // Alarms are sorted by alert time, then priority auto it{m_alarms.begin()}; while (it != m_alarms.end()) { @@ -113,15 +118,15 @@ void Alarms::Insert(Alarm& alarm) { m_alarms.push_back(alarm); } -void Alarms::Erase(Alarm& alarm) { +void Alarms::Erase(Kernel::KernelCore& kernel, Alarm& alarm) { m_alarms.erase(m_alarms.iterator_to(alarm)); } -Result Alarms::UpdateClosestAndSignal() { +Result Alarms::UpdateClosestAndSignal(Kernel::KernelCore& kernel) { m_closest_alarm = m_alarms.empty() ? nullptr : std::addressof(m_alarms.front()); R_SUCCEED_IF(m_closest_alarm == nullptr); - m_event->Signal(); + m_event->Signal(kernel); R_SUCCEED(); } @@ -183,7 +188,7 @@ void ISteadyClockAlarm::Enable(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto time{rp.Pop()}; - auto res = m_alarms.Enable(m_alarm, time); + auto res = m_alarms.Enable(system.Kernel(), m_alarm, time); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res); @@ -192,7 +197,7 @@ void ISteadyClockAlarm::Enable(HLERequestContext& ctx) { void ISteadyClockAlarm::Disable(HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called."); - m_alarms.Disable(m_alarm); + m_alarms.Disable(system.Kernel(), m_alarm); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/psc/time/alarms.h b/src/core/hle/service/psc/time/alarms.h index 597770028b..79b66c06ea 100644 --- a/src/core/hle/service/psc/time/alarms.h +++ b/src/core/hle/service/psc/time/alarms.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -48,8 +51,8 @@ struct Alarm : public Common::IntrusiveListBaseNode { return m_priority; } - void Signal() { - m_event->Signal(); + void Signal(Kernel::KernelCore& kernel) { + m_event->Signal(kernel); } Result Lock() { @@ -83,15 +86,15 @@ public: return m_steady_clock.GetRawTime(); } - Result Enable(Alarm& alarm, s64 time); - void Disable(Alarm& alarm); - void CheckAndSignal(); + Result Enable(Kernel::KernelCore& kernel, Alarm& alarm, s64 time); + void Disable(Kernel::KernelCore& kernel, Alarm& alarm); + void CheckAndSignal(Kernel::KernelCore& kernel); bool GetClosestAlarm(Alarm** out_alarm); private: - void Insert(Alarm& alarm); - void Erase(Alarm& alarm); - Result UpdateClosestAndSignal(); + void Insert(Kernel::KernelCore& kernel, Alarm& alarm); + void Erase(Kernel::KernelCore& kernel, Alarm& alarm); + Result UpdateClosestAndSignal(Kernel::KernelCore& kernel); Core::System& m_system; KernelHelpers::ServiceContext m_ctx; diff --git a/src/core/hle/service/psc/time/clocks/context_writers.cpp b/src/core/hle/service/psc/time/clocks/context_writers.cpp index a44486b438..4e54a07a37 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.cpp +++ b/src/core/hle/service/psc/time/clocks/context_writers.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -6,10 +9,10 @@ namespace Service::PSC::Time { -void ContextWriter::SignalAllNodes() { +void ContextWriter::SignalAllNodes(Kernel::KernelCore& kernel) { std::scoped_lock l{m_mutex}; for (auto& operation : m_operation_events) { - operation.m_event->Signal(); + operation.m_event->Signal(kernel); } } @@ -33,7 +36,7 @@ Result LocalSystemClockContextWriter::Write(const SystemClockContext& context) { m_shared_memory.SetLocalSystemContext(context); - SignalAllNodes(); + SignalAllNodes(m_system.Kernel()); R_SUCCEED(); } @@ -57,7 +60,7 @@ Result NetworkSystemClockContextWriter::Write(const SystemClockContext& context) m_shared_memory.SetNetworkSystemContext(context); - SignalAllNodes(); + SignalAllNodes(m_system.Kernel()); R_SUCCEED(); } @@ -75,7 +78,7 @@ Result EphemeralNetworkSystemClockContextWriter::Write(const SystemClockContext& m_in_use = true; } - SignalAllNodes(); + SignalAllNodes(m_system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/clocks/context_writers.h b/src/core/hle/service/psc/time/clocks/context_writers.h index 6643fc9f2a..2adc7d2546 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.h +++ b/src/core/hle/service/psc/time/clocks/context_writers.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,6 +14,9 @@ #include "core/hle/service/psc/time/common.h" #include "core/hle/service/psc/time/shared_memory.h" +namespace Kernel { +class KernelCore; +} namespace Core { class System; } @@ -25,7 +31,7 @@ public: virtual ~ContextWriter() = default; virtual Result Write(const SystemClockContext& context) = 0; - void SignalAllNodes(); + void SignalAllNodes(Kernel::KernelCore& kernel); void Link(OperationEvent& operation_event); private: diff --git a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp index 31ed273966..7a51e51f3c 100644 --- a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -57,7 +60,7 @@ Result StandardUserSystemClockCore::GetTimePoint(SteadyClockTimePoint& out_time_ void StandardUserSystemClockCore::SetTimePointAndSignal(SteadyClockTimePoint& time_point) { m_time_point = time_point; - m_event->Signal(); + m_event->Signal(m_system.Kernel()); } } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/power_state_request_manager.cpp b/src/core/hle/service/psc/time/power_state_request_manager.cpp index b28b513649..7a494f47cb 100644 --- a/src/core/hle/service/psc/time/power_state_request_manager.cpp +++ b/src/core/hle/service/psc/time/power_state_request_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -35,7 +35,7 @@ void PowerStateRequestManager::SignalPowerStateRequestAvailability() { } m_has_pending_request = false; m_available_request_priority = m_pending_request_priority; - m_event->Signal(); + m_event->Signal(m_system.Kernel()); } } @@ -45,7 +45,7 @@ bool PowerStateRequestManager::GetAndClearPowerStateRequest(u32& out_priority) { if (m_has_available_request) { out_priority = m_available_request_priority; m_has_available_request = false; - m_event->Clear(); + m_event->Clear(m_system.Kernel()); } return had_request; } diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index ed9fb32cdf..4646def3db 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -238,7 +241,7 @@ Result ServiceManager::GetClosestAlarmUpdatedEvent( Result ServiceManager::CheckAndSignalAlarms() { LOG_DEBUG(Service_Time, "called."); - m_alarms.CheckAndSignal(); + m_alarms.CheckAndSignal(m_system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 9a0adb2955..488731565d 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -171,7 +174,7 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( R_TRY(m_time->m_standard_steady_clock.GetCurrentTimePoint(time_point)); m_user_system_clock.SetTimePointAndSignal(time_point); - m_user_system_clock.GetEvent().Signal(); + m_user_system_clock.GetEvent().Signal(system.Kernel()); R_SUCCEED(); } diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 06396bbb4c..211f380171 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -43,19 +43,19 @@ public: void SignalChargerTypeChanged() { if (should_signal && should_signal_charger_type) { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } void SignalPowerSupplyChanged() { if (should_signal && should_signal_power_supply) { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } void SignalBatteryVoltageStateChanged() { if (should_signal && should_signal_battery_voltage) { - state_change_event->Signal(); + state_change_event->Signal(system.Kernel()); } } diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index 895bcad864..879e51c65e 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp @@ -57,7 +57,7 @@ struct NrrInfo { struct ProcessContext { constexpr ProcessContext() = default; - void Initialize(Kernel::KProcess* process, u64 process_id) { + void Initialize(Kernel::KernelCore& kernel, Kernel::KProcess* process, u64 process_id) { ASSERT(!m_in_use); m_nro_in_use = {}; @@ -70,15 +70,15 @@ struct ProcessContext { m_in_use = true; if (m_process) { - m_process->Open(); + m_process->Open(kernel); } } - void Finalize() { + void Finalize(Kernel::KernelCore& kernel) { ASSERT(m_in_use); if (m_process) { - m_process->Close(); + m_process->Close(kernel); } m_nro_in_use = {}; @@ -307,7 +307,7 @@ class RoContext { public: explicit RoContext() = default; - Result RegisterProcess(size_t* out_context_id, Kernel::KProcess* process, u64 process_id) { + Result RegisterProcess(Kernel::KernelCore& kernel, size_t* out_context_id, Kernel::KProcess* process, u64 process_id) { // Validate process id. R_UNLESS(process->GetProcessId() == process_id, RO::ResultInvalidProcess); @@ -315,7 +315,7 @@ public: R_UNLESS(this->GetContextByProcessId(process_id) == nullptr, RO::ResultInvalidSession); // Allocate a context to manage the process handle. - *out_context_id = this->AllocateContext(process, process_id); + *out_context_id = this->AllocateContext(kernel, process, process_id); R_SUCCEED(); } @@ -327,8 +327,8 @@ public: R_SUCCEED(); } - void UnregisterProcess(size_t context_id) { - this->FreeContext(context_id); + void UnregisterProcess(Kernel::KernelCore& kernel, size_t context_id) { + this->FreeContext(kernel, context_id); } Result RegisterModuleInfo(size_t context_id, u64 nrr_address, u64 nrr_size, NrrKind nrr_kind, @@ -481,13 +481,13 @@ private: return nullptr; } - size_t AllocateContext(Kernel::KProcess* process, u64 process_id) { + size_t AllocateContext(Kernel::KernelCore& kernel, Kernel::KProcess* process, u64 process_id) { // Find a free process context. for (size_t i = 0; i < MaxSessions; i++) { ProcessContext* context = std::addressof(process_contexts[i]); if (context->IsFree()) { - context->Initialize(process, process_id); + context->Initialize(kernel, process, process_id); return i; } } @@ -496,9 +496,9 @@ private: UNREACHABLE(); } - void FreeContext(size_t context_id) { + void FreeContext(Kernel::KernelCore& kernel, size_t context_id) { if (ProcessContext* context = GetContextById(context_id); context != nullptr) { - context->Finalize(); + context->Finalize(kernel); } } }; @@ -525,7 +525,7 @@ public: } ~RoInterface() { - m_ro->UnregisterProcess(m_context_id); + m_ro->UnregisterProcess(system.Kernel(), m_context_id); } Result MapManualLoadModuleMemory(Out out_load_address, ClientProcessId client_pid, @@ -551,20 +551,16 @@ public: R_RETURN(m_ro->UnregisterModuleInfo(m_context_id, nrr_address)); } - Result RegisterProcessHandle(ClientProcessId client_pid, - InCopyHandle process) { + Result RegisterProcessHandle(ClientProcessId client_pid, InCopyHandle process) { // Register the process. - R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.Get(), *client_pid)); + R_RETURN(m_ro->RegisterProcess(system.Kernel(), std::addressof(m_context_id), process.Get(), *client_pid)); } - Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, - InCopyHandle process) { + Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, InCopyHandle process) { // Validate the process. R_TRY(m_ro->ValidateProcess(m_context_id, *client_pid)); - // Register the module. - R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind, - m_nrr_kind == NrrKind::JitPlugin)); + R_RETURN(m_ro->RegisterModuleInfo(m_context_id, nrr_address, nrr_size, m_nrr_kind, m_nrr_kind == NrrKind::JitPlugin)); } private: diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 3d898725e8..ee0dc83ee8 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -28,13 +31,15 @@ enum class UserDataTag { class Port : public MultiWaitHolder, public Common::IntrusiveListBaseNode { public: - explicit Port(Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory) - : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) { + explicit Port(Kernel::KernelCore& kernel, Kernel::KServerPort* server_port, SessionRequestHandlerFactory&& handler_factory) + : MultiWaitHolder(server_port), m_handler_factory(std::move(handler_factory)) + , m_kernel{kernel} + { this->SetUserData(static_cast(UserDataTag::Port)); } ~Port() { - this->GetNativeHandle()->Close(); + this->GetNativeHandle()->Close(m_kernel); } SessionRequestHandlerPtr CreateHandler() { @@ -43,18 +48,20 @@ public: private: const SessionRequestHandlerFactory m_handler_factory; + Kernel::KernelCore& m_kernel; }; class Session : public MultiWaitHolder, public Common::IntrusiveListBaseNode { public: - explicit Session(Kernel::KServerSession* server_session, - std::shared_ptr&& manager) - : MultiWaitHolder(server_session), m_manager(std::move(manager)) { + explicit Session(Kernel::KernelCore& kernel, Kernel::KServerSession* server_session, std::shared_ptr&& manager) + : MultiWaitHolder(server_session), m_manager(std::move(manager)) + , m_kernel{kernel} + { this->SetUserData(static_cast(UserDataTag::Session)); } ~Session() { - this->GetNativeHandle()->Close(); + this->GetNativeHandle()->Close(m_kernel); } std::shared_ptr& GetManager() { @@ -68,12 +75,16 @@ public: private: std::shared_ptr m_manager; std::shared_ptr m_context; + Kernel::KernelCore& m_kernel; }; -ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selection_mutex{system} { +ServerManager::ServerManager(Core::System& system) + : m_system{system} + , m_selection_mutex{system} +{ // Initialize event. m_wakeup_event = Kernel::KEvent::Create(system.Kernel()); - m_wakeup_event->Initialize(nullptr); + m_wakeup_event->Initialize(m_system.Kernel(), nullptr); // Register event. Kernel::KEvent::Register(system.Kernel(), m_wakeup_event); @@ -86,7 +97,7 @@ ServerManager::ServerManager(Core::System& system) : m_system{system}, m_selecti ServerManager::~ServerManager() { // Signal stop. m_stop_source.request_stop(); - m_wakeup_event->Signal(); + m_wakeup_event->Signal(m_system.Kernel()); // Wait for processing to stop. m_stopped.Wait(); @@ -109,11 +120,11 @@ ServerManager::~ServerManager() { } // Close wakeup event. - m_wakeup_event->GetReadableEvent().Close(); - m_wakeup_event->Close(); + m_wakeup_event->GetReadableEvent().Close(m_system.Kernel()); + m_wakeup_event->Close(m_system.Kernel()); if (m_deferral_event) { - m_deferral_event->GetReadableEvent().Close(); + m_deferral_event->GetReadableEvent().Close(m_system.Kernel()); // Write event is owned by ServiceManager } } @@ -125,7 +136,7 @@ void ServerManager::RunServer(std::unique_ptr&& server_manager) { Result ServerManager::RegisterSession(Kernel::KServerSession* server_session, std::shared_ptr manager) { // We are taking ownership of the server session, so don't open it. - auto* session = new Session(server_session, std::move(manager)); + auto* session = new Session(m_system.Kernel(), server_session, std::move(manager)); // Begin tracking the server session. { @@ -148,7 +159,7 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, max_sessions, handler_factory)); // We are taking ownership of the server port, so don't open it. - auto* server = new Port(server_port, std::move(handler_factory)); + auto* server = new Port(m_system.Kernel(), server_port, std::move(handler_factory)); // Begin tracking the server port. { @@ -177,15 +188,15 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, u32 max_sessions) { // Create a new port. auto* port = Kernel::KPort::Create(m_system.Kernel()); - port->Initialize(max_sessions, false, 0); + port->Initialize(m_system.Kernel(), max_sessions, false, 0); // Register the port. Kernel::KPort::Register(m_system.Kernel(), port); // Ensure that our reference to the port is closed if we fail to register it. SCOPE_EXIT { - port->GetClientPort().Close(); - port->GetServerPort().Close(); + port->GetClientPort().Close(m_system.Kernel()); + port->GetServerPort().Close(m_system.Kernel()); }; // Register the object name with the kernel. @@ -193,10 +204,10 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, service_name.c_str())); // Open a new reference to the server port. - port->GetServerPort().Open(); + port->GetServerPort().Open(m_system.Kernel()); // Transfer ownership into a new port object. - auto* server = new Port(std::addressof(port->GetServerPort()), std::move(handler_factory)); + auto* server = new Port(m_system.Kernel(), std::addressof(port->GetServerPort()), std::move(handler_factory)); // Begin tracking the port. { @@ -217,7 +228,7 @@ Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) { ASSERT(m_deferral_event != nullptr); // Initialize the event. - m_deferral_event->Initialize(nullptr); + m_deferral_event->Initialize(m_system.Kernel(), nullptr); // Register the event. Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event); @@ -258,7 +269,7 @@ void ServerManager::LinkToDeferredList(MultiWaitHolder* holder) { } // Signal the wakeup event. - m_wakeup_event->Signal(); + m_wakeup_event->Signal(m_system.Kernel()); } void ServerManager::LinkDeferred() { @@ -281,7 +292,7 @@ MultiWaitHolder* ServerManager::WaitSignaled() { auto* selected = m_multi_wait.WaitAny(m_system.Kernel()); if (selected == std::addressof(*m_wakeup_holder)) { // Clear and restart if we were woken up. - m_wakeup_event->Clear(); + m_wakeup_event->Clear(m_system.Kernel()); } else { // Unlink and handle the event. selected->UnlinkFromMultiWait(); @@ -323,7 +334,7 @@ Result ServerManager::LoopProcessImpl() { Result ServerManager::OnPortEvent(Port* server) { // Accept a new server session. auto* server_port = static_cast(server->GetNativeHandle()); - Kernel::KServerSession* server_session = server_port->AcceptSession(); + Kernel::KServerSession* server_session = server_port->AcceptSession(m_system.Kernel()); ASSERT(server_session != nullptr); // Create the session manager and install the handler. @@ -345,7 +356,7 @@ Result ServerManager::OnSessionEvent(Session* session) { // Try to receive a message. auto* server_session = static_cast(session->GetNativeHandle()); - res = server_session->ReceiveRequestHLE(&session->GetContext(), session->GetManager()); + res = server_session->ReceiveRequestHLE(m_system.Kernel(), &session->GetContext(), session->GetManager()); // If the session has been closed, we're done. if (res == Kernel::ResultSessionClosed) { @@ -382,7 +393,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) { } // Send the reply. - res = server_session->SendReplyHLE(); + res = server_session->SendReplyHLE(m_system.Kernel()); // If the session has been closed, we're done. if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) { @@ -401,7 +412,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) { Result ServerManager::OnDeferralEvent() { // Clear event before grabbing the list. - m_deferral_event->Clear(); + m_deferral_event->Clear(m_system.Kernel()); // Get and clear list. const auto deferrals = [&] { diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 5332fa3615..241533d53b 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -33,11 +33,11 @@ ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} { ServiceManager::~ServiceManager() { for (auto& [name, port] : service_ports) { - port->Close(); + port->Close(kernel); } if (deferral_event) { - deferral_event->Close(); + deferral_event->Close(kernel); } } @@ -64,7 +64,7 @@ Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, st } auto* port = Kernel::KPort::Create(kernel); - port->Initialize(ServerSessionCountMax, false, 0); + port->Initialize(kernel, ServerSessionCountMax, false, 0); // Register the port. Kernel::KPort::Register(kernel, port); @@ -72,7 +72,7 @@ Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, st service_ports.emplace(name, std::addressof(port->GetClientPort())); registered_services.emplace(name, handler); if (deferral_event) { - deferral_event->Signal(); + deferral_event->Signal(kernel); } // Set our output. @@ -195,7 +195,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques // Create a new session. Kernel::KClientSession* session{}; - if (const auto result = client_port->CreateSession(&session); result.IsError()) { + if (const auto result = client_port->CreateSession(kernel, &session); result.IsError()) { LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); return result; } diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 00c88f6de1..7d7ef38152 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -37,8 +37,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { // once this is a proper process // Reserve a new session from the process resource limit. - Kernel::KScopedResourceReservation session_reservation( - Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax); + Kernel::KScopedResourceReservation session_reservation(system.Kernel(), Kernel::GetCurrentProcessPointer(kernel), Kernel::LimitableResource::SessionCountMax); ASSERT(session_reservation.Succeeded()); // Create the session. @@ -46,7 +45,7 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { ASSERT(session != nullptr); // Initialize the session. - session->Initialize(nullptr, 0); + session->Initialize(kernel, nullptr, 0); // Commit the session reservation. session_reservation.Commit(); diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp index 801a135dd7..002c653b8c 100644 --- a/src/core/hle/service/vi/conductor.cpp +++ b/src/core/hle/service/vi/conductor.cpp @@ -70,7 +70,7 @@ void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { void Conductor::ProcessVsync() { for (auto& [display_id, manager] : m_vsync_managers) { m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); - manager.SignalVsync(); + manager.SignalVsync(m_system.Kernel()); } } diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp index bdc4dfa966..59d0b82e0a 100644 --- a/src/core/hle/service/vi/vsync_manager.cpp +++ b/src/core/hle/service/vi/vsync_manager.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -9,18 +12,10 @@ namespace Service::VI { VsyncManager::VsyncManager() = default; VsyncManager::~VsyncManager() = default; -void VsyncManager::SignalVsync() { +void VsyncManager::SignalVsync(Kernel::KernelCore& kernel) { for (auto* event : m_vsync_events) { - event->Signal(); + event->Signal(kernel); } } -void VsyncManager::LinkVsyncEvent(Event* event) { - m_vsync_events.insert(event); -} - -void VsyncManager::UnlinkVsyncEvent(Event* event) { - m_vsync_events.erase(event); -} - } // namespace Service::VI diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h index 5d45bb5eec..9c04516749 100644 --- a/src/core/hle/service/vi/vsync_manager.h +++ b/src/core/hle/service/vi/vsync_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -5,6 +8,10 @@ #include +namespace Kernel { +class KernelCore; +} + namespace Service { class Event; } @@ -18,9 +25,13 @@ public: explicit VsyncManager(); ~VsyncManager(); - void SignalVsync(); - void LinkVsyncEvent(Event* event); - void UnlinkVsyncEvent(Event* event); + void SignalVsync(Kernel::KernelCore& kernel); + void LinkVsyncEvent(Event* event) { + m_vsync_events.insert(event); + } + void UnlinkVsyncEvent(Event* event) { + m_vsync_events.erase(event); + } private: std::set m_vsync_events; diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 74b2ff7018..3286606c5e 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -235,7 +235,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect ? ::Settings::values.rng_seed.GetValue() : Common::Random::Random64(0)) << 12) & 0xfff000; // Setup the process code layout - if (process.LoadFromMetadata(metadata, code_size, fastmem_base, aslr_offset).IsError()) { + if (process.LoadFromMetadata(system.Kernel(), metadata, code_size, fastmem_base, aslr_offset).IsError()) { return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; } diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index fdfbac0a20..62bcbc9579 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -93,11 +93,11 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, ? ::Settings::values.rng_seed.GetValue() : Common::Random::Random64(0)) << 12) & 0xfff000; // Setup the process code layout - if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset).IsError()) { + if (process.LoadFromMetadata(system.Kernel(), FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset).IsError()) { return {ResultStatus::ErrorNotInitialized, {}}; } const VAddr base_address = GetInteger(process.GetEntryPoint()); - process.LoadModule(std::move(codeset), base_address); + process.LoadModule(system.Kernel(), std::move(codeset), base_address); LOG_DEBUG(Loader, "loaded module {} @ {:#X}", kip->GetName(), base_address); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 21640b7330..4ba4bde0bb 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -280,7 +280,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // Setup the process code layout if (process - .LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), image_size, fastmem_base, aslr_offset) + .LoadFromMetadata(system.Kernel(), FileSys::ProgramMetadata::GetDefault(), image_size, fastmem_base, aslr_offset) .IsError()) { return false; } @@ -296,7 +296,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // Load codeset for current process codeset.memory = std::move(program_image); - process.LoadModule(std::move(codeset), process.GetEntryPoint()); + process.LoadModule(system.Kernel(), std::move(codeset), process.GetEntryPoint()); if (!argv_string.empty()) { constexpr u32 kEntryEndOfList = 0; constexpr u32 kEntryMainThreadHandle = 1; @@ -314,19 +314,14 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, {kEntryArgv, 0, {0, argv_addr}}, {kEntryEndOfList, 0, {0, 0}}, }; - process.GetMemory().WriteBlock(Common::ProcessAddress{config_addr}, entries, - sizeof(entries)); - process.GetMemory().WriteBlock(Common::ProcessAddress{argv_addr}, - argv_string.data(), argv_string.size()); - + process.GetMemory().WriteBlock(Common::ProcessAddress{config_addr}, entries, sizeof(entries)); + process.GetMemory().WriteBlock(Common::ProcessAddress{argv_addr}, argv_string.data(), argv_string.size()); constexpr size_t kMainThreadHandleValueOffset = offsetof(ConfigEntry, value); process.SetArgPointer(Kernel::KProcessAddress{config_addr}); if (exit_process_offset_in_image) { - process.SetArgReturnAddress( - Kernel::KProcessAddress{base + *exit_process_offset_in_image}); + process.SetArgReturnAddress(Kernel::KProcessAddress{base + *exit_process_offset_in_image}); } - process.SetMainThreadHandleAddr( - Kernel::KProcessAddress{config_addr + kMainThreadHandleValueOffset}); + process.SetMainThreadHandleAddr(Kernel::KProcessAddress{config_addr + kMainThreadHandleValueOffset}); } return true; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 482c853542..a831f44a40 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -217,7 +217,7 @@ std::optional AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: } // Load codeset for current process - process.LoadModule(std::move(codeset), load_base); + process.LoadModule(system.Kernel(), std::move(codeset), load_base); return load_base + image_size; } diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index dcfd23644f..8e23a54a0d 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -91,17 +91,15 @@ u64 StandardVmCallbacks::HidKeysDown() { } void StandardVmCallbacks::PauseProcess() { - if (system.ApplicationProcess()->IsSuspended()) { - return; + if (!system.ApplicationProcess()->IsSuspended()) { + system.ApplicationProcess()->SetActivity(system.Kernel(), Kernel::Svc::ProcessActivity::Paused); } - system.ApplicationProcess()->SetActivity(Kernel::Svc::ProcessActivity::Paused); } void StandardVmCallbacks::ResumeProcess() { - if (!system.ApplicationProcess()->IsSuspended()) { - return; + if (system.ApplicationProcess()->IsSuspended()) { + system.ApplicationProcess()->SetActivity(system.Kernel(), Kernel::Svc::ProcessActivity::Runnable); } - system.ApplicationProcess()->SetActivity(Kernel::Svc::ProcessActivity::Runnable); } void StandardVmCallbacks::DebugLog(u8 id, u64 value) { diff --git a/src/hid_core/hid_core.cpp b/src/hid_core/hid_core.cpp index 410c84afbc..12cd0c1f27 100644 --- a/src/hid_core/hid_core.cpp +++ b/src/hid_core/hid_core.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,18 +13,20 @@ namespace Core::HID { -HIDCore::HIDCore() - : player_1{std::make_unique(NpadIdType::Player1)}, - player_2{std::make_unique(NpadIdType::Player2)}, - player_3{std::make_unique(NpadIdType::Player3)}, - player_4{std::make_unique(NpadIdType::Player4)}, - player_5{std::make_unique(NpadIdType::Player5)}, - player_6{std::make_unique(NpadIdType::Player6)}, - player_7{std::make_unique(NpadIdType::Player7)}, - player_8{std::make_unique(NpadIdType::Player8)}, - other{std::make_unique(NpadIdType::Other)}, - handheld{std::make_unique(NpadIdType::Handheld)}, - console{std::make_unique()}, devices{std::make_unique()} {} +HIDCore::HIDCore(Kernel::KernelCore& kernel_) + : player_1{std::make_unique(NpadIdType::Player1)} + , player_2{std::make_unique(NpadIdType::Player2)} + , player_3{std::make_unique(NpadIdType::Player3)} + , player_4{std::make_unique(NpadIdType::Player4)} + , player_5{std::make_unique(NpadIdType::Player5)} + , player_6{std::make_unique(NpadIdType::Player6)} + , player_7{std::make_unique(NpadIdType::Player7)} + , player_8{std::make_unique(NpadIdType::Player8)} + , other{std::make_unique(NpadIdType::Other)} + , handheld{std::make_unique(NpadIdType::Handheld)} + , console{std::make_unique()}, devices{std::make_unique()} + , kernel{kernel_} +{} HIDCore::~HIDCore() = default; diff --git a/src/hid_core/hid_core.h b/src/hid_core/hid_core.h index dae29c5062..7da11897ca 100644 --- a/src/hid_core/hid_core.h +++ b/src/hid_core/hid_core.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,6 +11,10 @@ #include "common/common_funcs.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Core::HID { class EmulatedConsole; class EmulatedController; @@ -18,7 +25,7 @@ namespace Core::HID { class HIDCore { public: - explicit HIDCore(); + explicit HIDCore(Kernel::KernelCore& kernel); ~HIDCore(); YUZU_NON_COPYABLE(HIDCore); @@ -69,7 +76,6 @@ public: /// Number of emulated controllers static constexpr std::size_t available_controllers{10}; -private: std::unique_ptr player_1; std::unique_ptr player_2; std::unique_ptr player_3; @@ -82,6 +88,7 @@ private: std::unique_ptr handheld; std::unique_ptr console; std::unique_ptr devices; + Kernel::KernelCore& kernel; NpadStyleTag supported_style_tag{NpadStyleSet::All}; NpadIdType last_active_controller{NpadIdType::Handheld}; }; diff --git a/src/hid_core/hidbus/ringcon.cpp b/src/hid_core/hidbus/ringcon.cpp index 1927a6f856..b942cad480 100644 --- a/src/hid_core/hidbus/ringcon.cpp +++ b/src/hid_core/hidbus/ringcon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -141,12 +141,12 @@ bool RingController::SetCommand(std::span data) { case RingConCommands::ReadRepCount: case RingConCommands::ReadTotalPushCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); - send_command_async_event->Signal(); + send_command_async_event->Signal(system.Kernel()); return true; case RingConCommands::ResetRepCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); total_rep_count = 0; - send_command_async_event->Signal(); + send_command_async_event->Signal(system.Kernel()); return true; case RingConCommands::SaveCalData: { ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); @@ -154,14 +154,14 @@ bool RingController::SetCommand(std::span data) { SaveCalData save_info{}; std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); user_calibration = save_info.calibration; - send_command_async_event->Signal(); + send_command_async_event->Signal(system.Kernel()); return true; } default: LOG_ERROR(Service_HID, "Command not implemented {}", command); command = RingConCommands::Error; // Signal a reply to avoid softlocking the game - send_command_async_event->Signal(); + send_command_async_event->Signal(system.Kernel()); return false; } } diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index 0c10d1bec9..d4d62ea4ba 100644 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp @@ -91,7 +91,7 @@ ResourceManager::~ResourceManager() { system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event); system.CoreTiming().UnscheduleEvent(motion_update_event); system.CoreTiming().UnscheduleEvent(touch_update_event); - input_event->Finalize(); + input_event->Finalize(system.Kernel()); }; void ResourceManager::Initialize() { @@ -486,7 +486,7 @@ void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); - npad->OnUpdate(core_timing); + npad->OnUpdate(system.Kernel(), core_timing); } void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) { diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp index d5f37247e1..a80f8271f9 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -16,7 +16,9 @@ namespace Service::HID { -NpadAbstractBatteryHandler::NpadAbstractBatteryHandler() {} +NpadAbstractBatteryHandler::NpadAbstractBatteryHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractBatteryHandler::~NpadAbstractBatteryHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h index 85ac5eb72f..9c270aa92d 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +10,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { struct AppletResourceHolder; class NpadAbstractedPadHolder; @@ -15,7 +22,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractBatteryHandler final { public: - explicit NpadAbstractBatteryHandler(); + explicit NpadAbstractBatteryHandler(Kernel::KernelCore& kernel_); ~NpadAbstractBatteryHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -44,6 +51,7 @@ private: Core::HID::NpadPowerInfo left_battery{}; Core::HID::NpadPowerInfo right_battery{}; bool has_new_battery_data{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp index 36deb25c94..239fc7656e 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -16,7 +16,9 @@ namespace Service::HID { -NpadAbstractButtonHandler::NpadAbstractButtonHandler() {} +NpadAbstractButtonHandler::NpadAbstractButtonHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractButtonHandler::~NpadAbstractButtonHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.h b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h index 01eafe96df..6e49471b5e 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_button_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +10,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { struct NpadSharedMemoryEntry; @@ -17,7 +24,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractButtonHandler final { public: - explicit NpadAbstractButtonHandler(); + explicit NpadAbstractButtonHandler(Kernel::KernelCore& kernel_); ~NpadAbstractButtonHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -70,6 +77,7 @@ private: u64 gc_sampling_number{}; GcTrigger gc_trigger_state{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp index 16ec2257fb..a2aaa1d8ec 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -14,7 +14,9 @@ namespace Service::HID { -NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler() {} +NpadAbstractIrSensorHandler::NpadAbstractIrSensorHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractIrSensorHandler::~NpadAbstractIrSensorHandler() = default; @@ -52,7 +54,7 @@ void NpadAbstractIrSensorHandler::UpdateIrSensorState() { if (sensor_state == previous_state) { return; } - ir_sensor_event->Signal(); + ir_sensor_event->Signal(kernel); return; } @@ -77,7 +79,7 @@ void NpadAbstractIrSensorHandler::UpdateIrSensorState() { if (sensor_state == previous_state) { return; } - ir_sensor_event->Signal(); + ir_sensor_event->Signal(kernel); return; } @@ -86,7 +88,7 @@ void NpadAbstractIrSensorHandler::UpdateIrSensorState() { return; } - ir_sensor_event->Signal(); + ir_sensor_event->Signal(kernel); return; } @@ -105,7 +107,7 @@ Result NpadAbstractIrSensorHandler::ActivateIrSensor(bool is_enabled) { } sensor_state = NpadIrSensorState::Available; } - ir_sensor_event->Signal(); + ir_sensor_event->Signal(kernel); return ResultSuccess; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h index 9978115116..799d83e82f 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -12,6 +15,7 @@ class EmulatedController; } namespace Kernel { +class KernelCore; class KEvent; class KReadableEvent; } // namespace Kernel @@ -30,7 +34,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractIrSensorHandler final { public: - explicit NpadAbstractIrSensorHandler(); + explicit NpadAbstractIrSensorHandler(Kernel::KernelCore& kernel_); ~NpadAbstractIrSensorHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -56,5 +60,6 @@ private: Kernel::KEvent* ir_sensor_event{nullptr}; Core::HID::EmulatedController* xcd_handle{}; NpadIrSensorState sensor_state{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp index 813d3d3188..94d895509b 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -15,7 +15,9 @@ namespace Service::HID { -NpadAbstractLedHandler::NpadAbstractLedHandler() {} +NpadAbstractLedHandler::NpadAbstractLedHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractLedHandler::~NpadAbstractLedHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.h b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h index 09528129b6..7ff12a9e75 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_led_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +10,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { struct AppletResourceHolder; class NpadAbstractedPadHolder; @@ -15,7 +22,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractLedHandler final { public: - explicit NpadAbstractLedHandler(); + explicit NpadAbstractLedHandler(Kernel::KernelCore& kernel_); ~NpadAbstractLedHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -39,5 +46,6 @@ private: Core::HID::LedPattern left_pattern{0, 0, 0, 0}; Core::HID::LedPattern right_pattern{0, 0, 0, 0}; u64 led_interval{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp index 2b763d8e0f..d87446030a 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -12,7 +12,9 @@ namespace Service::HID { -NpadAbstractMcuHandler::NpadAbstractMcuHandler() {} +NpadAbstractMcuHandler::NpadAbstractMcuHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractMcuHandler::~NpadAbstractMcuHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h index 9902dd03a7..44be82cd43 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +10,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { struct IAbstractedPad; class NpadAbstractedPadHolder; @@ -28,7 +35,7 @@ static_assert(sizeof(NpadMcuHolder) == 0x10, "NpadMcuHolder is an invalid size") /// Handles Npad request from HID interfaces class NpadAbstractMcuHandler final { public: - explicit NpadAbstractMcuHandler(); + explicit NpadAbstractMcuHandler(Kernel::KernelCore& kernel_); ~NpadAbstractMcuHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -48,5 +55,6 @@ private: s32 ref_counter{}; std::array mcu_holder{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp index 80f5f3ba62..9990add4cc 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -14,7 +14,9 @@ namespace Service::HID { -NpadAbstractNfcHandler::NpadAbstractNfcHandler() {} +NpadAbstractNfcHandler::NpadAbstractNfcHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractNfcHandler::~NpadAbstractNfcHandler() = default; @@ -48,13 +50,13 @@ void NpadAbstractNfcHandler::UpdateNfcState() { if (count == 0) { if (sensor_state == NpadNfcState::Active) { - nfc_activate_event->Signal(); + nfc_activate_event->Signal(kernel); } if (sensor_state == NpadNfcState::Unavailable) { return; } sensor_state = NpadNfcState::Unavailable; - input_event->Signal(); + input_event->Signal(kernel); return; } @@ -79,19 +81,18 @@ void NpadAbstractNfcHandler::UpdateNfcState() { return; } sensor_state = NpadNfcState::Available; - input_event->Signal(); + input_event->Signal(kernel); return; } if (sensor_state == NpadNfcState::Active) { - nfc_activate_event->Signal(); + nfc_activate_event->Signal(kernel); } if (sensor_state == NpadNfcState::Unavailable) { return; } sensor_state = NpadNfcState::Unavailable; - input_event->Signal(); - return; + input_event->Signal(kernel); } bool NpadAbstractNfcHandler::HasNfcSensor() { @@ -123,7 +124,7 @@ Result NpadAbstractNfcHandler::ActivateNfc(bool is_enabled) { } if (sensor_state != new_state) { sensor_state = new_state; - nfc_activate_event->Signal(); + nfc_activate_event->Signal(kernel); } return ResultSuccess; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h index 0702722a6b..223a0afd4e 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -8,7 +11,9 @@ #include "hid_core/hid_types.h" namespace Kernel { +class KernelCore; class KReadableEvent; +class KEvent; } enum class NpadNfcState : u32 { @@ -24,7 +29,7 @@ class NpadAbstractPropertiesHandler; /// Handles Npad request from HID interfaces class NpadAbstractNfcHandler final { public: - explicit NpadAbstractNfcHandler(); + explicit NpadAbstractNfcHandler(Kernel::KernelCore& kernel_); ~NpadAbstractNfcHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -53,5 +58,6 @@ private: Kernel::KEvent* input_event{nullptr}; u64 xcd_handle{}; NpadNfcState sensor_state{NpadNfcState::Unavailable}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp index d7cf2bba9b..b828c9b11e 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -12,7 +12,20 @@ namespace Service::HID { -AbstractPad::AbstractPad() {} +AbstractPad::AbstractPad(Kernel::KernelCore& kernel_) + //: abstract_pad_holder{kernel_} + : properties_handler{kernel_} + , led_handler{kernel_} + , ir_sensor_handler{kernel_} + , nfc_handler{kernel_} + , mcu_handler{kernel_} + , vibration_handler{kernel_} + , sixaxis_handler{kernel_} + , button_handler{kernel_} + , battery_handler{kernel_} + , palma_handler{kernel_} + , kernel{kernel_} +{} AbstractPad::~AbstractPad() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h index 3297924574..99d886d40c 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.h +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -27,6 +30,10 @@ #include "hid_core/resources/vibration/n64_vibration_device.h" #include "hid_core/resources/vibration/vibration_device.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { class AppletResource; class SixAxisResource; @@ -49,7 +56,7 @@ struct HandheldConfig; /// Handles Npad request from HID interfaces class AbstractPad final { public: - explicit AbstractPad(); + explicit AbstractPad(Kernel::KernelCore& kernel_); ~AbstractPad(); void SetExternals(AppletResourceHolder* applet_resource, @@ -88,17 +95,19 @@ public: private: AppletResourceHolder* applet_resource_holder{nullptr}; + + // TODO: fix NpadAbstractedPadHolder abstract_pad_holder{}; - NpadAbstractPropertiesHandler properties_handler{}; - NpadAbstractLedHandler led_handler{}; - NpadAbstractIrSensorHandler ir_sensor_handler{}; - NpadAbstractNfcHandler nfc_handler{}; - NpadAbstractMcuHandler mcu_handler{}; - NpadAbstractVibrationHandler vibration_handler{}; - NpadAbstractSixAxisHandler sixaxis_handler{}; - NpadAbstractButtonHandler button_handler{}; - NpadAbstractBatteryHandler battery_handler{}; - NpadAbstractPalmaHandler palma_handler{}; + NpadAbstractPropertiesHandler properties_handler; + NpadAbstractLedHandler led_handler; + NpadAbstractIrSensorHandler ir_sensor_handler; + NpadAbstractNfcHandler nfc_handler; + NpadAbstractMcuHandler mcu_handler; + NpadAbstractVibrationHandler vibration_handler; + NpadAbstractSixAxisHandler sixaxis_handler; + NpadAbstractButtonHandler button_handler; + NpadAbstractBatteryHandler battery_handler; + NpadAbstractPalmaHandler palma_handler; NpadN64VibrationDevice vibration_n64{}; NpadVibrationDevice vibration_left{}; @@ -114,6 +123,7 @@ private: s32 ref_counter{}; Core::HID::NpadInterfaceType interface_type{Core::HID::NpadInterfaceType::None}; + Kernel::KernelCore& kernel; }; using FullAbstractPad = std::array; diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp index 7766bedfd0..981f92ea00 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -10,7 +10,9 @@ namespace Service::HID { -NpadAbstractPalmaHandler::NpadAbstractPalmaHandler() {} +NpadAbstractPalmaHandler::NpadAbstractPalmaHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractPalmaHandler::~NpadAbstractPalmaHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h index fbd2e67e53..c09572a7b6 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -7,6 +10,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { class NpadAbstractedPadHolder; class NpadAbstractPropertiesHandler; @@ -14,7 +21,7 @@ class PalmaResource; class NpadAbstractPalmaHandler final { public: - explicit NpadAbstractPalmaHandler(); + explicit NpadAbstractPalmaHandler(Kernel::KernelCore& kernel_); ~NpadAbstractPalmaHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -32,6 +39,7 @@ private: PalmaResource* palma_resource{nullptr}; s32 ref_counter{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp index c225670043..db011bc6dd 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -14,7 +14,9 @@ namespace Service::HID { -NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler() {} +NpadAbstractPropertiesHandler::NpadAbstractPropertiesHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractPropertiesHandler::~NpadAbstractPropertiesHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h index fa68278998..1b8cf4be82 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -10,6 +13,10 @@ #include "hid_core/hid_types.h" #include "hid_core/resources/npad/npad_types.h" +namespace Kernel { +class KernelCore; +} + namespace Service::HID { struct NpadSharedMemoryEntry; @@ -25,7 +32,7 @@ struct ColorProperties { /// Handles Npad request from HID interfaces class NpadAbstractPropertiesHandler final { public: - explicit NpadAbstractPropertiesHandler(); + explicit NpadAbstractPropertiesHandler(Kernel::KernelCore& kernel_); ~NpadAbstractPropertiesHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -82,5 +89,6 @@ private: ColorProperties fullkey_color{}; ColorProperties left_color{}; ColorProperties right_color{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp index a8d2e5b2a0..54055751a2 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -15,7 +15,9 @@ namespace Service::HID { -NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler() {} +NpadAbstractSixAxisHandler::NpadAbstractSixAxisHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractSixAxisHandler::~NpadAbstractSixAxisHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h index 9c20459e91..c126c25a23 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -6,6 +9,11 @@ #include "common/common_types.h" #include "core/hle/result.h" #include "hid_core/hid_types.h" +#include "hid_core/resources/shared_memory_format.h" + +namespace Kernel { +class KernelCore; +} namespace Service::HID { class SixAxisResource; @@ -17,7 +25,7 @@ struct NpadSixAxisSensorLifo; /// Handles Npad request from HID interfaces class NpadAbstractSixAxisHandler final { public: - explicit NpadAbstractSixAxisHandler(); + explicit NpadAbstractSixAxisHandler(Kernel::KernelCore& kernel_); ~NpadAbstractSixAxisHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -56,6 +64,7 @@ private: SixAxisResource* six_axis_resource{nullptr}; s32 ref_counter{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp index 3266422133..a0a37806fc 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -19,7 +19,9 @@ namespace Service::HID { -NpadAbstractVibrationHandler::NpadAbstractVibrationHandler() {} +NpadAbstractVibrationHandler::NpadAbstractVibrationHandler(Kernel::KernelCore& kernel_) + : kernel{kernel_} +{} NpadAbstractVibrationHandler::~NpadAbstractVibrationHandler() = default; diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h index 8bc8129c24..d57bf27814 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -9,6 +12,10 @@ #include "core/hle/result.h" #include "hid_core/hid_types.h" +namespace Kernel { +class KernelCore; +} + namespace Core::HID { class HIDCore; } @@ -25,7 +32,7 @@ class NpadVibration; /// Keeps track of battery levels and updates npad battery shared memory values class NpadAbstractVibrationHandler final { public: - explicit NpadAbstractVibrationHandler(); + explicit NpadAbstractVibrationHandler(Kernel::KernelCore& kernel_); ~NpadAbstractVibrationHandler(); void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); @@ -55,5 +62,6 @@ private: NpadGcVibrationDevice* gc_vibration_device{nullptr}; NpadVibration* vibration_handler{nullptr}; s32 ref_counter{}; + Kernel::KernelCore& kernel; }; } // namespace Service::HID diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index 31480a0e90..a7b9658cac 100644 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -14,7 +14,10 @@ namespace Service::HID { AppletResource::AppletResource(Core::System& system_) : system{system_} {} -AppletResource::~AppletResource() = default; +AppletResource::~AppletResource() { + for (size_t i = 0; i < shared_memory_holder.size(); ++i) + shared_memory_holder[i].Finalize(system); +} Result AppletResource::CreateAppletResource(u64 aruid) { const u64 index = GetIndexFromAruid(aruid); @@ -34,7 +37,7 @@ Result AppletResource::CreateAppletResource(u64 aruid) { return result; } if (shared_memory.GetAddress() == nullptr) { - shared_memory.Finalize(); + shared_memory.Finalize(system); return ResultSharedMemoryNotInitialized; } } @@ -139,7 +142,7 @@ void AppletResource::FreeAppletResourceId(u64 aruid) { if (aruid_data.flag.is_assigned) { aruid_data.shared_memory_format = nullptr; aruid_data.flag.is_assigned.Assign(false); - shared_memory_holder[index].Finalize(); + shared_memory_holder[index].Finalize(system); } } diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 04d8a85301..8e309238d2 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -29,21 +29,36 @@ namespace Service::HID { NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) - : hid_core{hid_core_}, service_context{service_context_}, npad_resource{service_context} { + : hid_core{hid_core_} + , service_context{service_context_} + , npad_resource{hid_core_.kernel, service_context} + , abstracted_pads{{ + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + AbstractPad{hid_core_.kernel}, + }} +{ for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) { for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { auto& controller = controller_data[aruid_index][i]; controller.device = hid_core.GetEmulatedControllerByIndex(i); Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = - [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, + .on_change = [this, i](Core::HID::ControllerTriggerType type) { + ControllerUpdate(hid_core.kernel, type, i); + }, .is_npad_service = true, }; controller.callback_key = controller.device->SetCallback(engine_callback); } } for (std::size_t i = 0; i < abstracted_pads.size(); ++i) { - abstracted_pads[i] = AbstractPad{}; abstracted_pads[i].SetNpadId(IndexToNpadIdType(i)); } } @@ -123,10 +138,10 @@ void NPad::FreeAppletResourceId(u64 aruid) { return npad_resource.FreeAppletResourceId(aruid); } -void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) { +void NPad::ControllerUpdate(Kernel::KernelCore& kernel, Core::HID::ControllerTriggerType type, std::size_t controller_idx) { if (type == Core::HID::ControllerTriggerType::All) { - ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx); - ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx); + ControllerUpdate(kernel, Core::HID::ControllerTriggerType::Connected, controller_idx); + ControllerUpdate(kernel, Core::HID::ControllerTriggerType::Battery, controller_idx); return; } @@ -151,7 +166,7 @@ void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t c if (is_connected == controller.is_connected) { return; } - UpdateControllerAt(data->aruid, npad_type, npad_id, is_connected); + UpdateControllerAt(kernel, data->aruid, npad_type, npad_id, is_connected); break; case Core::HID::ControllerTriggerType::Battery: { if (!controller.device->IsConnected()) { @@ -173,7 +188,7 @@ void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t c } } -void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { +void NPad::InitNewlyAddedController(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { auto& controller = GetControllerFromNpadIdType(aruid, npad_id); if (!npad_resource.IsControllerSupported(aruid, controller.device->GetNpadStyleIndex())) { return; @@ -188,7 +203,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { return; } if (controller_type == Core::HID::NpadStyleIndex::None) { - npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); + npad_resource.SignalStyleSetUpdateEvent(kernel, aruid, npad_id); return; } @@ -372,7 +387,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { Common::Input::PollingMode::Active); } - npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); + npad_resource.SignalStyleSetUpdateEvent(kernel, aruid, npad_id); WriteEmptyEntry(controller.shared_memory); hid_core.SetLastActiveController(npad_id); abstracted_pads[NpadIdTypeToIndex(npad_id)].Update(); @@ -399,20 +414,20 @@ void NPad::WriteEmptyEntry(NpadInternalState* npad) { npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state); } -void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) { +void NPad::RequestPadStateUpdate(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { std::scoped_lock lock{*applet_resource_holder.shared_mutex}; auto& controller = GetControllerFromNpadIdType(aruid, npad_id); const auto controller_type = controller.device->GetNpadStyleIndex(); if (!controller.device->IsConnected() && controller.is_connected) { - DisconnectNpad(aruid, npad_id); + DisconnectNpad(kernel, aruid, npad_id); return; } if (!controller.device->IsConnected()) { return; } if (controller.device->IsConnected() && !controller.is_connected) { - InitNewlyAddedController(aruid, npad_id); + InitNewlyAddedController(kernel, aruid, npad_id); } // This function is unique to yuzu for the turbo buttons and motion to work properly @@ -468,7 +483,7 @@ void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) { } } -void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { +void NPad::OnUpdate(Kernel::KernelCore& kernel, const Core::Timing::CoreTiming& core_timing) { if (ref_counter == 0) { return; } @@ -510,7 +525,7 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { continue; } - RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); + RequestPadStateUpdate(kernel, aruid, controller.device->GetNpadIdType()); auto& pad_state = controller.npad_pad_state; auto& libnx_state = controller.npad_libnx_state; auto& trigger_state = controller.npad_trigger_state; @@ -627,17 +642,17 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { } } -Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) { +Result NPad::SetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet supported_style_set) { std::scoped_lock lock{mutex}; hid_core.SetSupportedStyleTag({supported_style_set}); const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set); if (result.IsSuccess()) { - OnUpdate({}); + OnUpdate(kernel, {}); } return result; } -Result NPad::GetSupportedNpadStyleSet(u64 aruid, +Result NPad::GetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { std::scoped_lock lock{mutex}; const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid); @@ -650,8 +665,7 @@ Result NPad::GetSupportedNpadStyleSet(u64 aruid, return result; } -Result NPad::GetMaskedSupportedNpadStyleSet( - u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { +Result NPad::GetMaskedSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const { std::scoped_lock lock{mutex}; const Result result = npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid); @@ -664,8 +678,7 @@ Result NPad::GetMaskedSupportedNpadStyleSet( return result; } -Result NPad::SetSupportedNpadIdType(u64 aruid, - std::span supported_npad_list) { +Result NPad::SetSupportedNpadIdType(Kernel::KernelCore& kernel, u64 aruid, std::span supported_npad_list) { std::scoped_lock lock{mutex}; if (supported_npad_list.size() > MaxSupportedNpadIdTypes) { return ResultInvalidArraySize; @@ -674,7 +687,7 @@ Result NPad::SetSupportedNpadIdType(u64 aruid, Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list); if (result.IsSuccess()) { - OnUpdate({}); + OnUpdate(kernel, {}); } return result; @@ -690,22 +703,21 @@ Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid); } -Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) { +Result NPad::SetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode mode) { std::scoped_lock lock{mutex}; Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode); if (result.IsSuccess()) { - OnUpdate({}); + OnUpdate(kernel, {}); } return result; } -Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const { +Result NPad::GetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode& out_mode) const { std::scoped_lock lock{mutex}; return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid); } -bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, - NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { +bool NPad::SetNpadMode(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); return false; @@ -727,17 +739,17 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID: if (assignment_mode == NpadJoyAssignmentMode::Dual) { if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) { - DisconnectNpad(aruid, npad_id); + DisconnectNpad(kernel, aruid, npad_id); controller.is_dual_left_connected = true; controller.is_dual_right_connected = false; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); return false; } if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) { - DisconnectNpad(aruid, npad_id); + DisconnectNpad(kernel, aruid, npad_id); controller.is_dual_left_connected = false; controller.is_dual_right_connected = true; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true); return false; } return false; @@ -751,58 +763,55 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID: } if (controller.is_dual_left_connected && !controller.is_dual_right_connected) { - DisconnectNpad(aruid, npad_id); - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); + DisconnectNpad(kernel, aruid, npad_id); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); return false; } if (!controller.is_dual_left_connected && controller.is_dual_right_connected) { - DisconnectNpad(aruid, npad_id); - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); + DisconnectNpad(kernel, aruid, npad_id); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); return false; } // We have two controllers connected to the same npad_id we need to split them new_npad_id = hid_core.GetFirstDisconnectedNpadId(); auto& controller_2 = GetControllerFromNpadIdType(aruid, new_npad_id); - DisconnectNpad(aruid, npad_id); + DisconnectNpad(kernel, aruid, npad_id); if (npad_device_type == NpadJoyDeviceType::Left) { - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true); controller_2.is_dual_left_connected = false; controller_2.is_dual_right_connected = true; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } else { - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true); controller_2.is_dual_left_connected = true; controller_2.is_dual_right_connected = false; - UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); + UpdateControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true); } return true; } -Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id) { +Result NPad::AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id) { std::scoped_lock lock{mutex}; - return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id); + return npad_resource.AcquireNpadStyleSetUpdateEventHandle(kernel, aruid, out_event, npad_id); } -void NPad::AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, - Core::HID::NpadIdType npad_id) { - UpdateControllerAt(aruid, controller, npad_id, true); +void NPad::AddNewControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id) { + UpdateControllerAt(kernel, aruid, controller, npad_id, true); } -void NPad::UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex type, - Core::HID::NpadIdType npad_id, bool connected) { +void NPad::UpdateControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex type, Core::HID::NpadIdType npad_id, bool connected) { auto& controller = GetControllerFromNpadIdType(aruid, npad_id); if (!connected) { - DisconnectNpad(aruid, npad_id); + DisconnectNpad(kernel, aruid, npad_id); return; } controller.device->SetNpadStyleIndex(type); - InitNewlyAddedController(aruid, npad_id); + InitNewlyAddedController(kernel, aruid, npad_id); } -Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { +Result NPad::DisconnectNpad(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { if (!IsNpadIdValid(npad_id)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); return ResultInvalidNpadId; @@ -845,7 +854,7 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { controller.is_dual_right_connected = true; controller.is_connected = false; controller.device->Disconnect(); - npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); + npad_resource.SignalStyleSetUpdateEvent(kernel, aruid, npad_id); WriteEmptyEntry(shared_memory); return ResultSuccess; } @@ -878,8 +887,7 @@ Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( return ResultSuccess; } -Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2) { +Result NPad::MergeSingleJoyAsDualJoy(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) { if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, npad_id_2); @@ -933,11 +941,11 @@ Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, } // Disconnect the joycons and connect them as dual joycon at the first index. - DisconnectNpad(aruid, npad_id_1); - DisconnectNpad(aruid, npad_id_2); + DisconnectNpad(kernel, aruid, npad_id_1); + DisconnectNpad(kernel, aruid, npad_id_2); controller_1.is_dual_left_connected = true; controller_1.is_dual_right_connected = true; - AddNewControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); + AddNewControllerAt(kernel, aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); return ResultSuccess; } @@ -961,11 +969,9 @@ Result NPad::StopLrAssignmentMode(u64 aruid) { return result; } -Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2) { +Result NPad::SwapNpadAssignment(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2) { if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { - LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, - npad_id_2); + LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, npad_id_2); return ResultInvalidNpadId; } if (npad_id_1 == Core::HID::NpadIdType::Handheld || @@ -987,20 +993,17 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, return ResultNpadNotConnected; } - UpdateControllerAt(aruid, type_index_2, npad_id_1, is_connected_2); - UpdateControllerAt(aruid, type_index_1, npad_id_2, is_connected_1); - + UpdateControllerAt(kernel, aruid, type_index_2, npad_id_1, is_connected_2); + UpdateControllerAt(kernel, aruid, type_index_1, npad_id_2, is_connected_1); return ResultSuccess; } -Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const { +Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid, Core::HID::NpadIdType npad_id) const { std::scoped_lock lock{mutex}; return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id); } -Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, - bool is_enabled) { +Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled) { std::scoped_lock lock{mutex}; return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled); } @@ -1054,29 +1057,29 @@ Core::HID::NpadButton NPad::GetAndResetPressState() { return static_cast(press_state.exchange(0)); } -Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) { +Result NPad::ApplyNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid) { std::scoped_lock lock{mutex}; const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false); if (result.IsSuccess()) { - OnUpdate({}); + OnUpdate(kernel, {}); } return result; } -Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) { +Result NPad::ApplyNpadSystemCommonPolicyFull(Kernel::KernelCore& kernel, u64 aruid) { std::scoped_lock lock{mutex}; const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true); if (result.IsSuccess()) { - OnUpdate({}); + OnUpdate(kernel, {}); } return result; } -Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) { +Result NPad::ClearNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid) { std::scoped_lock lock{mutex}; const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid); if (result.IsSuccess()) { - OnUpdate({}); + OnUpdate(kernel, {}); } return result; } diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 99e761127d..3e10f02a7c 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -61,37 +64,31 @@ public: void FreeAppletResourceId(u64 aruid); // When the controller is requesting an update for the shared memory - void OnUpdate(const Core::Timing::CoreTiming& core_timing); + void OnUpdate(Kernel::KernelCore& kernel, const Core::Timing::CoreTiming& core_timing); - Result SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set); - Result GetSupportedNpadStyleSet(u64 aruid, - Core::HID::NpadStyleSet& out_supported_style_set) const; - Result GetMaskedSupportedNpadStyleSet(u64 aruid, - Core::HID::NpadStyleSet& out_supported_style_set) const; - - Result SetSupportedNpadIdType(u64 aruid, - std::span supported_npad_list); + Result SetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet supported_style_set); + Result GetSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const; + Result GetMaskedSupportedNpadStyleSet(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const; + Result SetSupportedNpadIdType(Kernel::KernelCore& kernel, u64 aruid, std::span supported_npad_list); Result SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type); Result GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const; - Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode); - Result GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const; + Result SetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode mode); + Result GetNpadHandheldActivationMode(Kernel::KernelCore& kernel, u64 aruid, NpadHandheldActivationMode& out_mode) const; - bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, + bool SetNpadMode(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); - Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, + Result AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id); // Adds a new controller at an index. - void AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, - Core::HID::NpadIdType npad_id); + void AddNewControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id); // Adds a new controller at an index with connection status. - void UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller, - Core::HID::NpadIdType npad_id, bool connected); + void UpdateControllerAt(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, bool connected); - Result DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id); + Result DisconnectNpad(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); Result IsFirmwareUpdateAvailableForSixAxisSensor( u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle, @@ -110,20 +107,18 @@ public: void ConnectAllDisconnectedControllers(); void ClearAllControllers(); - Result MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2); + Result MergeSingleJoyAsDualJoy(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); Result StartLrAssignmentMode(u64 aruid); Result StopLrAssignmentMode(u64 aruid); - Result SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1, - Core::HID::NpadIdType npad_id_2); + Result SwapNpadAssignment(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); // Logical OR for all buttons presses on all controllers // Specifically for cheat engine and other features. Core::HID::NpadButton GetAndResetPressState(); - Result ApplyNpadSystemCommonPolicy(u64 aruid); - Result ApplyNpadSystemCommonPolicyFull(u64 aruid); - Result ClearNpadSystemCommonPolicy(u64 aruid); + Result ApplyNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid); + Result ApplyNpadSystemCommonPolicyFull(Kernel::KernelCore& kernel, u64 aruid); + Result ClearNpadSystemCommonPolicy(Kernel::KernelCore& kernel, u64 aruid); void SetRevision(u64 aruid, NpadRevision revision); NpadRevision GetRevision(u64 aruid); @@ -180,9 +175,9 @@ private: int callback_key{}; }; - void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); - void InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id); - void RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id); + void ControllerUpdate(Kernel::KernelCore& kernel, Core::HID::ControllerTriggerType type, std::size_t controller_idx); + void InitNewlyAddedController(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); + void RequestPadStateUpdate(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); void WriteEmptyEntry(NpadInternalState* npad); NpadControllerData& GetControllerFromHandle( @@ -209,7 +204,6 @@ private: NpadVibration vibration_handler{}; std::atomic press_state{}; - std::array, AruidIndexMax> - controller_data{}; + std::array, AruidIndexMax> controller_data{}; }; } // namespace Service::HID diff --git a/src/hid_core/resources/npad/npad_resource.cpp b/src/hid_core/resources/npad/npad_resource.cpp index 08546f8dc4..54f7acab12 100644 --- a/src/hid_core/resources/npad/npad_resource.cpp +++ b/src/hid_core/resources/npad/npad_resource.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -13,7 +13,9 @@ namespace Service::HID { -NPadResource::NPadResource(KernelHelpers::ServiceContext& context) : service_context{context} {} +NPadResource::NPadResource(Kernel::KernelCore& kernel_, KernelHelpers::ServiceContext& context) + : service_context{context} +{} NPadResource::~NPadResource() = default; @@ -505,9 +507,7 @@ Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 a return ResultSuccess; } -Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, - Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id) { +Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id) { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; @@ -526,26 +526,25 @@ Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, *out_event = &controller_state.style_set_update_event->GetReadableEvent(); if (controller_state.is_styleset_update_event_initialized) { - controller_state.style_set_update_event->Signal(); + controller_state.style_set_update_event->Signal(kernel); } return ResultSuccess; } -Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) { +Result NPadResource::SignalStyleSetUpdateEvent(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id) { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; } - auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; - if (controller.is_styleset_update_event_initialized) { - controller.style_set_update_event->Signal(); + auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)]; + if (controller_state.is_styleset_update_event_initialized) { + controller_state.style_set_update_event->Signal(kernel); } return ResultSuccess; } -Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const { +Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, Core::HID::NpadIdType npad_id) const { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; @@ -555,8 +554,7 @@ Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, return ResultSuccess; } -Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, - bool is_enabled) { +Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled) { const u64 aruid_index = GetIndexFromAruid(aruid); if (aruid_index >= AruidIndexMax) { return ResultNpadNotConnected; diff --git a/src/hid_core/resources/npad/npad_resource.h b/src/hid_core/resources/npad/npad_resource.h index 8ee5702fd4..2d381c4642 100644 --- a/src/hid_core/resources/npad/npad_resource.h +++ b/src/hid_core/resources/npad/npad_resource.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -20,6 +23,7 @@ class System; } namespace Kernel { +class KernelCore; class KReadableEvent; } @@ -37,8 +41,7 @@ struct NpadState { DataStatusFlag flag{}; u64 aruid{}; NPadData data{}; - std::array, MaxSupportedNpadIdTypes> - button_config; + std::array, MaxSupportedNpadIdTypes> button_config; std::array controller_state; NpadRevision npad_revision; }; @@ -46,7 +49,7 @@ struct NpadState { /// Handles Npad request from HID interfaces class NPadResource final { public: - explicit NPadResource(KernelHelpers::ServiceContext& context); + explicit NPadResource(Kernel::KernelCore& kernel, KernelHelpers::ServiceContext& context); ~NPadResource(); NPadData* GetActiveData(); @@ -81,11 +84,9 @@ public: Result GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const; Result SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode activation_mode); - Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, - u64 aruid) const; + Result GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode, u64 aruid) const; - Result SetSupportedNpadIdType(u64 aruid, - std::span supported_npad_list); + Result SetSupportedNpadIdType(u64 aruid, std::span supported_npad_list); bool IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const; Result SetLrAssignmentMode(u64 aruid, bool is_enabled); @@ -94,28 +95,20 @@ public: Result SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled); Result IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const; - Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, - Core::HID::NpadIdType npad_id); - Result SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id); - - Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, - Core::HID::NpadIdType npad_id) const; + Result AcquireNpadStyleSetUpdateEventHandle(Kernel::KernelCore& kernel, u64 aruid, Kernel::KReadableEvent** out_event, Core::HID::NpadIdType npad_id); + Result SignalStyleSetUpdateEvent(Kernel::KernelCore& kernel, u64 aruid, Core::HID::NpadIdType npad_id); + Result GetHomeProtectionEnabled(bool& is_enabled, u64 aruid, Core::HID::NpadIdType npad_id) const; Result SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id, bool is_enabled); Result SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled); - Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, - Core::HID::NpadButton button_config); - Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, - std::size_t index, Core::HID::NpadButton mask, - bool is_enabled); + Result SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, Core::HID::NpadButton button_config); + Core::HID::NpadButton GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index, Core::HID::NpadButton mask, bool is_enabled); void ResetButtonConfig(); - Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, - Core::HID::NpadButton button_assignment); + Result SetNpadCaptureButtonAssignment(u64 aruid, Core::HID::NpadStyleSet npad_style_set, Core::HID::NpadButton button_assignment); Result ClearNpadCaptureButtonAssignment(u64 aruid); - std::size_t GetNpadCaptureButtonAssignment(std::span out_list, - u64 aruid) const; + std::size_t GetNpadCaptureButtonAssignment(std::span out_list, u64 aruid) const; Result SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled); @@ -124,9 +117,8 @@ private: AruidRegisterList registration_list{}; std::array state{}; u64 active_data_aruid{}; + KernelHelpers::ServiceContext& service_context; NpadJoyHoldType default_hold_type{}; s32 ref_counter{}; - - KernelHelpers::ServiceContext& service_context; }; } // namespace Service::HID diff --git a/src/hid_core/resources/palma/palma.cpp b/src/hid_core/resources/palma/palma.cpp index 0652455f5f..1a1a3aae18 100644 --- a/src/hid_core/resources/palma/palma.cpp +++ b/src/hid_core/resources/palma/palma.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -77,7 +77,7 @@ Result Palma::PlayPalmaActivity(const PalmaConnectionHandle& handle, u64 palma_a operation.operation = PackedPalmaOperationType::PlayActivity; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -96,7 +96,7 @@ Result Palma::ReadPalmaStep(const PalmaConnectionHandle& handle) { operation.operation = PackedPalmaOperationType::ReadStep; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -125,7 +125,7 @@ Result Palma::ReadPalmaUniqueCode(const PalmaConnectionHandle& handle) { operation.operation = PackedPalmaOperationType::ReadUniqueCode; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -136,7 +136,7 @@ Result Palma::SetPalmaUniqueCodeInvalid(const PalmaConnectionHandle& handle) { operation.operation = PackedPalmaOperationType::SetUniqueCodeInvalid; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -149,7 +149,7 @@ Result Palma::WritePalmaRgbLedPatternEntry(const PalmaConnectionHandle& handle, operation.operation = PackedPalmaOperationType::WriteRgbLedPatternEntry; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -161,7 +161,7 @@ Result Palma::WritePalmaWaveEntry(const PalmaConnectionHandle& handle, PalmaWave operation.operation = PackedPalmaOperationType::WriteWaveEntry; operation.result = PalmaResultSuccess; operation.data = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -174,7 +174,7 @@ Result Palma::SetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& operation.operation = PackedPalmaOperationType::ReadDataBaseIdentificationVersion; operation.result = PalmaResultSuccess; operation.data[0] = {}; - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } @@ -186,7 +186,7 @@ Result Palma::GetPalmaDataBaseIdentificationVersion(const PalmaConnectionHandle& operation.result = PalmaResultSuccess; operation.data = {}; operation.data[0] = static_cast(database_id_version); - operation_complete_event->Signal(); + operation_complete_event->Signal(hid_core.kernel); return ResultSuccess; } diff --git a/src/hid_core/resources/shared_memory_holder.cpp b/src/hid_core/resources/shared_memory_holder.cpp index ada593d8ba..c94829821a 100644 --- a/src/hid_core/resources/shared_memory_holder.cpp +++ b/src/hid_core/resources/shared_memory_holder.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -9,17 +12,10 @@ #include "hid_core/resources/shared_memory_holder.h" namespace Service::HID { -SharedMemoryHolder::SharedMemoryHolder() {} - -SharedMemoryHolder::~SharedMemoryHolder() { - Finalize(); -} Result SharedMemoryHolder::Initialize(Core::System& system) { shared_memory = Kernel::KSharedMemory::Create(system.Kernel()); - const Result result = shared_memory->Initialize( - system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, - Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); + const Result result = shared_memory->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, Kernel::Svc::MemoryPermission::None, Kernel::Svc::MemoryPermission::Read, sizeof(SharedMemoryFormat)); if (result.IsError()) { return result; } @@ -31,9 +27,9 @@ Result SharedMemoryHolder::Initialize(Core::System& system) { return ResultSuccess; } -void SharedMemoryHolder::Finalize() { +void SharedMemoryHolder::Finalize(Core::System& system) { if (address != nullptr) { - shared_memory->Close(); + shared_memory->Close(system.Kernel()); } is_created = false; is_mapped = false; diff --git a/src/hid_core/resources/shared_memory_holder.h b/src/hid_core/resources/shared_memory_holder.h index 943407c00a..5fcaddecc0 100644 --- a/src/hid_core/resources/shared_memory_holder.h +++ b/src/hid_core/resources/shared_memory_holder.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -19,17 +22,13 @@ struct SharedMemoryFormat; // This is nn::hid::detail::SharedMemoryHolder class SharedMemoryHolder { public: - SharedMemoryHolder(); - ~SharedMemoryHolder(); - Result Initialize(Core::System& system); - void Finalize(); + void Finalize(Core::System& system); bool IsMapped(); SharedMemoryFormat* GetAddress(); Kernel::KSharedMemory* GetHandle(); -private: bool is_owner{}; bool is_created{}; bool is_mapped{}; diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp index 018a43b6c0..d340f186b3 100644 --- a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp +++ b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp @@ -494,7 +494,7 @@ void TouchResource::ReadTouchInput() { has_moved |= (delta_x > 1 || delta_y > 1); } if (has_moved) { - input_event->Signal(); + input_event->Signal(system.Kernel()); } } } diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 7566e6040c..620e0cf630 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -13,6 +13,7 @@ #include "common/param_package.h" #include "common/random.h" #include "common/settings.h" +#include "common/thread.h" #include "input_common/drivers/udp_client.h" #include "input_common/helpers/udp_protocol.h" @@ -133,6 +134,7 @@ private: }; static void SocketLoop(Socket* socket) { + Common::SetCurrentThreadName("cemuhookWorker"); socket->StartReceive(); socket->StartSend(Socket::clock::now()); socket->Loop(); @@ -328,9 +330,11 @@ void UDPClient::OnPadData(Response::PadData data, std::size_t client) { } void UDPClient::StartCommunication(std::size_t client, const std::string& host, u16 port) { - SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, - [this](Response::PortInfo info) { OnPortInfo(info); }, - [this, client](Response::PadData data) { OnPadData(data, client); }}; + SocketCallback callback{ + [this](Response::Version version) { OnVersion(version); }, + [this](Response::PortInfo info) { OnPortInfo(info); }, + [this, client](Response::PadData data) { OnPadData(data, client); } + }; LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port); clients[client].uuid = GetHostUUID(host); clients[client].host = host; @@ -573,9 +577,7 @@ bool UDPClient::IsStickInverted(const Common::ParamPackage& params) { return true; } -void TestCommunication(const std::string& host, u16 port, - const std::function& success_callback, - const std::function& failure_callback) { +void TestCommunication(const std::string& host, u16 port, const std::function& success_callback, const std::function& failure_callback) { std::thread([=] { Common::Event success_event; SocketCallback callback{ @@ -608,40 +610,38 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( u16 max_y{}; Status current_status{Status::Initialized}; - SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, - [&](Response::PadData data) { - constexpr u16 CALIBRATION_THRESHOLD = 100; + SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, [&](Response::PadData data) { + constexpr u16 CALIBRATION_THRESHOLD = 100; - if (current_status == Status::Initialized) { - // Receiving data means the communication is ready now - current_status = Status::Ready; - status_callback(current_status); - } - if (data.touch[0].is_active == 0) { - return; - } - LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, - data.touch[0].y); - min_x = (std::min)(min_x, static_cast(data.touch[0].x)); - min_y = (std::min)(min_y, static_cast(data.touch[0].y)); - if (current_status == Status::Ready) { - // First touch - min data (min_x/min_y) - current_status = Status::Stage1Completed; - status_callback(current_status); - } - if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && - data.touch[0].y - min_y > CALIBRATION_THRESHOLD) { - // Set the current position as max value and finishes - // configuration - max_x = data.touch[0].x; - max_y = data.touch[0].y; - current_status = Status::Completed; - data_callback(min_x, min_y, max_x, max_y); - status_callback(current_status); + if (current_status == Status::Initialized) { + // Receiving data means the communication is ready now + current_status = Status::Ready; + status_callback(current_status); + } + if (data.touch[0].is_active == 0) { + return; + } + LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, data.touch[0].y); + min_x = (std::min)(min_x, u16(data.touch[0].x)); + min_y = (std::min)(min_y, u16(data.touch[0].y)); + if (current_status == Status::Ready) { + // First touch - min data (min_x/min_y) + current_status = Status::Stage1Completed; + status_callback(current_status); + } + if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && + data.touch[0].y - min_y > CALIBRATION_THRESHOLD) { + // Set the current position as max value and finishes + // configuration + max_x = data.touch[0].x; + max_y = data.touch[0].y; + current_status = Status::Completed; + data_callback(min_x, min_y, max_x, max_y); + status_callback(current_status); - complete_event.Set(); - } - }}; + complete_event.Set(); + } + }}; Socket socket{host, port, std::move(callback)}; std::thread worker_thread{SocketLoop, &socket}; complete_event.Wait(); diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 53b0d1638b..5c02b5ed90 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -334,7 +334,7 @@ if (YUZU_USE_EXTERNAL_FFMPEG) add_dependencies(video_core ffmpeg-build) endif() -target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR}) +target_include_directories(video_core PUBLIC ${FFmpeg_INCLUDE_DIR}) target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES}) target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp index 1f0f8b5a38..635ca769d8 100644 --- a/src/video_core/cdma_pusher.cpp +++ b/src/video_core/cdma_pusher.cpp @@ -20,8 +20,7 @@ namespace Tegra { CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_, s32 id) - : host_processor(host1x_) - , host1x{host1x_} + : host1x{host1x_} , current_class{ChClassId(id)} { thread = std::jthread([this](std::stop_token stop_token) { @@ -99,7 +98,7 @@ void CDmaPusher::ExecuteCommand(u32 method, u32 arg) { switch (current_class) { case ChClassId::Control: LOG_TRACE(Service_NVDRV, "Class {} method {:#X} arg 0x{:X}", u32(current_class), method, arg); - host_processor.ProcessMethod(Host1x::Control::Method(method), arg); + host_processor.ProcessMethod(host1x, Host1x::Control::Method(method), arg); break; default: thi_regs.reg_array[method] = arg; diff --git a/src/video_core/control/channel_state.cpp b/src/video_core/control/channel_state.cpp index d07c7e2a83..c6f2c3c2ca 100644 --- a/src/video_core/control/channel_state.cpp +++ b/src/video_core/control/channel_state.cpp @@ -17,28 +17,36 @@ namespace Tegra::Control { -ChannelState::ChannelState(s32 bind_id_) : bind_id{bind_id_}, initialized{} {} +ChannelState::Payload::Payload(Core::System& system, MemoryManager& memory_manager, ChannelState& channel_state) + : maxwell_3d(memory_manager) + , fermi_2d(memory_manager) + , kepler_compute(memory_manager) + , maxwell_dma(memory_manager) + , kepler_memory(memory_manager) + , nv01_timer(memory_manager) + , dma_pusher(system, memory_manager, channel_state) +{} -void ChannelState::Init(Core::System& system, GPU& gpu, u64 program_id_) { +ChannelState::ChannelState(s32 bind_id_) + : bind_id{bind_id_} +{} + +void ChannelState::Init(Core::System& system, u64 program_id_) { ASSERT(memory_manager); program_id = program_id_; - dma_pusher.emplace(system, gpu, *memory_manager, *this); - maxwell_3d.emplace(system, *memory_manager); - fermi_2d.emplace(*memory_manager); - kepler_compute.emplace(system, *memory_manager); - maxwell_dma.emplace(system, *memory_manager); - kepler_memory.emplace(system, *memory_manager); + payload.emplace(system, *memory_manager, *this); initialized = true; } void ChannelState::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) { - dma_pusher->BindRasterizer(rasterizer); + payload->dma_pusher.BindRasterizer(rasterizer); memory_manager->BindRasterizer(rasterizer); - maxwell_3d->BindRasterizer(rasterizer); - fermi_2d->BindRasterizer(rasterizer); - kepler_memory->BindRasterizer(rasterizer); - kepler_compute->BindRasterizer(rasterizer); - maxwell_dma->BindRasterizer(rasterizer); + payload->maxwell_3d.BindRasterizer(rasterizer); + payload->fermi_2d.BindRasterizer(rasterizer); + payload->kepler_memory.BindRasterizer(rasterizer); + payload->kepler_compute.BindRasterizer(rasterizer); + payload->maxwell_dma.BindRasterizer(rasterizer); + //payload->nv01_timer.BindRasterizer(rasterizer); } } // namespace Tegra::Control diff --git a/src/video_core/control/channel_state.h b/src/video_core/control/channel_state.h index 2984d2e09e..80811c1458 100644 --- a/src/video_core/control/channel_state.h +++ b/src/video_core/control/channel_state.h @@ -14,6 +14,7 @@ #include "video_core/engines/kepler_compute.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_dma.h" +#include "video_core/engines/nv01_timer.h" #include "video_core/dma_pusher.h" namespace Core { @@ -34,28 +35,33 @@ namespace Control { struct ChannelState { explicit ChannelState(s32 bind_id); - void Init(Core::System& system, GPU& gpu, u64 program_id); + void Init(Core::System& system, u64 program_id); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); - /// 3D engine - std::optional maxwell_3d; - /// 2D engine - std::optional fermi_2d; - /// Compute engine - std::optional kepler_compute; - /// DMA engine - std::optional maxwell_dma; - /// Inline memory engine - std::optional kepler_memory; - /// NV01 Timer - std::optional nv01_timer; - std::optional dma_pusher; - std::shared_ptr memory_manager; + struct Payload { + explicit Payload(Core::System& system, MemoryManager& memory_manager, ChannelState& channel_state); + + /// 3D engine + Engines::Maxwell3D maxwell_3d; + /// 2D engine + Engines::Fermi2D fermi_2d; + /// Compute engine + Engines::KeplerCompute kepler_compute; + /// DMA engine + Engines::MaxwellDMA maxwell_dma; + /// Inline memory engine + Engines::KeplerMemory kepler_memory; + /// NV01 Timer + Engines::Nv01Timer nv01_timer; + DmaPusher dma_pusher; + }; + std::optional payload; + MemoryManager* memory_manager = nullptr; s32 bind_id = -1; u64 program_id = 0; - bool initialized{}; + bool initialized = false; }; } // namespace Control diff --git a/src/video_core/control/channel_state_cache.cpp b/src/video_core/control/channel_state_cache.cpp index f8c6a762d2..bd794d939a 100644 --- a/src/video_core/control/channel_state_cache.cpp +++ b/src/video_core/control/channel_state_cache.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -6,8 +9,11 @@ namespace VideoCommon { ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) - : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, - gpu_memory{*channel_state.memory_manager}, program_id{channel_state.program_id} {} + : maxwell3d{channel_state.payload->maxwell_3d} + , kepler_compute{channel_state.payload->kepler_compute} + , gpu_memory{*channel_state.memory_manager} + , program_id{channel_state.program_id} + {} template class VideoCommon::ChannelSetupCaches; diff --git a/src/video_core/control/channel_state_cache.inc b/src/video_core/control/channel_state_cache.inc index d882d8222f..5bb15f8907 100644 --- a/src/video_core/control/channel_state_cache.inc +++ b/src/video_core/control/channel_state_cache.inc @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -41,7 +44,7 @@ void ChannelSetupCaches

::CreateChannel(struct Tegra::Control::ChannelState& c AddressSpaceRef new_gpu_mem_ref{ .ref_count = 1, .storage_id = address_spaces.size(), - .gpu_memory = channel.memory_manager.get(), + .gpu_memory = channel.memory_manager, }; address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref); OnGPUASRegister(channel.memory_manager->GetID()); diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp index bd3b8b860e..8af13e415c 100644 --- a/src/video_core/control/scheduler.cpp +++ b/src/video_core/control/scheduler.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2021 yuzu Emulator Project @@ -12,11 +12,8 @@ #include "video_core/gpu.h" namespace Tegra::Control { -Scheduler::Scheduler(GPU& gpu_) : gpu{gpu_} {} -Scheduler::~Scheduler() = default; - -void Scheduler::Push(s32 channel, CommandList&& entries) { +void Scheduler::Push(GPU& gpu, s32 channel, CommandList&& entries) { std::shared_ptr channel_state; { std::unique_lock lk(scheduling_guard); @@ -27,8 +24,8 @@ void Scheduler::Push(s32 channel, CommandList&& entries) { } // Process commands outside the lock to reduce contention. // Multiple channels can prepare their commands in parallel. - channel_state->dma_pusher->Push(std::move(entries)); - channel_state->dma_pusher->DispatchCalls(); + channel_state->payload->dma_pusher.Push(std::move(entries)); + channel_state->payload->dma_pusher.DispatchCalls(); } void Scheduler::DeclareChannel(std::shared_ptr new_channel) { diff --git a/src/video_core/control/scheduler.h b/src/video_core/control/scheduler.h index 9c2b9de32b..fb9c583386 100644 --- a/src/video_core/control/scheduler.h +++ b/src/video_core/control/scheduler.h @@ -22,17 +22,13 @@ struct ChannelState; class Scheduler { public: - explicit Scheduler(GPU& gpu_); - ~Scheduler(); - - void Push(s32 channel, CommandList&& entries); + void Push(GPU& gpu, s32 channel, CommandList&& entries); void DeclareChannel(std::shared_ptr new_channel); private: ankerl::unordered_dense::map> channels; std::mutex scheduling_guard; - GPU& gpu; }; } // namespace Control diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 8a7798e035..41bb43f0c1 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -12,37 +12,32 @@ #include "video_core/guest_memory.h" #include "video_core/memory_manager.h" #include "video_core/rasterizer_interface.h" -#include "video_core/texture_cache/util.h" - -#ifdef _MSC_VER -#include -#endif namespace Tegra { constexpr u32 MacroRegistersStart = 0xE00; [[maybe_unused]] constexpr u32 ComputeInline = 0x6D; -DmaPusher::DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_, - Control::ChannelState& channel_state_) - : gpu{gpu_}, system{system_}, memory_manager{memory_manager_}, puller{gpu_, memory_manager_, - *this, channel_state_}, signal_sync{false}, synced{true} {} +DmaPusher::DmaPusher(Core::System& system_, MemoryManager& memory_manager_, Control::ChannelState& channel_state_) + : system{system_} + , memory_manager{memory_manager_} + , channel_state{channel_state_} + , signal_sync{false} + , synced{false} +{} DmaPusher::~DmaPusher() = default; void DmaPusher::DispatchCalls() { - dma_pushbuffer_subindex = 0; - dma_state.is_last_call = true; - while (system.IsPoweredOn()) { if (!Step()) { break; } } - gpu.FlushCommands(); - gpu.OnCommandListEnd(); + system.GPU().FlushCommands(); + system.GPU().OnCommandListEnd(); } bool DmaPusher::Step() { @@ -171,9 +166,9 @@ void DmaPusher::SetState(const CommandHeader& command_header) { dma_state.method_count = command_header.method_count; } -void DmaPusher::CallMethod(u32 argument) const { +void DmaPusher::CallMethod(u32 argument) { if (dma_state.method < non_puller_methods) { - puller.CallPullerMethod(Engines::Puller::MethodCall{ + puller.CallPullerMethod(*this, Engines::Puller::MethodCall{ dma_state.method, argument, dma_state.subchannel, @@ -181,30 +176,29 @@ void DmaPusher::CallMethod(u32 argument) const { }); } else { auto subchannel = subchannels[dma_state.subchannel]; - if (subchannel->execution_mask[dma_state.method]) { - subchannel->ConsumeSink(); - subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; - subchannel->CallMethod(dma_state.method, argument, dma_state.is_last_call); - } else { + if (!subchannel->execution_mask[dma_state.method]) { subchannel->method_sink.emplace_back(dma_state.method, argument); + } else { + subchannel->ConsumeSink(system); + subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; + subchannel->CallMethod(system, dma_state.method, argument, dma_state.is_last_call); } } } -void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) const { +void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) { if (dma_state.method < non_puller_methods) { - puller.CallMultiMethod(dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count); + puller.CallMultiMethod(*this, dma_state.method, dma_state.subchannel, base_start, num_methods, dma_state.method_count); } else { auto subchannel = subchannels[dma_state.subchannel]; - subchannel->ConsumeSink(); + subchannel->ConsumeSink(system); subchannel->current_dma_segment = dma_state.dma_get + dma_state.dma_word_offset; - subchannel->CallMultiMethod(dma_state.method, base_start, num_methods, dma_state.method_count); + subchannel->CallMultiMethod(system, dma_state.method, base_start, num_methods, dma_state.method_count); } } void DmaPusher::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { rasterizer = rasterizer_; - puller.BindRasterizer(rasterizer); } } // namespace Tegra diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h index f850513603..62af628511 100644 --- a/src/video_core/dma_pusher.h +++ b/src/video_core/dma_pusher.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -109,25 +109,21 @@ inline CommandHeader BuildCommandHeader(BufferMethods method, u32 arg_count, Sub struct CommandList final { CommandList() = default; explicit CommandList(std::size_t size) : command_lists(size) {} - explicit CommandList( - boost::container::small_vector&& prefetch_command_list_) + explicit CommandList(boost::container::small_vector&& prefetch_command_list_) : prefetch_command_list{std::move(prefetch_command_list_)} {} boost::container::small_vector command_lists; boost::container::small_vector prefetch_command_list; }; -/** - * The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the - * emulated app fills with commands and tells PFIFO to process. The pushbuffers are then assembled - * into a "command stream" consisting of 32-bit words that make up "commands". - * See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for - * details on this implementation. - */ +/// @brief The DmaPusher class implements DMA submission to FIFOs, providing an area of memory that the +/// emulated app fills with commands and tells PFIFO to process. The pushbuffers are then assembled +/// into a "command stream" consisting of 32-bit words that make up "commands". +/// See https://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html#fifo-dma-pusher for +/// details on this implementation. class DmaPusher final { public: - explicit DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_, - Control::ChannelState& channel_state_); + explicit DmaPusher(Core::System& system_, MemoryManager& memory_manager_, Control::ChannelState& channel_state_); ~DmaPusher(); void Push(CommandList&& entries) { @@ -136,8 +132,7 @@ public: void DispatchCalls(); - void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id, - Engines::EngineTypes engine_type) { + void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id, Engines::EngineTypes engine_type) { subchannels[subchannel_id] = engine; subchannel_type[subchannel_id] = engine_type; } @@ -152,11 +147,11 @@ private: void SetState(const CommandHeader& command_header); - void CallMethod(u32 argument) const; - void CallMultiMethod(const u32* base_start, u32 num_methods) const; + void CallMethod(u32 argument); + void CallMultiMethod(const u32* base_start, u32 num_methods); - Common::ScratchBuffer - command_headers; ///< Buffer for list of commands fetched at once +public: + Common::ScratchBuffer command_headers; ///< Buffer for list of commands fetched at once std::queue dma_pushbuffer; ///< Queue of command lists to be processed std::size_t dma_pushbuffer_subindex{}; ///< Index within a command list within the pushbuffer @@ -172,24 +167,24 @@ private: bool is_last_call; }; + Core::System& system; + MemoryManager& memory_manager; + Control::ChannelState& channel_state; + DmaState dma_state{}; - bool dma_increment_once{}; - - const bool ib_enable{true}; ///< IB mode enabled - std::array subchannels{}; std::array subchannel_type; - GPU& gpu; - Core::System& system; - MemoryManager& memory_manager; - mutable Engines::Puller puller; - - VideoCore::RasterizerInterface* rasterizer; - bool signal_sync; - bool synced; + Engines::Puller puller; std::mutex sync_mutex; std::condition_variable sync_cv; + + VideoCore::RasterizerInterface* rasterizer = nullptr; + + const bool ib_enable : 1 = true; ///< IB mode enabled + bool dma_increment_once : 1 = false; + bool signal_sync : 1 = false; + bool synced : 1 = false; }; } // namespace Tegra diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h index bf3bd66aca..83dbf13059 100644 --- a/src/video_core/engines/engine_interface.h +++ b/src/video_core/engines/engine_interface.h @@ -12,6 +12,10 @@ #include "common/common_types.h" +namespace Core { +class System; +} + namespace Tegra::Engines { enum class EngineTypes : u32 { @@ -28,28 +32,25 @@ public: virtual ~EngineInterface() = default; /// Write the value to the register identified by method. - virtual void CallMethod(u32 method, u32 method_argument, bool is_last_call) = 0; + virtual void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) = 0; /// Write multiple values to the register identified by method. - virtual void CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) = 0; + virtual void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) = 0; - void ConsumeSink() { - if (method_sink.empty()) { - return; + void ConsumeSink(Core::System& system) { + if (!method_sink.empty()) { + ConsumeSinkImpl(system); } - ConsumeSinkImpl(); } std::bitset<(std::numeric_limits::max)()> execution_mask{}; std::vector> method_sink{}; - bool current_dirty{}; GPUVAddr current_dma_segment; - + bool current_dirty{}; protected: - virtual void ConsumeSinkImpl() { + virtual void ConsumeSinkImpl(Core::System& system) { for (auto [method, value] : method_sink) { - CallMethod(method, value, true); + CallMethod(system, method, value, true); } method_sink.clear(); } diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index b442c5cc76..8b02c91e03 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -36,9 +36,8 @@ void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { rasterizer = rasterizer_; } -void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { - ASSERT_MSG(method < Regs::NUM_REGS, - "Invalid Fermi2D register, increase the size of the Regs structure"); +void Fermi2D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { + ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Fermi2D register, increase the size of the Regs structure"); regs.reg_array[method] = method_argument; if (method == FERMI2D_REG_INDEX(pixels_from_memory.src_y0) + 1) { @@ -46,13 +45,13 @@ void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { } } -void Fermi2D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, u32 methods_pending) { +void Fermi2D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { for (u32 i = 0; i < amount; ++i) { - CallMethod(method, base_start[i], methods_pending - i <= 1); + CallMethod(system, method, base_start[i], methods_pending - i <= 1); } } -void Fermi2D::ConsumeSinkImpl() { +void Fermi2D::ConsumeSinkImpl(Core::System& system) { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } @@ -60,8 +59,7 @@ void Fermi2D::ConsumeSinkImpl() { } void Fermi2D::Blit() { - LOG_DEBUG(HW_GPU, "called. source address=0x{:x}, destination address=0x{:x}", - regs.src.Address(), regs.dst.Address()); + LOG_DEBUG(HW_GPU, "called. source address=0x{:x}, destination address=0x{:x}", regs.src.Address(), regs.dst.Address()); UNIMPLEMENTED_IF_MSG(regs.operation != Operation::SrcCopy, "Operation is not copy"); UNIMPLEMENTED_IF_MSG(regs.src.layer != 0, "Source layer is not zero"); diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 705b323e15..7fddf9fdc1 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -44,11 +47,10 @@ public: void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); /// Write the value to the register identified by method. - void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) override; + void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; enum class Origin : u32 { Center = 0, @@ -311,7 +313,7 @@ private: /// registers. void Blit(); - void ConsumeSinkImpl() override; + void ConsumeSinkImpl(Core::System& system) override; }; #define ASSERT_REG_POSITION(field_name, position) \ diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index 7b4efeb1e0..1ef6e0fc0d 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp @@ -16,8 +16,10 @@ namespace Tegra::Engines { -KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_) - : system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} { +KeplerCompute::KeplerCompute(MemoryManager& memory_manager_) + : memory_manager{memory_manager_} + , upload_state{memory_manager, regs.upload} +{ execution_mask.reset(); execution_mask[KEPLER_COMPUTE_REG_INDEX(exec_upload)] = true; execution_mask[KEPLER_COMPUTE_REG_INDEX(data_upload)] = true; @@ -31,16 +33,15 @@ void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) upload_state.BindRasterizer(rasterizer); } -void KeplerCompute::ConsumeSinkImpl() { +void KeplerCompute::ConsumeSinkImpl(Core::System& system) { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } method_sink.clear(); } -void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { - ASSERT_MSG(method < Regs::NUM_REGS, - "Invalid KeplerCompute register, increase the size of the Regs structure"); +void KeplerCompute::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { + ASSERT_MSG(method < Regs::NUM_REGS, "Invalid KeplerCompute register, increase the size of the Regs structure"); regs.reg_array[method] = method_argument; @@ -78,8 +79,7 @@ void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_cal } } -void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) { +void KeplerCompute::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { switch (method) { case KEPLER_COMPUTE_REG_INDEX(data_upload): upload_address = current_dma_segment; @@ -87,7 +87,7 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun return; default: for (u32 i = 0; i < amount; i++) { - CallMethod(method, base_start[i], methods_pending - i <= 1); + CallMethod(system, method, base_start[i], methods_pending - i <= 1); } break; } diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index 735e05fb43..4f7242f804 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -42,7 +45,7 @@ namespace Tegra::Engines { class KeplerCompute final : public EngineInterface { public: - explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager); + explicit KeplerCompute(MemoryManager& memory_manager); ~KeplerCompute(); /// Binds a rasterizer to this engine. @@ -199,11 +202,10 @@ public: "KeplerCompute LaunchParams has wrong size"); /// Write the value to the register identified by method. - void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) override; + void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; std::optional GetIndirectComputeAddress() const { return indirect_compute; @@ -212,7 +214,7 @@ public: private: void ProcessLaunch(); - void ConsumeSinkImpl() override; + void ConsumeSinkImpl(Core::System& system) override; /// Retrieves information about a specific TIC entry from the TIC buffer. Texture::TICEntry GetTICEntry(u32 tic_index) const; @@ -220,7 +222,6 @@ private: /// Retrieves information about a specific TSC entry from the TSC buffer. Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; - Core::System& system; MemoryManager& memory_manager; VideoCore::RasterizerInterface* rasterizer = nullptr; Upload::State upload_state; diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp index 5d4c4720d3..3af5f91271 100644 --- a/src/video_core/engines/kepler_memory.cpp +++ b/src/video_core/engines/kepler_memory.cpp @@ -14,8 +14,9 @@ namespace Tegra::Engines { -KeplerMemory::KeplerMemory(Core::System& system_, MemoryManager& memory_manager) - : system{system_}, upload_state{memory_manager, regs.upload} {} +KeplerMemory::KeplerMemory(MemoryManager& memory_manager) + : upload_state{memory_manager, regs.upload} +{} KeplerMemory::~KeplerMemory() = default; @@ -27,16 +28,15 @@ void KeplerMemory::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { execution_mask[KEPLERMEMORY_REG_INDEX(data)] = true; } -void KeplerMemory::ConsumeSinkImpl() { +void KeplerMemory::ConsumeSinkImpl(Core::System& system) { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } method_sink.clear(); } -void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call) { - ASSERT_MSG(method < Regs::NUM_REGS, - "Invalid KeplerMemory register, increase the size of the Regs structure"); +void KeplerMemory::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { + ASSERT_MSG(method < Regs::NUM_REGS, "Invalid KeplerMemory register, increase the size of the Regs structure"); regs.reg_array[method] = method_argument; @@ -52,15 +52,14 @@ void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call } } -void KeplerMemory::CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) { +void KeplerMemory::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { switch (method) { case KEPLERMEMORY_REG_INDEX(data): upload_state.ProcessData(base_start, amount); return; default: for (u32 i = 0; i < amount; i++) { - CallMethod(method, base_start[i], methods_pending - i <= 1); + CallMethod(system, method, base_start[i], methods_pending - i <= 1); } break; } diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h index fb1eecbba9..aa0952d17a 100644 --- a/src/video_core/engines/kepler_memory.h +++ b/src/video_core/engines/kepler_memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -36,18 +39,17 @@ namespace Tegra::Engines { class KeplerMemory final : public EngineInterface { public: - explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager); + explicit KeplerMemory(MemoryManager& memory_manager); ~KeplerMemory() override; /// Binds a rasterizer to this engine. void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); /// Write the value to the register identified by method. - void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) override; + void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; struct Regs { static constexpr size_t NUM_REGS = 0x7F; @@ -73,9 +75,7 @@ public: } regs{}; private: - void ConsumeSinkImpl() override; - - Core::System& system; + void ConsumeSinkImpl(Core::System& system) override; Upload::State upload_state; }; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 7cf351e458..3474ad6d63 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -25,9 +25,8 @@ namespace Tegra::Engines { /// First register id that is actually a Macro call. constexpr u32 MacroRegistersStart = 0xE00; -Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) +Maxwell3D::Maxwell3D(MemoryManager& memory_manager_) : draw_manager() - , system{system_} , memory_manager{memory_manager_} #ifdef ARCHITECTURE_x86_64 , macro_engine(bool(Settings::values.disable_macro_jit)) @@ -201,11 +200,10 @@ bool Maxwell3D::IsMethodExecutable(u32 method) { } } -void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { +void Maxwell3D::ProcessMacro(Core::System& system, u32 method, const u32* base_start, u32 amount, bool is_last_call) { if (executing_macro == 0) { // A macro call must begin by writing the macro method's register, not its argument. - ASSERT_MSG((method % 2) == 0, - "Can't start macro execution by writing to the ARGS register"); + ASSERT((method % 2) == 0 && "Can't start macro execution by writing to the ARGS register"); executing_macro = method; } @@ -219,8 +217,8 @@ void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool // Call the macro when there are no more parameters in the command buffer if (is_last_call) { - ConsumeSink(); - CallMacroMethod(executing_macro, macro_params); + ConsumeSink(system); + CallMacroMethod(system, executing_macro, macro_params); macro_params.clear(); macro_addresses.clear(); macro_segments.clear(); @@ -287,7 +285,7 @@ u32 Maxwell3D::ProcessShadowRam(u32 method, u32 argument) { return argument; } -void Maxwell3D::ConsumeSinkImpl() { +void Maxwell3D::ConsumeSinkImpl(Core::System& system) { const auto control = shadow_state.shadow_ram_control; if (control == Regs::ShadowRamControl::Track || control == Regs::ShadowRamControl::TrackWithFilter) { for (auto [method, value] : method_sink) { @@ -378,7 +376,7 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume } } -void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) { +void Maxwell3D::CallMacroMethod(Core::System& system, u32 method, const std::vector& parameters) { // Reset the current macro. executing_macro = 0; @@ -387,11 +385,11 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) ((method - MacroRegistersStart) >> 1) % static_cast(macro_positions.size()); // Execute the current macro. - macro_engine.Execute(*this, macro_positions[entry], parameters); + macro_engine.Execute(system, *this, macro_positions[entry], parameters); draw_manager.DrawDeferred(*this); } -void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { +void Maxwell3D::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { // It is an error to write to a register other than the current macro's ARG register before // it has finished execution. if (executing_macro != 0) { @@ -401,7 +399,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. if (method >= MacroRegistersStart) { - ProcessMacro(method, &method_argument, 1, is_last_call); + ProcessMacro(system, method, &method_argument, 1, is_last_call); return; } @@ -411,12 +409,11 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { ProcessMethodCall(method, argument, method_argument, is_last_call); } -void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) { +void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. if (method >= MacroRegistersStart) { - ProcessMacro(method, base_start, amount, amount == methods_pending); + ProcessMacro(system, method, base_start, amount, amount == methods_pending); return; } switch (method) { @@ -445,7 +442,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, } default: for (u32 i = 0; i < amount; i++) { - CallMethod(method, base_start[i], methods_pending - i <= 1); + CallMethod(system, method, base_start[i], methods_pending - i <= 1); } break; } @@ -467,7 +464,7 @@ void Maxwell3D::ProcessFirmwareCall4() { regs.shadow_scratch[0] = 1; } -void Maxwell3D::StampQueryResult(u64 payload, bool long_query) { +void Maxwell3D::StampQueryResult(Core::System& system, u64 payload, bool long_query) { const GPUVAddr sequence_address{regs.report_semaphore.Address()}; if (long_query) { memory_manager.Write(sequence_address + sizeof(u64), system.GPU().GetTicks()); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 864ee27fb6..823be0f63e 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -55,7 +55,7 @@ namespace Tegra::Engines { class Maxwell3D final : public EngineInterface { public: - explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager); + explicit Maxwell3D(MemoryManager& memory_manager); ~Maxwell3D(); /// Binds a rasterizer to this engine. @@ -3129,11 +3129,10 @@ public: u32 GetRegisterValue(u32 method) const; /// Write the value to the register identified by method. - void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) override; + void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; bool ShouldExecute() const { return execute_on; @@ -3190,13 +3189,13 @@ public: private: void InitializeRegisterDefaults(); - void ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call); + void ProcessMacro(Core::System& system, u32 method, const u32* base_start, u32 amount, bool is_last_call); u32 ProcessShadowRam(u32 method, u32 argument); void ProcessDirtyRegisters(u32 method, u32 argument); - void ConsumeSinkImpl() override; + void ConsumeSinkImpl(Core::System& system) override; void ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argument, bool is_last_call); @@ -3212,7 +3211,7 @@ private: * @param method Method to call * @param parameters Arguments to the method call */ - void CallMacroMethod(u32 method, const std::vector& parameters); + void CallMacroMethod(Core::System& system, u32 method, const std::vector& parameters); /// Handles writes to the macro uploading register. void ProcessMacroUpload(u32 data); @@ -3227,7 +3226,7 @@ private: void ProcessQueryGet(); /// Writes the query result accordingly. - void StampQueryResult(u64 payload, bool long_query); + void StampQueryResult(Core::System& system, u64 payload, bool long_query); /// Handles conditional rendering. void ProcessQueryCondition(); @@ -3242,7 +3241,6 @@ private: bool IsMethodExecutable(u32 method); - Core::System& system; MemoryManager& memory_manager; VideoCore::RasterizerInterface* rasterizer = nullptr; diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 089d118a09..a4090bc2ce 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -21,8 +21,9 @@ namespace Tegra::Engines { using namespace Texture; -MaxwellDMA::MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_) - : system{system_}, memory_manager{memory_manager_} { +MaxwellDMA::MaxwellDMA(MemoryManager& memory_manager_) + : memory_manager{memory_manager_} +{ execution_mask.reset(); execution_mask[offsetof(Regs, launch_dma) / sizeof(u32)] = true; } @@ -33,14 +34,14 @@ void MaxwellDMA::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { rasterizer = rasterizer_; } -void MaxwellDMA::ConsumeSinkImpl() { +void MaxwellDMA::ConsumeSinkImpl(Core::System& system) { for (auto [method, value] : method_sink) { regs.reg_array[method] = value; } method_sink.clear(); } -void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call) { +void MaxwellDMA::CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) { ASSERT_MSG(method < NUM_REGS, "Invalid MaxwellDMA register"); regs.reg_array[method] = method_argument; @@ -50,16 +51,14 @@ void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call) } } -void MaxwellDMA::CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) { +void MaxwellDMA::CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) { for (u32 i = 0; i < amount; ++i) { - CallMethod(method, base_start[i], methods_pending - i <= 1); + CallMethod(system, method, base_start[i], methods_pending - i <= 1); } } void MaxwellDMA::Launch() { - LOG_TRACE(Render_OpenGL, "DMA copy 0x{:x} -> 0x{:x}", static_cast(regs.offset_in), - static_cast(regs.offset_out)); + LOG_TRACE(Render_OpenGL, "DMA copy 0x{:x} -> 0x{:x}", static_cast(regs.offset_in), GPUVAddr(regs.offset_out)); // TODO(Subv): Perform more research and implement all features of this engine. const LaunchDMA& launch = regs.launch_dma; diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index 99341e431c..9cf2813d31 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -238,15 +241,14 @@ public: void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); - explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); + explicit MaxwellDMA(MemoryManager& memory_manager_); ~MaxwellDMA() override; /// Write the value to the register identified by method. - void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; + void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override; /// Write multiple values to the register identified by method. - void CallMultiMethod(u32 method, const u32* base_start, u32 amount, - u32 methods_pending) override; + void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override; private: /// Performs the copy from the source buffer to the destination buffer as configured in the @@ -261,9 +263,7 @@ private: void ReleaseSemaphore(); - void ConsumeSinkImpl() override; - - Core::System& system; + void ConsumeSinkImpl(Core::System& system) override; MemoryManager& memory_manager; VideoCore::RasterizerInterface* rasterizer = nullptr; diff --git a/src/video_core/engines/nv01_timer.h b/src/video_core/engines/nv01_timer.h index add9886f41..37c6668144 100644 --- a/src/video_core/engines/nv01_timer.h +++ b/src/video_core/engines/nv01_timer.h @@ -26,18 +26,16 @@ class MemoryManager; namespace Tegra::Engines { class Nv01Timer final : public EngineInterface { public: - explicit Nv01Timer(Core::System& system_, MemoryManager& memory_manager) - : system{system_} - {} - ~Nv01Timer() override; + explicit Nv01Timer(MemoryManager& memory_manager) noexcept {} + ~Nv01Timer() noexcept override {} /// Write the value to the register identified by method. - void CallMethod(u32 method, u32 method_argument, bool is_last_call) override { + void CallMethod(Core::System& system, u32 method, u32 method_argument, bool is_last_call) override { LOG_DEBUG(HW_GPU, "method={}, argument={}, is_last_call={}", method, method_argument, is_last_call); } /// Write multiple values to the register identified by method. - void CallMultiMethod(u32 method, const u32* base_start, u32 amount, u32 methods_pending) override { + void CallMultiMethod(Core::System& system, u32 method, const u32* base_start, u32 amount, u32 methods_pending) override { LOG_DEBUG(HW_GPU, "method={}, base_start={}, amount={}, pending={}", method, fmt::ptr(base_start), amount, methods_pending); } @@ -46,7 +44,6 @@ public: INSERT_PADDING_BYTES_NOINIT(0x48); } regs{}; private: - void ConsumeSinkImpl() override {} - Core::System& system; + void ConsumeSinkImpl(Core::System& system) override {} }; } diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index 4030f93d49..5816b5901a 100644 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp @@ -22,37 +22,29 @@ namespace Tegra::Engines { -Puller::Puller(GPU& gpu_, MemoryManager& memory_manager_, DmaPusher& dma_pusher_, - Control::ChannelState& channel_state_) - : gpu{gpu_}, memory_manager{memory_manager_}, dma_pusher{dma_pusher_}, channel_state{ - channel_state_} {} - -Puller::~Puller() = default; - -void Puller::ProcessBindMethod(const MethodCall& method_call) { +void Puller::ProcessBindMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { // Bind the current subchannel to the desired engine id. - LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel, - method_call.argument); + LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel, method_call.argument); const auto engine_id = static_cast(method_call.argument); bound_engines[method_call.subchannel] = engine_id; switch (engine_id) { case EngineID::FERMI_TWOD_A: - dma_pusher.BindSubchannel(&*channel_state.fermi_2d, method_call.subchannel, EngineTypes::Fermi2D); + dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->fermi_2d, method_call.subchannel, EngineTypes::Fermi2D); break; case EngineID::MAXWELL_B: - dma_pusher.BindSubchannel(&*channel_state.maxwell_3d, method_call.subchannel, EngineTypes::Maxwell3D); + dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->maxwell_3d, method_call.subchannel, EngineTypes::Maxwell3D); break; case EngineID::KEPLER_COMPUTE_B: - dma_pusher.BindSubchannel(&*channel_state.kepler_compute, method_call.subchannel, EngineTypes::KeplerCompute); + dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->kepler_compute, method_call.subchannel, EngineTypes::KeplerCompute); break; case EngineID::MAXWELL_DMA_COPY_A: - dma_pusher.BindSubchannel(&*channel_state.maxwell_dma, method_call.subchannel, EngineTypes::MaxwellDMA); + dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->maxwell_dma, method_call.subchannel, EngineTypes::MaxwellDMA); break; case EngineID::KEPLER_INLINE_TO_MEMORY_B: - dma_pusher.BindSubchannel(&*channel_state.kepler_memory, method_call.subchannel, EngineTypes::KeplerMemory); + dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->kepler_memory, method_call.subchannel, EngineTypes::KeplerMemory); break; case EngineID::NV01_TIMER: - dma_pusher.BindSubchannel(&*channel_state.nv01_timer, method_call.subchannel, EngineTypes::Nv01Timer); + dma_pusher.BindSubchannel(&dma_pusher.channel_state.payload->nv01_timer, method_call.subchannel, EngineTypes::Nv01Timer); break; default: UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id); @@ -60,15 +52,15 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) { } } -void Puller::ProcessFenceActionMethod() { +void Puller::ProcessFenceActionMethod(DmaPusher& dma_pusher) { switch (regs.fence_action.op) { case Puller::FenceOperation::Acquire: // UNIMPLEMENTED_MSG("Channel Scheduling pending."); // WaitFence(regs.fence_action.syncpoint_id, regs.fence_value); - rasterizer->ReleaseFences(); + dma_pusher.rasterizer->ReleaseFences(); break; case Puller::FenceOperation::Increment: - rasterizer->SignalSyncPoint(regs.fence_action.syncpoint_id); + dma_pusher.rasterizer->SignalSyncPoint(regs.fence_action.syncpoint_id); break; default: UNIMPLEMENTED_MSG("Unimplemented operation {}", regs.fence_action.op.Value()); @@ -76,37 +68,35 @@ void Puller::ProcessFenceActionMethod() { } } -void Puller::ProcessSemaphoreTriggerMethod() { +void Puller::ProcessSemaphoreTriggerMethod(DmaPusher& dma_pusher) { const auto semaphoreOperationMask = 0xF; - const auto op = - static_cast(regs.semaphore_trigger & semaphoreOperationMask); + const auto op = GpuSemaphoreOperation(regs.semaphore_trigger & semaphoreOperationMask); if (op == GpuSemaphoreOperation::WriteLong) { const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()}; const u32 payload = regs.semaphore_sequence; - rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, - VideoCommon::QueryPropertiesFlags::HasTimeout, payload, 0); + dma_pusher.rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, VideoCommon::QueryPropertiesFlags::HasTimeout, payload, 0); } else { do { - const u32 word{memory_manager.Read(regs.semaphore_address.SemaphoreAddress())}; + const u32 word = dma_pusher.memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); regs.acquire_source = true; regs.acquire_value = regs.semaphore_sequence; if (op == GpuSemaphoreOperation::AcquireEqual) { regs.acquire_active = true; regs.acquire_mode = false; if (word != regs.acquire_value) { - rasterizer->ReleaseFences(); + dma_pusher.rasterizer->ReleaseFences(); continue; } } else if (op == GpuSemaphoreOperation::AcquireGequal) { regs.acquire_active = true; regs.acquire_mode = true; if (word < regs.acquire_value) { - rasterizer->ReleaseFences(); + dma_pusher.rasterizer->ReleaseFences(); continue; } } else if (op == GpuSemaphoreOperation::AcquireMask) { if (word && regs.semaphore_sequence == 0) { - rasterizer->ReleaseFences(); + dma_pusher.rasterizer->ReleaseFences(); continue; } } else { @@ -116,21 +106,20 @@ void Puller::ProcessSemaphoreTriggerMethod() { } } -void Puller::ProcessSemaphoreRelease() { +void Puller::ProcessSemaphoreRelease(DmaPusher& dma_pusher) { const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()}; const u32 payload = regs.semaphore_release; - rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, - VideoCommon::QueryPropertiesFlags::IsAFence, payload, 0); + dma_pusher.rasterizer->Query(sequence_address, VideoCommon::QueryType::Payload, VideoCommon::QueryPropertiesFlags::IsAFence, payload, 0); } -void Puller::ProcessSemaphoreAcquire() { - u32 word = memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); +void Puller::ProcessSemaphoreAcquire(DmaPusher& dma_pusher) { + u32 word = dma_pusher.memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); const auto value = regs.semaphore_acquire; while (word != value) { regs.acquire_active = true; regs.acquire_value = value; - rasterizer->ReleaseFences(); - word = memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); + dma_pusher.rasterizer->ReleaseFences(); + word = dma_pusher.memory_manager.Read(regs.semaphore_address.SemaphoreAddress()); // TODO(kemathe73) figure out how to do the acquire_timeout regs.acquire_mode = false; regs.acquire_source = false; @@ -138,13 +127,13 @@ void Puller::ProcessSemaphoreAcquire() { } /// Calls a GPU puller method. -void Puller::CallPullerMethod(const MethodCall& method_call) { +void Puller::CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { regs.reg_array[method_call.method] = method_call.argument; const auto method = static_cast(method_call.method); switch (method) { case BufferMethods::BindObject: { - ProcessBindMethod(method_call); + ProcessBindMethod(dma_pusher, method_call); break; } case BufferMethods::Nop: @@ -155,16 +144,16 @@ void Puller::CallPullerMethod(const MethodCall& method_call) { case BufferMethods::WrcacheFlush: break; case BufferMethods::RefCnt: - rasterizer->SignalReference(); + dma_pusher.rasterizer->SignalReference(); break; case BufferMethods::SyncpointOperation: - ProcessFenceActionMethod(); + ProcessFenceActionMethod(dma_pusher); break; case BufferMethods::WaitForIdle: - rasterizer->WaitForIdle(); + dma_pusher.rasterizer->WaitForIdle(); break; case BufferMethods::SemaphoreOperation: { - ProcessSemaphoreTriggerMethod(); + ProcessSemaphoreTriggerMethod(dma_pusher); break; } case BufferMethods::NonStallInterrupt: { @@ -177,7 +166,7 @@ void Puller::CallPullerMethod(const MethodCall& method_call) { } case BufferMethods::MemOpB: { // Implement this better. - rasterizer->InvalidateGPUCache(); + dma_pusher.rasterizer->InvalidateGPUCache(); break; } case BufferMethods::MemOpC: @@ -186,11 +175,11 @@ void Puller::CallPullerMethod(const MethodCall& method_call) { break; } case BufferMethods::SemaphoreAcquire: { - ProcessSemaphoreAcquire(); + ProcessSemaphoreAcquire(dma_pusher); break; } case BufferMethods::SemaphoreRelease: { - ProcessSemaphoreRelease(); + ProcessSemaphoreRelease(dma_pusher); break; } case BufferMethods::Yield: { @@ -205,27 +194,26 @@ void Puller::CallPullerMethod(const MethodCall& method_call) { } /// Calls a GPU engine method. -void Puller::CallEngineMethod(const MethodCall& method_call) { +void Puller::CallEngineMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { const EngineID engine = bound_engines[method_call.subchannel]; - switch (engine) { case EngineID::FERMI_TWOD_A: - channel_state.fermi_2d->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + dma_pusher.channel_state.payload->fermi_2d.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::MAXWELL_B: - channel_state.maxwell_3d->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + dma_pusher.channel_state.payload->maxwell_3d.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::KEPLER_COMPUTE_B: - channel_state.kepler_compute->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + dma_pusher.channel_state.payload->kepler_compute.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::MAXWELL_DMA_COPY_A: - channel_state.maxwell_dma->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + dma_pusher.channel_state.payload->maxwell_dma.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::KEPLER_INLINE_TO_MEMORY_B: - channel_state.kepler_memory->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + dma_pusher.channel_state.payload->kepler_memory.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); break; case EngineID::NV01_TIMER: - channel_state.nv01_timer->CallMethod(method_call.method, method_call.argument, method_call.IsLastCall()); + dma_pusher.channel_state.payload->nv01_timer.CallMethod(dma_pusher.system, method_call.method, method_call.argument, method_call.IsLastCall()); break; default: UNIMPLEMENTED_MSG("Unimplemented engine"); @@ -234,28 +222,26 @@ void Puller::CallEngineMethod(const MethodCall& method_call) { } /// Calls a GPU engine multivalue method. -void Puller::CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, - u32 methods_pending) { +void Puller::CallEngineMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending) { const EngineID engine = bound_engines[subchannel]; - switch (engine) { case EngineID::FERMI_TWOD_A: - channel_state.fermi_2d->CallMultiMethod(method, base_start, amount, methods_pending); + dma_pusher.channel_state.payload->fermi_2d.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); break; case EngineID::MAXWELL_B: - channel_state.maxwell_3d->CallMultiMethod(method, base_start, amount, methods_pending); + dma_pusher.channel_state.payload->maxwell_3d.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); break; case EngineID::KEPLER_COMPUTE_B: - channel_state.kepler_compute->CallMultiMethod(method, base_start, amount, methods_pending); + dma_pusher.channel_state.payload->kepler_compute.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); break; case EngineID::MAXWELL_DMA_COPY_A: - channel_state.maxwell_dma->CallMultiMethod(method, base_start, amount, methods_pending); + dma_pusher.channel_state.payload->maxwell_dma.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); break; case EngineID::KEPLER_INLINE_TO_MEMORY_B: - channel_state.kepler_memory->CallMultiMethod(method, base_start, amount, methods_pending); + dma_pusher.channel_state.payload->kepler_memory.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); break; case EngineID::NV01_TIMER: - channel_state.nv01_timer->CallMultiMethod(method, base_start, amount, methods_pending); + dma_pusher.channel_state.payload->nv01_timer.CallMultiMethod(dma_pusher.system, method, base_start, amount, methods_pending); break; default: UNIMPLEMENTED_MSG("Unimplemented engine"); @@ -264,31 +250,26 @@ void Puller::CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_s } /// Calls a GPU method. -void Puller::CallMethod(const MethodCall& method_call) { - LOG_TRACE(HW_GPU, "Processing method {:08X} on subchannel {}", method_call.method, - method_call.subchannel); - +void Puller::CallMethod(DmaPusher& dma_pusher, const MethodCall& method_call) { + LOG_TRACE(HW_GPU, "Processing method {:08X} on subchannel {}", method_call.method, method_call.subchannel); ASSERT(method_call.subchannel < bound_engines.size()); - if (ExecuteMethodOnEngine(method_call.method)) { - CallEngineMethod(method_call); + if (ExecuteMethodOnEngine(dma_pusher, method_call.method)) { + CallEngineMethod(dma_pusher, method_call); } else { - CallPullerMethod(method_call); + CallPullerMethod(dma_pusher, method_call); } } /// Calls a GPU multivalue method. -void Puller::CallMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, - u32 methods_pending) { +void Puller::CallMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending) { LOG_TRACE(HW_GPU, "Processing method {:08X} on subchannel {}", method, subchannel); - ASSERT(subchannel < bound_engines.size()); - - if (ExecuteMethodOnEngine(method)) { - CallEngineMultiMethod(method, subchannel, base_start, amount, methods_pending); + if (ExecuteMethodOnEngine(dma_pusher, method)) { + CallEngineMultiMethod(dma_pusher, method, subchannel, base_start, amount, methods_pending); } else { for (u32 i = 0; i < amount; i++) { - CallPullerMethod(MethodCall{ + CallPullerMethod(dma_pusher, MethodCall{ method, base_start[i], subchannel, @@ -298,13 +279,9 @@ void Puller::CallMultiMethod(u32 method, u32 subchannel, const u32* base_start, } } -void Puller::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { - rasterizer = rasterizer_; -} - /// Determines where the method should be executed. -[[nodiscard]] bool Puller::ExecuteMethodOnEngine(u32 method) { - const auto buffer_method = static_cast(method); +[[nodiscard]] bool Puller::ExecuteMethodOnEngine(DmaPusher& dma_pusher, u32 method) { + const auto buffer_method = BufferMethods(method); return buffer_method >= BufferMethods::NonPullerMethods; } diff --git a/src/video_core/engines/puller.h b/src/video_core/engines/puller.h index fe5102e3ed..e8994f5640 100644 --- a/src/video_core/engines/puller.h +++ b/src/video_core/engines/puller.h @@ -70,32 +70,13 @@ public: BitField<8, 24, u32> syncpoint_id; }; - explicit Puller(GPU& gpu_, MemoryManager& memory_manager_, DmaPusher& dma_pusher, - Control::ChannelState& channel_state); - ~Puller(); - - void CallMethod(const MethodCall& method_call); - - void CallMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, - u32 methods_pending); - - void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); - - void CallPullerMethod(const MethodCall& method_call); - - void CallEngineMethod(const MethodCall& method_call); - - void CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount, - u32 methods_pending); - + void CallMethod(DmaPusher& dma_pusher, const MethodCall& method_call); + void CallMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending); + void BindRasterizer(DmaPusher& dma_pusher, VideoCore::RasterizerInterface* rasterizer); + void CallPullerMethod(DmaPusher& dma_pusher, const MethodCall& method_call); + void CallEngineMethod(DmaPusher& dma_pusher, const MethodCall& method_call); + void CallEngineMultiMethod(DmaPusher& dma_pusher, u32 method, u32 subchannel, const u32* base_start, u32 amount, u32 methods_pending); private: - Tegra::GPU& gpu; - - MemoryManager& memory_manager; - DmaPusher& dma_pusher; - Control::ChannelState& channel_state; - VideoCore::RasterizerInterface* rasterizer = nullptr; - static constexpr std::size_t NUM_REGS = 0x800; struct Regs { static constexpr size_t NUM_REGS = 0x40; @@ -139,12 +120,12 @@ private: }; } regs{}; - void ProcessBindMethod(const MethodCall& method_call); - void ProcessFenceActionMethod(); - void ProcessSemaphoreAcquire(); - void ProcessSemaphoreRelease(); - void ProcessSemaphoreTriggerMethod(); - [[nodiscard]] bool ExecuteMethodOnEngine(u32 method); + void ProcessBindMethod(DmaPusher& dma_pusher, const MethodCall& method_call); + void ProcessFenceActionMethod(DmaPusher& dma_pusher); + void ProcessSemaphoreAcquire(DmaPusher& dma_pusher); + void ProcessSemaphoreRelease(DmaPusher& dma_pusher); + void ProcessSemaphoreTriggerMethod(DmaPusher& dma_pusher); + [[nodiscard]] bool ExecuteMethodOnEngine(DmaPusher& dma_pusher, u32 method); /// Mapping of command subchannels to their bound engine ids std::array bound_engines{}; @@ -157,8 +138,7 @@ private: }; #define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(Regs, field_name) == position * 4, \ - "Field " #field_name " has invalid position") + static_assert(offsetof(Regs, field_name) == position * 4, "Field " #field_name " has invalid position") ASSERT_REG_POSITION(semaphore_address, 0x4); ASSERT_REG_POSITION(semaphore_sequence, 0x6); diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 391ca4ef5f..548a8bf809 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -40,30 +40,31 @@ namespace Tegra { struct GPU::Impl { - explicit Impl(GPU& gpu_, Core::System& system_, bool is_async_, bool use_nvdec_) - : gpu{gpu_}, system{system_}, host1x{system.Host1x()}, use_nvdec{use_nvdec_}, - shader_notify{std::make_unique()}, is_async{is_async_}, - gpu_thread{system_, is_async_}, scheduler{std::make_unique(gpu)} {} + explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_) + : system{system_} + , use_nvdec{use_nvdec_} + , shader_notify() + , is_async{is_async_} + , gpu_thread{system_} + {} ~Impl() = default; std::shared_ptr CreateChannel(s32 channel_id) { auto channel_state = std::make_shared(channel_id); channels.emplace(channel_id, channel_state); - scheduler->DeclareChannel(channel_state); + scheduler.DeclareChannel(channel_state); return channel_state; } void BindChannel(s32 channel_id) { - if (bound_channel == channel_id) { - return; + if (bound_channel != channel_id) { + auto it = channels.find(channel_id); + ASSERT(it != channels.end()); + bound_channel = channel_id; + current_channel = it->second.get(); + renderer->ReadRasterizer()->BindChannel(*current_channel); } - auto it = channels.find(channel_id); - ASSERT(it != channels.end()); - bound_channel = channel_id; - current_channel = it->second.get(); - - rasterizer->BindChannel(*current_channel); } std::shared_ptr AllocateChannel() { @@ -71,13 +72,13 @@ struct GPU::Impl { } void InitChannel(Control::ChannelState& to_init, u64 program_id) { - to_init.Init(system, gpu, program_id); - to_init.BindRasterizer(rasterizer); - rasterizer->InitializeChannel(to_init); + to_init.Init(system, program_id); + to_init.BindRasterizer(renderer->ReadRasterizer()); + renderer->ReadRasterizer()->InitializeChannel(to_init); } void InitAddressSpace(Tegra::MemoryManager& memory_manager) { - memory_manager.BindRasterizer(rasterizer); + memory_manager.BindRasterizer(renderer->ReadRasterizer()); } void ReleaseChannel(Control::ChannelState& to_release) { @@ -87,26 +88,26 @@ struct GPU::Impl { /// Binds a renderer to the GPU. void BindRenderer(std::unique_ptr renderer_) { renderer = std::move(renderer_); - rasterizer = renderer->ReadRasterizer(); - host1x.MemoryManager().BindInterface(rasterizer); - host1x.gmmu_manager.BindRasterizer(rasterizer); + system.Host1x().memory_manager.BindInterface(renderer->ReadRasterizer()); + system.Host1x().gmmu_manager.BindRasterizer(renderer->ReadRasterizer()); } /// Flush all current written commands into the host GPU for execution. void FlushCommands() { - rasterizer->FlushCommands(); + renderer->ReadRasterizer()->FlushCommands(); } /// Synchronizes CPU writes with Host GPU memory. void InvalidateGPUCache() { - std::function callback_writes( - [this](PAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); }); + std::function callback_writes([this](PAddr address, size_t size) { + renderer->ReadRasterizer()->OnCacheInvalidation(address, size); + }); system.GatherGPUDirtyMemory(callback_writes); } /// Signal the ending of command list. void OnCommandListEnd() { - rasterizer->ReleaseFences(false); + renderer->ReadRasterizer()->ReleaseFences(false); Settings::UpdateGPUAccuracy(); } @@ -143,62 +144,6 @@ struct GPU::Impl { } } - /// Returns a reference to the Maxwell3D GPU engine. - [[nodiscard]] Engines::Maxwell3D& Maxwell3D() { - ASSERT(current_channel); - return *current_channel->maxwell_3d; - } - - /// Returns a const reference to the Maxwell3D GPU engine. - [[nodiscard]] const Engines::Maxwell3D& Maxwell3D() const { - ASSERT(current_channel); - return *current_channel->maxwell_3d; - } - - /// Returns a reference to the KeplerCompute GPU engine. - [[nodiscard]] Engines::KeplerCompute& KeplerCompute() { - ASSERT(current_channel); - return *current_channel->kepler_compute; - } - - /// Returns a reference to the KeplerCompute GPU engine. - [[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const { - ASSERT(current_channel); - return *current_channel->kepler_compute; - } - - /// Returns a reference to the GPU DMA pusher. - [[nodiscard]] Tegra::DmaPusher& DmaPusher() { - ASSERT(current_channel); - return *current_channel->dma_pusher; - } - - /// Returns a const reference to the GPU DMA pusher. - [[nodiscard]] const Tegra::DmaPusher& DmaPusher() const { - ASSERT(current_channel); - return *current_channel->dma_pusher; - } - - /// Returns a reference to the underlying renderer. - [[nodiscard]] VideoCore::RendererBase& Renderer() { - return *renderer; - } - - /// Returns a const reference to the underlying renderer. - [[nodiscard]] const VideoCore::RendererBase& Renderer() const { - return *renderer; - } - - /// Returns a reference to the shader notifier. - [[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() { - return *shader_notify; - } - - /// Returns a const reference to the shader notifier. - [[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const { - return *shader_notify; - } - [[nodiscard]] u64 GetTicks() const { u64 gpu_tick = system.CoreTiming().GetGPUTicks(); Settings::GpuOverclock overclock = Settings::values.fast_gpu_time.GetValue(); @@ -210,14 +155,6 @@ struct GPU::Impl { return gpu_tick; } - [[nodiscard]] bool IsAsync() const { - return is_async; - } - - [[nodiscard]] bool UseNvdec() const { - return use_nvdec; - } - void RendererFrameEndNotify() { system.GetPerfStats().EndGameFrame(); } @@ -227,7 +164,7 @@ struct GPU::Impl { /// core timing events. void Start() { Settings::UpdateGPUAccuracy(); - gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler); + gpu_thread.StartThread(*renderer, renderer->Context(), scheduler); } void NotifyShutdown() { @@ -251,25 +188,24 @@ struct GPU::Impl { /// Push GPU command entries to be processed void PushGPUEntries(s32 channel, Tegra::CommandList&& entries) { - gpu_thread.SubmitList(channel, std::move(entries)); + gpu_thread.SubmitList(channel, std::move(entries), is_async); } /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory void FlushRegion(DAddr addr, u64 size) { - gpu_thread.FlushRegion(addr, size); + gpu_thread.FlushRegion(addr, size, is_async); } VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size) { - auto raster_area = rasterizer->GetFlushArea(addr, size); + auto raster_area = renderer->ReadRasterizer()->GetFlushArea(addr, size); if (raster_area.preemtive) { return raster_area; } raster_area.preemtive = true; const u64 fence = RequestSyncOperation([this, &raster_area]() { - rasterizer->FlushRegion(raster_area.start_address, - raster_area.end_address - raster_area.start_address); + renderer->ReadRasterizer()->FlushRegion(raster_area.start_address, raster_area.end_address - raster_area.start_address); }); - gpu_thread.TickGPU(); + gpu_thread.TickGPU(is_async); WaitForSyncOperation(fence); return raster_area; } @@ -280,16 +216,15 @@ struct GPU::Impl { } bool OnCPUWrite(DAddr addr, u64 size) { - return rasterizer->OnCPUWrite(addr, size); + return renderer->ReadRasterizer()->OnCPUWrite(addr, size); } /// Notify rasterizer that any caches of the specified region should be flushed and invalidated void FlushAndInvalidateRegion(DAddr addr, u64 size) { - gpu_thread.FlushAndInvalidateRegion(addr, size); + gpu_thread.FlushAndInvalidateRegion(addr, size, is_async); } - void RequestComposite(std::vector&& layers, - std::vector&& fences) { + void RequestComposite(std::vector&& layers, std::vector&& fences) { size_t num_fences{fences.size()}; size_t current_request_counter{}; { @@ -304,7 +239,7 @@ struct GPU::Impl { } } const auto wait_fence = RequestSyncOperation([this, current_request_counter, &layers, &fences, num_fences] { - auto& syncpoint_manager = host1x.GetSyncpointManager(); + auto& syncpoint_manager = system.Host1x().GetSyncpointManager(); if (num_fences == 0) { renderer->Composite(layers); } @@ -322,7 +257,7 @@ struct GPU::Impl { syncpoint_manager.RegisterGuestAction(fences[i].id, fences[i].value, executer); } }); - gpu_thread.TickGPU(); + gpu_thread.TickGPU(is_async); WaitForSyncOperation(wait_fence); } @@ -331,23 +266,20 @@ struct GPU::Impl { const auto wait_fence = RequestSyncOperation([&] { out = renderer->GetAppletCaptureBuffer(); }); - gpu_thread.TickGPU(); + gpu_thread.TickGPU(is_async); WaitForSyncOperation(wait_fence); return out; } - GPU& gpu; Core::System& system; - Host1x::Host1x& host1x; std::unique_ptr renderer; - VideoCore::RasterizerInterface* rasterizer = nullptr; const bool use_nvdec; s32 new_channel_id{1}; /// Shader build notifier - std::unique_ptr shader_notify; + VideoCore::ShaderNotify shader_notify; /// When true, we are about to shut down emulation session, so terminate outstanding tasks std::atomic_bool shutting_down{}; @@ -371,7 +303,7 @@ struct GPU::Impl { VideoCommon::GPUThread::ThreadManager gpu_thread; std::unique_ptr cpu_context; - std::unique_ptr scheduler; + Tegra::Control::Scheduler scheduler; ankerl::unordered_dense::map> channels; Tegra::Control::ChannelState* current_channel; s32 bound_channel{-1}; @@ -382,7 +314,8 @@ struct GPU::Impl { }; GPU::GPU(Core::System& system, bool is_async, bool use_nvdec) - : impl{std::make_unique(*this, system, is_async, use_nvdec)} {} + : impl{std::make_unique(system, is_async, use_nvdec)} +{} GPU::~GPU() = default; @@ -423,8 +356,9 @@ void GPU::OnCommandListEnd() { } u64 GPU::RequestFlush(DAddr addr, std::size_t size) { - return impl->RequestSyncOperation( - [this, addr, size]() { impl->rasterizer->FlushRegion(addr, size); }); + return impl->RequestSyncOperation([this, addr, size]() { + impl->renderer->ReadRasterizer()->FlushRegion(addr, size); + }); } u64 GPU::CurrentSyncRequestFence() const { @@ -441,52 +375,52 @@ void GPU::TickWork() { /// Gets a mutable reference to the Host1x interface Host1x::Host1x& GPU::Host1x() { - return impl->host1x; + return impl->system.Host1x(); } /// Gets an immutable reference to the Host1x interface. const Host1x::Host1x& GPU::Host1x() const { - return impl->host1x; + return impl->system.Host1x(); } Engines::Maxwell3D& GPU::Maxwell3D() { - return impl->Maxwell3D(); + return impl->current_channel->payload->maxwell_3d; } const Engines::Maxwell3D& GPU::Maxwell3D() const { - return impl->Maxwell3D(); + return impl->current_channel->payload->maxwell_3d; } Engines::KeplerCompute& GPU::KeplerCompute() { - return impl->KeplerCompute(); + return impl->current_channel->payload->kepler_compute; } const Engines::KeplerCompute& GPU::KeplerCompute() const { - return impl->KeplerCompute(); + return impl->current_channel->payload->kepler_compute; } Tegra::DmaPusher& GPU::DmaPusher() { - return impl->DmaPusher(); + return impl->current_channel->payload->dma_pusher; } const Tegra::DmaPusher& GPU::DmaPusher() const { - return impl->DmaPusher(); + return impl->current_channel->payload->dma_pusher; } VideoCore::RendererBase& GPU::Renderer() { - return impl->Renderer(); + return *impl->renderer; } const VideoCore::RendererBase& GPU::Renderer() const { - return impl->Renderer(); + return *impl->renderer; } VideoCore::ShaderNotify& GPU::ShaderNotify() { - return impl->ShaderNotify(); + return impl->shader_notify; } const VideoCore::ShaderNotify& GPU::ShaderNotify() const { - return impl->ShaderNotify(); + return impl->shader_notify; } void GPU::RequestComposite(std::vector&& layers, @@ -503,11 +437,11 @@ u64 GPU::GetTicks() const { } bool GPU::IsAsync() const { - return impl->IsAsync(); + return impl->is_async; } bool GPU::UseNvdec() const { - return impl->UseNvdec(); + return impl->use_nvdec; } void GPU::RendererFrameEndNotify() { diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index d7c8ac391c..50570b596d 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -19,8 +19,9 @@ namespace VideoCommon::GPUThread { -ThreadManager::ThreadManager(Core::System& system_, bool is_async_) - : system{system_}, is_async{is_async_} {} +ThreadManager::ThreadManager(Core::System& system_) + : system{system_} +{} ThreadManager::~ThreadManager() = default; @@ -39,7 +40,7 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten break; } if (auto* submit_list = std::get_if(&next.data)) { - scheduler.Push(submit_list->channel, std::move(submit_list->entries)); + scheduler.Push(system.GPU(), submit_list->channel, std::move(submit_list->entries)); } else if (std::holds_alternative(next.data)) { system.GPU().TickWork(); } else if (const auto* flush = std::get_if(&next.data)) { @@ -60,41 +61,40 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Core::Fronten }); } -void ThreadManager::SubmitList(s32 channel, Tegra::CommandList&& entries) { - PushCommand(SubmitListCommand(channel, std::move(entries))); +void ThreadManager::SubmitList(s32 channel, Tegra::CommandList&& entries, bool is_async) { + PushCommand(SubmitListCommand(channel, std::move(entries)), false, is_async); } -void ThreadManager::FlushRegion(DAddr addr, u64 size) { +void ThreadManager::FlushRegion(DAddr addr, u64 size, bool is_async) { if (!is_async) { // Always flush with synchronous GPU mode - PushCommand(FlushRegionCommand(addr, size)); + PushCommand(FlushRegionCommand(addr, size), false, is_async); } - return; } -void ThreadManager::TickGPU() { - PushCommand(GPUTickCommand()); +void ThreadManager::TickGPU(bool is_async) { + PushCommand(GPUTickCommand(), false, is_async); } void ThreadManager::InvalidateRegion(DAddr addr, u64 size) { rasterizer->OnCacheInvalidation(addr, size); } -void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size) { +void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size, bool is_async) { if (Settings::IsGPULevelHigh()) { if (!is_async) { - PushCommand(FlushRegionCommand(addr, size)); + PushCommand(FlushRegionCommand(addr, size), false, is_async); } else { auto& gpu = system.GPU(); const u64 fence = gpu.RequestFlush(addr, size); - TickGPU(); + TickGPU(is_async); gpu.WaitForSyncOperation(fence); } } rasterizer->OnCacheInvalidation(addr, size); } -u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { +u64 ThreadManager::PushCommand(CommandData&& command_data, bool block, bool is_async) { if (!is_async) { // In synchronous GPU mode, block the caller until the command has executed block = true; diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index ac1283a338..4c3fadce15 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -15,6 +15,7 @@ #include "common/bounded_threadsafe_queue.h" #include "common/polyfill_thread.h" +#include "video_core/dma_pusher.h" #include "video_core/framebuffer_config.h" namespace Tegra { @@ -103,7 +104,7 @@ struct SynchState final { /// Class used to manage the GPU thread class ThreadManager final { public: - explicit ThreadManager(Core::System& system_, bool is_async_); + explicit ThreadManager(Core::System& system_); ~ThreadManager(); /// Creates and starts the GPU thread. @@ -111,27 +112,25 @@ public: Tegra::Control::Scheduler& scheduler); /// Push GPU command entries to be processed - void SubmitList(s32 channel, Tegra::CommandList&& entries); + void SubmitList(s32 channel, Tegra::CommandList&& entries, bool is_async); /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory - void FlushRegion(DAddr addr, u64 size); + void FlushRegion(DAddr addr, u64 size, bool is_async); /// Notify rasterizer that any caches of the specified region should be invalidated void InvalidateRegion(DAddr addr, u64 size); /// Notify rasterizer that any caches of the specified region should be flushed and invalidated - void FlushAndInvalidateRegion(DAddr addr, u64 size); + void FlushAndInvalidateRegion(DAddr addr, u64 size, bool is_async); - void TickGPU(); + void TickGPU(bool is_async); private: /// Pushes a command to be executed by the GPU thread - u64 PushCommand(CommandData&& command_data, bool block = false); + u64 PushCommand(CommandData&& command_data, bool block, bool is_async); Core::System& system; - const bool is_async; VideoCore::RasterizerInterface* rasterizer = nullptr; - SynchState state; std::jthread thread; }; diff --git a/src/video_core/host1x/control.cpp b/src/video_core/host1x/control.cpp index 53b3063557..93ee57456b 100644 --- a/src/video_core/host1x/control.cpp +++ b/src/video_core/host1x/control.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2021 yuzu Emulator Project @@ -10,26 +10,22 @@ namespace Tegra::Host1x { -Control::Control(Host1x& host1x_) : host1x(host1x_) {} - -Control::~Control() = default; - -void Control::ProcessMethod(Method method, u32 argument) { +void Control::ProcessMethod(Host1x& host1x, Method method, u32 argument) { switch (method) { case Method::LoadSyncptPayload32: syncpoint_value = argument; break; case Method::WaitSyncpt: case Method::WaitSyncpt32: - Execute(argument); + Execute(host1x, argument); break; default: - UNIMPLEMENTED_MSG("Control method {:#X}", static_cast(method)); + UNIMPLEMENTED_MSG("Control method {:#X}", u32(method)); break; } } -void Control::Execute(u32 data) { +void Control::Execute(Host1x& host1x, u32 data) { LOG_TRACE(Service_NVDRV, "Control wait syncpt {} value {}", data, syncpoint_value); host1x.GetSyncpointManager().WaitHost(data, syncpoint_value); } diff --git a/src/video_core/host1x/control.h b/src/video_core/host1x/control.h index bd8a2d7ad4..4d87e63b32 100644 --- a/src/video_core/host1x/control.h +++ b/src/video_core/host1x/control.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-FileCopyrightText: 2021 Skyline Team and Contributors // SPDX-License-Identifier: GPL-3.0-or-later @@ -19,17 +22,11 @@ public: WaitSyncpt32 = 0x50, }; - explicit Control(Host1x& host1x); - ~Control(); - /// Writes the method into the state, Invoke Execute() if encountered - void ProcessMethod(Method method, u32 argument); - -private: + void ProcessMethod(Host1x& host1x, Method method, u32 argument); /// For Host1x, execute is waiting on a syncpoint previously written into the state - void Execute(u32 data); + void Execute(Host1x& host1x, u32 data); - Host1x& host1x; u32 syncpoint_value{}; }; diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp index b4e4a38c80..590b0e0ff2 100644 --- a/src/video_core/host1x/host1x.cpp +++ b/src/video_core/host1x/host1x.cpp @@ -27,22 +27,22 @@ void Host1x::StartDevice(s32 fd, ChannelType type, u32 syncpt) { #ifdef YUZU_LEGACY std::call_once(nvdec_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer #endif - devices[fd] = std::make_unique(*this, fd, syncpt); + devices[fd].emplace(*this, fd, syncpt); break; case ChannelType::VIC: #ifdef YUZU_LEGACY std::call_once(vic_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer #endif - devices[fd] = std::make_unique(*this, fd, syncpt); + devices[fd].emplace(*this, fd, syncpt); break; default: - LOG_ERROR(HW_GPU, "Unimplemented host1x device {}", static_cast(type)); + LOG_ERROR(HW_GPU, "Unimplemented host1x device {}", u32(type)); break; } } void Host1x::StopDevice(s32 fd, ChannelType type) { - devices.erase(fd); + devices[fd].emplace(); } } // namespace Tegra::Host1x diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h index 838e749072..592ec449e8 100644 --- a/src/video_core/host1x/host1x.h +++ b/src/video_core/host1x/host1x.h @@ -8,10 +8,14 @@ #include #include -#include +#include #include "common/common_types.h" +// fd types? +#include "video_core/host1x/nvdec.h" +#include "video_core/host1x/vic.h" + #include "common/address_space.h" #include "video_core/cdma_pusher.h" #include "video_core/host1x/gpu_device_memory_manager.h" @@ -31,118 +35,90 @@ class Nvdec; class FrameQueue { public: + struct FrameDevice { + std::deque>> m_presentation_order; + std::unordered_map> m_decode_order; + }; + void Open(s32 fd) { std::scoped_lock l{m_mutex}; - m_presentation_order.insert({fd, {}}); - m_decode_order.insert({fd, {}}); + m_frame_devices.insert_or_assign(fd, FrameDevice{}); } void Close(s32 fd) { std::scoped_lock l{m_mutex}; - m_presentation_order.erase(fd); - m_decode_order.erase(fd); + m_frame_devices.erase(fd); } s32 VicFindNvdecFdFromOffset(u64 search_offset) { std::scoped_lock l{m_mutex}; - for (auto& map : m_presentation_order) { - for (auto& [offset, frame] : map.second) { - if (offset == search_offset) { - return map.first; - } - } - } - for (auto& map : m_decode_order) { - for (auto& [offset, frame] : map.second) { - if (offset == search_offset) { - return map.first; - } - } + for (auto const& [fd, dev] : m_frame_devices) { + for (auto const& [offset, frame] : dev.m_presentation_order) + if (offset == search_offset) + return fd; + for (auto const& [offset, frame] : dev.m_decode_order) + if (offset == search_offset) + return fd; } return -1; } void PushPresentOrder(s32 fd, u64 offset, std::shared_ptr&& frame) { std::scoped_lock l{m_mutex}; - auto map = m_presentation_order.find(fd); - if (map == m_presentation_order.end()) { - return; + if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { + if (it->second.m_presentation_order.size() >= MAX_PRESENT_QUEUE) + it->second.m_presentation_order.pop_front(); + it->second.m_presentation_order.emplace_back(offset, std::move(frame)); } - - if (map->second.size() >= MAX_PRESENT_QUEUE) { - map->second.pop_front(); - } - - map->second.emplace_back(offset, std::move(frame)); } void PushDecodeOrder(s32 fd, u64 offset, std::shared_ptr&& frame) { std::scoped_lock l{m_mutex}; - auto map = m_decode_order.find(fd); - if (map == m_decode_order.end()) { - return; - } - - map->second.insert_or_assign(offset, std::move(frame)); - - if (map->second.size() > MAX_DECODE_MAP) { - auto it = map->second.begin(); - std::advance(it, map->second.size() - MAX_DECODE_MAP); - map->second.erase(map->second.begin(), it); + if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { + it->second.m_decode_order.insert_or_assign(offset, std::move(frame)); + if (it->second.m_decode_order.size() > MAX_DECODE_MAP) { + auto it2 = it->second.m_decode_order.begin(); + std::advance(it2, it->second.m_decode_order.size() - MAX_DECODE_MAP); + it->second.m_decode_order.erase(it->second.m_decode_order.begin(), it2); + } } } std::shared_ptr GetFrame(s32 fd, u64 offset) { - if (fd == -1) { - return {}; + if (fd != -1) { + std::scoped_lock l{m_mutex}; + if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { + if (it->second.m_presentation_order.size() > 0) + return GetPresentOrderLocked(fd); + if (it->second.m_decode_order.size() > 0) + return GetDecodeOrderLocked(fd, offset); + } } - - std::scoped_lock l{m_mutex}; - - auto present_map = m_presentation_order.find(fd); - if (present_map != m_presentation_order.end() && !present_map->second.empty()) { - return GetPresentOrderLocked(fd); - } - - auto decode_map = m_decode_order.find(fd); - if (decode_map != m_decode_order.end() && !decode_map->second.empty()) { - return GetDecodeOrderLocked(fd, offset); - } - return {}; } private: std::shared_ptr GetPresentOrderLocked(s32 fd) { - auto map = m_presentation_order.find(fd); - if (map == m_presentation_order.end() || map->second.empty()) { - return {}; + if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { + auto frame = std::move(it->second.m_presentation_order.front().second); + it->second.m_presentation_order.pop_front(); + return frame; } - - auto frame = std::move(map->second.front().second); - map->second.pop_front(); - return frame; + return {}; } std::shared_ptr GetDecodeOrderLocked(s32 fd, u64 offset) { - auto map = m_decode_order.find(fd); - if (map == m_decode_order.end() || map->second.empty()) { - return {}; + if (auto const it = m_frame_devices.find(fd); it != m_frame_devices.end()) { + if (auto const it2 = it->second.m_decode_order.find(offset); it2 != it->second.m_decode_order.end()) { + // TODO: this "mapped" prevents us from fully embracing ankerl + return std::move(it->second.m_decode_order.extract(it2).mapped()); + } } - - auto it = map->second.find(offset); - if (it == map->second.end()) { - return {}; - } - // TODO: this "mapped" prevents us from fully embracing ankerl - return std::move(map->second.extract(it).mapped()); + return {}; } - using FramePtr = std::shared_ptr; - std::mutex m_mutex{}; - ankerl::unordered_dense::map>> m_presentation_order; - ankerl::unordered_dense::map> m_decode_order; + ankerl::unordered_dense::map m_frame_devices; static constexpr size_t MAX_PRESENT_QUEUE = 100; static constexpr size_t MAX_DECODE_MAP = 200; @@ -196,11 +172,11 @@ public: void StopDevice(s32 fd, ChannelType type); void PushEntries(s32 fd, ChCommandHeaderList&& entries) { - auto it = devices.find(fd); - if (it == devices.end()) { - return; + if (auto const nvdec = std::get_if(&devices[fd])) { + nvdec->PushEntries(std::move(entries)); + } else if (auto const vic = std::get_if(&devices[fd])) { + vic->PushEntries(std::move(entries)); } - it->second->PushEntries(std::move(entries)); } Core::System& system; @@ -209,7 +185,11 @@ public: Tegra::MemoryManager gmmu_manager; Common::FlatAllocator allocator; FrameQueue frame_queue; - ankerl::unordered_dense::map> devices; + std::array, 1024> devices; #ifdef YUZU_LEGACY std::once_flag nvdec_first_init; std::once_flag vic_first_init; diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index bafbb0ed25..f7830a3a45 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -407,15 +407,15 @@ void Vic::ReadInterlacedY8__V8U8_N420(const SlotStruct& slot, std::span offsets, std::shared_ptr frame, bool planar) noexcept { switch (slot.config.frame_format) { - case DXVAHD_FRAME_FORMAT::PROGRESSIVE: + case DxvhadFrameFormat::Progressive: ReadProgressiveY8__V8U8_N420(slot, offsets, std::move(frame), planar, false); break; - case DXVAHD_FRAME_FORMAT::TOP_FIELD: + case DxvhadFrameFormat::TopField: ReadInterlacedY8__V8U8_N420(slot, offsets, std::move(frame), planar, true); break; - case DXVAHD_FRAME_FORMAT::BOTTOM_FIELD: + case DxvhadFrameFormat::BottomField: ReadInterlacedY8__V8U8_N420(slot, offsets, std::move(frame), planar, false); break; default: @@ -860,7 +860,7 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) n }; switch (output_surface_config.out_block_kind) { - case BLK_KIND::GENERIC_16Bx2: { + case BlkKind::Generic_16Bx2: { u32 const block_height = u32(output_surface_config.out_block_height); auto const out_luma_swizzle_size = Texture::CalculateSize(true, BytesPerPixel, out_luma_width, out_luma_height, 1, block_height, 0); auto const out_chroma_swizzle_size = Texture::CalculateSize(true, BytesPerPixel * 2, out_chroma_width, out_chroma_height, 1, block_height, 0); @@ -889,7 +889,7 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) n Texture::SwizzleTexture(out_chroma, chroma_scratch, BytesPerPixel, out_chroma_width, out_chroma_height, 1, block_height, 0, 1); } } break; - case BLK_KIND::PITCH: { + case BlkKind::Pitch: { LOG_TRACE(HW_GPU, "Writing Y8__V8U8_N420 swizzled frame\n" "\tinput surface {}x{} stride {} size {:#X}\n" "\toutput luma {}x{} stride {} size {:#X} block height {} swizzled size 0x{:X}\n", @@ -1032,7 +1032,7 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config, VideoPixel }; switch (output_surface_config.out_block_kind) { - case BLK_KIND::GENERIC_16Bx2: { + case BlkKind::Generic_16Bx2: { const u32 block_height = u32(output_surface_config.out_block_height); auto const out_swizzle_size = Texture::CalculateSize(true, BytesPerPixel, out_luma_width, out_luma_height, 1, block_height, 0); LOG_TRACE(HW_GPU, "Writing ABGR swizzled frame\n" @@ -1051,7 +1051,7 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config, VideoPixel Texture::SwizzleTexture(out_luma, luma_scratch, BytesPerPixel, out_luma_width, out_luma_height, 1, block_height, 0, 1); } } break; - case BLK_KIND::PITCH: { + case BlkKind::Pitch: { LOG_TRACE(HW_GPU, "Writing ABGR pitch frame\n" "\tinput surface {}x{} stride {} size {:#X}" "\toutput surface {}x{} stride {} size {:#X}", diff --git a/src/video_core/host1x/vic.h b/src/video_core/host1x/vic.h index d728b38f91..23f3f66c18 100644 --- a/src/video_core/host1x/vic.h +++ b/src/video_core/host1x/vic.h @@ -6,16 +6,12 @@ #pragma once -#include -#include #include -#include -#include #include "common/common_types.h" #include "common/scratch_buffer.h" #include "video_core/cdma_pusher.h" -#include "video_core/host1x/host1x.h" +#include "video_core/host1x/ffmpeg.h" namespace Tegra::Host1x { class Host1x; @@ -138,52 +134,53 @@ enum SurfaceIndex : u32 { CombinedMotion = 7, }; -enum class DXVAHD_ALPHA_FILL_MODE : u32 { - OPAQUE = 0, - BACKGROUND = 1, - DESTINATION = 2, - SOURCE_STREAM = 3, - COMPOSITED = 4, - SOURCE_ALPHA = 5, +// Note: these will inevitably collide with Win32 defines if you use their UPPER_SNAKE_CASE naming +enum class DxvhadAlphaFillMode : u32 { + Opaque = 0, + Background = 1, + Destination = 2, + SourceStream = 3, + Composited = 4, + SourceAlpha = 5, }; -enum class DXVAHD_FRAME_FORMAT : u64 { - PROGRESSIVE = 0, - INTERLACED_TOP_FIELD_FIRST = 1, - INTERLACED_BOTTOM_FIELD_FIRST = 2, - TOP_FIELD = 3, - BOTTOM_FIELD = 4, - SUBPIC_PROGRESSIVE = 5, - SUBPIC_INTERLACED_TOP_FIELD_FIRST = 6, - SUBPIC_INTERLACED_BOTTOM_FIELD_FIRST = 7, - SUBPIC_TOP_FIELD = 8, - SUBPIC_BOTTOM_FIELD = 9, - TOP_FIELD_CHROMA_BOTTOM = 10, - BOTTOM_FIELD_CHROMA_TOP = 11, - SUBPIC_TOP_FIELD_CHROMA_BOTTOM = 12, - SUBPIC_BOTTOM_FIELD_CHROMA_TOP = 13, +enum class DxvhadFrameFormat : u64 { + Progressive = 0, + InterlacedTopFieldFirst = 1, + InterlacedBottomFieldFirst = 2, + TopField = 3, + BottomField = 4, + SubpicProgressive = 5, + SubpicInterlacedTopFieldFirst = 6, + SubpicInterlacedBottomFieldFirst = 7, + SubpicTopField = 8, + SubpicBottomField = 9, + TopFieldChromaBottom = 10, + BottomFieldChromaTop = 11, + SubpicTopFieldChromaBottom = 12, + SubpicBottomFieldChromaTop = 13, }; -enum class DXVAHD_DEINTERLACE_MODE_PRIVATE : u64 { - WEAVE = 0, - BOB_FIELD = 1, - BOB = 2, - NEWBOB = 3, - DISI1 = 4, - WEAVE_LUMA_BOB_FIELD_CHROMA = 5, - MAX = 0xF, +enum class DxvhadDeinterlaceModePrivate : u64 { + Weave = 0, + BobField = 1, + Bob = 2, + Newbob = 3, + Disi1 = 4, + WeaveLumaBobFieldChroma = 5, + Max = 0xF, }; -enum class BLK_KIND { - PITCH = 0, - GENERIC_16Bx2 = 1, +enum class BlkKind { + Pitch = 0, + Generic_16Bx2 = 1, // These are unsupported in the vic - BL_NAIVE = 2, - BL_KEPLER_XBAR_RAW = 3, - VP2_TILED = 15, + BlNaive = 2, + BlKeplerXbarRaw = 3, + Vp2Tiled = 15, }; -enum class BLEND_SRCFACTC : u32 { +enum class BlendSrcFactC : u32 { K1 = 0, K1_TIMES_DST = 1, NEG_K1_TIMES_DST = 2, @@ -191,7 +188,7 @@ enum class BLEND_SRCFACTC : u32 { ZERO = 4, }; -enum class BLEND_DSTFACTC : u32 { +enum class BlendDstFactC : u32 { K1 = 0, K2 = 1, K1_TIMES_DST = 2, @@ -201,7 +198,7 @@ enum class BLEND_DSTFACTC : u32 { ONE = 6, }; -enum class BLEND_SRCFACTA : u32 { +enum class BlendSrcFactA : u32 { K1 = 0, K2 = 1, NEG_K1_TIMES_DST = 2, @@ -209,7 +206,7 @@ enum class BLEND_SRCFACTA : u32 { MAX = 7, }; -enum class BLEND_DSTFACTA : u32 { +enum class BlendDstFactA : u32 { K2 = 0, NEG_K1_TIMES_SRC = 1, ZERO = 2, @@ -232,7 +229,7 @@ static_assert(sizeof(PipeConfig) == 0x10, "PipeConfig has the wrong size!"); struct OutputConfig { union { - BitField<0, 3, DXVAHD_ALPHA_FILL_MODE> alpha_fill_mode; + BitField<0, 3, DxvhadAlphaFillMode> alpha_fill_mode; BitField<3, 3, u64> alpha_fill_slot; BitField<6, 10, u64> background_a; BitField<16, 10, u64> background_r; @@ -265,7 +262,7 @@ struct OutputSurfaceConfig { BitField<0, 7, VideoPixelFormat> out_pixel_format; BitField<7, 2, u32> out_chroma_loc_horiz; BitField<9, 2, u32> out_chroma_loc_vert; - BitField<11, 4, BLK_KIND> out_block_kind; + BitField<11, 4, BlkKind> out_block_kind; BitField<15, 4, u32> out_block_height; // in gobs, log2 BitField<19, 3, u32> reserved0; BitField<22, 10, u32> reserved1; @@ -365,7 +362,7 @@ struct SlotConfig { BitField<14, 1, u64> prev_prev_motion_field_enable; BitField<15, 1, u64> combined_motion_field_enable; - BitField<16, 4, DXVAHD_FRAME_FORMAT> frame_format; + BitField<16, 4, DxvhadFrameFormat> frame_format; BitField<20, 2, u64> filter_length_y; // 0: 1-tap, 1: 2-tap, 2: 5-tap, 3: 10-tap BitField<22, 2, u64> filter_length_x; BitField<24, 12, u64> panoramic; @@ -377,7 +374,7 @@ struct SlotConfig { BitField<10, 10, u64> filter_detail; BitField<20, 10, u64> chroma_noise; BitField<30, 10, u64> chroma_detail; - BitField<40, 4, DXVAHD_DEINTERLACE_MODE_PRIVATE> deinterlace_mode; + BitField<40, 4, DxvhadDeinterlaceModePrivate> deinterlace_mode; BitField<44, 3, u64> motion_accumulation_weight; BitField<47, 11, u64> noise_iir; BitField<58, 4, u64> light_level; @@ -484,13 +481,13 @@ struct BlendingSlotStruct { BitField<26, 6, u32> reserved1; }; union { - BitField<0, 3, BLEND_SRCFACTC> src_factor_color_match_select; + BitField<0, 3, BlendSrcFactC> src_factor_color_match_select; BitField<3, 1, u32> reserved2; - BitField<4, 3, BLEND_DSTFACTC> dst_factor_color_match_select; + BitField<4, 3, BlendDstFactC> dst_factor_color_match_select; BitField<7, 1, u32> reserved3; - BitField<8, 3, BLEND_SRCFACTA> src_factor_a_match_select; + BitField<8, 3, BlendSrcFactA> src_factor_a_match_select; BitField<11, 1, u32> reserved4; - BitField<12, 3, BLEND_DSTFACTA> dst_factor_a_match_select; + BitField<12, 3, BlendDstFactA> dst_factor_a_match_select; BitField<15, 1, u32> reserved5; BitField<16, 4, u32> reserved6; BitField<20, 4, u32> reserved7; @@ -624,8 +621,8 @@ private: VicRegisters regs{}; Common::ScratchBuffer swizzle_scratch; - Common::ScratchBuffer output_surface; - Common::ScratchBuffer slot_surface; + Common::ScratchBuffer output_surface; + Common::ScratchBuffer slot_surface; Common::ScratchBuffer luma_scratch; Common::ScratchBuffer chroma_scratch; diff --git a/src/video_core/macro.cpp b/src/video_core/macro.cpp index 76a054665c..2833f95ee9 100644 --- a/src/video_core/macro.cpp +++ b/src/video_core/macro.cpp @@ -64,10 +64,10 @@ bool IsTopologySafe(Maxwell3D::Regs::PrimitiveTopology topology) { } // Anonymous namespace -void HLE_DrawArraysIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_DrawArraysIndirect::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { auto topology = static_cast(parameters[0]); if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { - Fallback(maxwell3d, parameters); + Fallback(system, maxwell3d, parameters); return; } @@ -93,7 +93,7 @@ void HLE_DrawArraysIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_DrawArraysIndirect::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { SCOPE_EXIT { if (extended) { maxwell3d.engine_state = Maxwell3D::EngineHint::None; @@ -123,10 +123,10 @@ void HLE_DrawArraysIndirect::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_DrawIndexedIndirect::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { auto topology = static_cast(parameters[0]); if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { - Fallback(maxwell3d, parameters); + Fallback(system, maxwell3d, parameters); return; } @@ -161,7 +161,7 @@ void HLE_DrawIndexedIndirect::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_DrawIndexedIndirect::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { maxwell3d.RefreshParameters(); const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); const u32 element_base = parameters[4]; @@ -184,7 +184,7 @@ void HLE_DrawIndexedIndirect::Fallback(Engines::Maxwell3D& maxwell3d, std::span< maxwell3d.replace_table.clear(); } } -void HLE_MultiLayerClear::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_MultiLayerClear::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); ASSERT(parameters.size() == 1); @@ -196,47 +196,44 @@ void HLE_MultiLayerClear::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_MultiDrawIndexedIndirectCount::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { const auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[2]); - if (!IsTopologySafe(topology)) { - Fallback(maxwell3d, parameters); - return; + if (IsTopologySafe(topology)) { + const u32 start_indirect = parameters[0]; + const u32 end_indirect = parameters[1]; + if (start_indirect >= end_indirect) { + // Nothing to do. + return; + } + const u32 padding = parameters[3]; // padding is in words + // size of each indirect segment + const u32 indirect_words = 5 + padding; + const u32 stride = indirect_words * sizeof(u32); + const std::size_t draw_count = end_indirect - start_indirect; + const u32 estimate = u32(maxwell3d.EstimateIndexBufferSize()); + maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; + auto& params = maxwell3d.draw_manager.indirect_state; + params.is_byte_count = false; + params.is_indexed = true; + params.include_count = true; + params.count_start_address = maxwell3d.GetMacroAddress(4); + params.indirect_start_address = maxwell3d.GetMacroAddress(5); + params.buffer_size = stride * draw_count; + params.max_draw_counts = draw_count; + params.stride = stride; + maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; + maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; + maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); + maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); + maxwell3d.SetHLEReplacementAttributeType(0, 0x648, Maxwell3D::HLEReplacementAttributeType::DrawID); + maxwell3d.draw_manager.DrawIndexedIndirect(maxwell3d, topology, 0, estimate); + maxwell3d.engine_state = Maxwell3D::EngineHint::None; + maxwell3d.replace_table.clear(); + } else { + Fallback(system, maxwell3d, parameters); } - - const u32 start_indirect = parameters[0]; - const u32 end_indirect = parameters[1]; - if (start_indirect >= end_indirect) { - // Nothing to do. - return; - } - - const u32 padding = parameters[3]; // padding is in words - - // size of each indirect segment - const u32 indirect_words = 5 + padding; - const u32 stride = indirect_words * sizeof(u32); - const std::size_t draw_count = end_indirect - start_indirect; - const u32 estimate = static_cast(maxwell3d.EstimateIndexBufferSize()); - maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; - auto& params = maxwell3d.draw_manager.indirect_state; - params.is_byte_count = false; - params.is_indexed = true; - params.include_count = true; - params.count_start_address = maxwell3d.GetMacroAddress(4); - params.indirect_start_address = maxwell3d.GetMacroAddress(5); - params.buffer_size = stride * draw_count; - params.max_draw_counts = draw_count; - params.stride = stride; - maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; - maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; - maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); - maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); - maxwell3d.SetHLEReplacementAttributeType(0, 0x648, Maxwell3D::HLEReplacementAttributeType::DrawID); - maxwell3d.draw_manager.DrawIndexedIndirect(maxwell3d, topology, 0, estimate); - maxwell3d.engine_state = Maxwell3D::EngineHint::None; - maxwell3d.replace_table.clear(); } -void HLE_MultiDrawIndexedIndirectCount::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_MultiDrawIndexedIndirectCount::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { SCOPE_EXIT { // Clean everything. maxwell3d.regs.vertex_id_base = 0x0; @@ -250,7 +247,7 @@ void HLE_MultiDrawIndexedIndirectCount::Fallback(Engines::Maxwell3D& maxwell3d, // Nothing to do. return; } - const auto topology = static_cast(parameters[2]); + const auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[2]); const u32 padding = parameters[3]; const std::size_t max_draws = parameters[4]; const u32 indirect_words = 5 + padding; @@ -265,41 +262,41 @@ void HLE_MultiDrawIndexedIndirectCount::Fallback(Engines::Maxwell3D& maxwell3d, maxwell3d.engine_state = Maxwell3D::EngineHint::OnHLEMacro; maxwell3d.SetHLEReplacementAttributeType(0, 0x640, Maxwell3D::HLEReplacementAttributeType::BaseVertex); maxwell3d.SetHLEReplacementAttributeType(0, 0x644, Maxwell3D::HLEReplacementAttributeType::BaseInstance); - maxwell3d.CallMethod(0x8e3, 0x648, true); - maxwell3d.CallMethod(0x8e4, static_cast(index), true); + maxwell3d.CallMethod(system, 0x8e3, 0x648, true); + maxwell3d.CallMethod(system, 0x8e4, u32(index), true); maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; maxwell3d.draw_manager.DrawIndex(maxwell3d, topology, parameters[base + 2], parameters[base], base_vertex, base_instance, parameters[base + 1]); } } -void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_DrawIndirectByteCount::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback(); - if (!force) { - Fallback(maxwell3d, parameters); - return; + if (force) { + auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[0] & 0xFFFFU); + auto& params = maxwell3d.draw_manager.indirect_state; + params.is_byte_count = true; + params.is_indexed = false; + params.include_count = false; + params.count_start_address = 0; + params.indirect_start_address = maxwell3d.GetMacroAddress(2); + params.buffer_size = 4; + params.max_draw_counts = 1; + params.stride = parameters[1]; + maxwell3d.regs.draw.begin = parameters[0]; + maxwell3d.regs.draw_auto_stride = parameters[1]; + maxwell3d.regs.draw_auto_byte_count = parameters[2]; + maxwell3d.draw_manager.DrawArrayIndirect(maxwell3d, topology); + } else { + Fallback(system, maxwell3d, parameters); } - auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[0] & 0xFFFFU); - auto& params = maxwell3d.draw_manager.indirect_state; - params.is_byte_count = true; - params.is_indexed = false; - params.include_count = false; - params.count_start_address = 0; - params.indirect_start_address = maxwell3d.GetMacroAddress(2); - params.buffer_size = 4; - params.max_draw_counts = 1; - params.stride = parameters[1]; - maxwell3d.regs.draw.begin = parameters[0]; - maxwell3d.regs.draw_auto_stride = parameters[1]; - maxwell3d.regs.draw_auto_byte_count = parameters[2]; - maxwell3d.draw_manager.DrawArrayIndirect(maxwell3d, topology); } -void HLE_DrawIndirectByteCount::Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters) { +void HLE_DrawIndirectByteCount::Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters) { maxwell3d.RefreshParameters(); maxwell3d.regs.draw.begin = parameters[0]; maxwell3d.regs.draw_auto_stride = parameters[1]; maxwell3d.regs.draw_auto_byte_count = parameters[2]; maxwell3d.draw_manager.DrawArray(maxwell3d, maxwell3d.regs.draw.topology, 0, maxwell3d.regs.draw_auto_byte_count / maxwell3d.regs.draw_auto_stride, 0, 1); } -void HLE_C713C83D8F63CCF3::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_C713C83D8F63CCF3::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const u32 offset = (parameters[0] & 0x3FFFFFFF) << 2; const u32 address = maxwell3d.regs.shadow_scratch[24]; @@ -309,7 +306,7 @@ void HLE_C713C83D8F63CCF3::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_D7333D26E0A93EDE::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const size_t index = parameters[0]; const u32 address = maxwell3d.regs.shadow_scratch[42 + index]; @@ -319,7 +316,7 @@ void HLE_D7333D26E0A93EDE::Execute(Engines::Maxwell3D& maxwell3d, std::span> 24) & 0xFF; const_buffer.address_low = address << 8; } -void HLE_BindShader::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_BindShader::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); auto& regs = maxwell3d.regs; const u32 index = parameters[0]; @@ -343,7 +340,7 @@ void HLE_BindShader::Execute(Engines::Maxwell3D& maxwell3d, std::span bind_group.raw_config = 0x11; maxwell3d.ProcessCBBind(bind_group_id); } -void HLE_SetRasterBoundingBox::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_SetRasterBoundingBox::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const u32 raster_mode = parameters[0]; auto& regs = maxwell3d.regs; @@ -352,7 +349,7 @@ void HLE_SetRasterBoundingBox::Execute(Engines::Maxwell3D& maxwell3d, std::span< regs.raster_bounding_box.raw = raster_mode & 0xFFFFF00F; regs.raster_bounding_box.pad.Assign(scratch_data & raster_enabled); } -void HLE_ClearConstBuffer::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_ClearConstBuffer::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { static constexpr std::array zeroes{}; //must be bigger than either 7000 or 5F00 maxwell3d.RefreshParameters(); auto& regs = maxwell3d.regs; @@ -362,7 +359,7 @@ void HLE_ClearConstBuffer::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_ClearMemory::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); const u32 needed_memory = parameters[2] / sizeof(u32); if (needed_memory > zero_memory.size()) { @@ -373,10 +370,10 @@ void HLE_ClearMemory::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { +void HLE_TransformFeedbackSetup::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method) { maxwell3d.RefreshParameters(); auto& regs = maxwell3d.regs; regs.transform_feedback_enabled = 1; @@ -388,8 +385,8 @@ void HLE_TransformFeedbackSetup::Execute(Engines::Maxwell3D& maxwell3d, std::spa regs.upload.line_count = 1; regs.upload.dest.address_high = parameters[0]; regs.upload.dest.address_low = parameters[1]; - maxwell3d.CallMethod(size_t(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); - maxwell3d.CallMethod(size_t(MAXWELL3D_REG_INDEX(inline_data)), regs.transform_feedback.controls[0].stride, true); + maxwell3d.CallMethod(system, size_t(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); + maxwell3d.CallMethod(system, size_t(MAXWELL3D_REG_INDEX(inline_data)), regs.transform_feedback.controls[0].stride, true); maxwell3d.Rasterizer().RegisterTransformFeedback(regs.upload.dest.Address()); } @@ -429,7 +426,7 @@ void HLE_TransformFeedbackSetup::Execute(Engines::Maxwell3D& maxwell3d, std::spa } } -void MacroInterpreterImpl::Execute(Engines::Maxwell3D& maxwell3d, std::span params, u32 method) { +void MacroInterpreterImpl::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span params, u32 method) { Reset(); registers[1] = params[0]; @@ -439,7 +436,7 @@ void MacroInterpreterImpl::Execute(Engines::Maxwell3D& maxwell3d, std::span> opcode.bf_src_bit) & opcode.GetBitfieldMask(); dst &= ~(opcode.GetBitfieldMask() << opcode.bf_dst_bit); dst |= src << opcode.bf_dst_bit; - ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, dst); + ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, dst); break; } case Macro::Operation::ExtractShiftLeftImmediate: { @@ -501,7 +498,7 @@ bool MacroInterpreterImpl::Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slo u32 result = ((src >> dst) & opcode.GetBitfieldMask()) << opcode.bf_dst_bit; - ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::ExtractShiftLeftRegister: { @@ -510,12 +507,12 @@ bool MacroInterpreterImpl::Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slo u32 result = ((src >> opcode.bf_src_bit) & opcode.GetBitfieldMask()) << dst; - ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::Read: { u32 result = Read(maxwell3d, GetRegister(opcode.src_a) + opcode.immediate); - ProcessResult(maxwell3d, opcode.result_operation, opcode.dst, result); + ProcessResult(system, maxwell3d, opcode.result_operation, opcode.dst, result); break; } case Macro::Operation::Branch: { @@ -531,7 +528,7 @@ bool MacroInterpreterImpl::Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slo delayed_pc = base_address + opcode.GetBranchTarget(); // Execute one more instruction due to the delay slot. - return Step(maxwell3d, true); + return Step(system, maxwell3d, true); } break; } @@ -544,7 +541,7 @@ bool MacroInterpreterImpl::Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slo // cause an exit if it's executed inside a delay slot. if (opcode.is_exit && !is_delay_slot) { // Exit has a delay slot, execute the next instruction - Step(maxwell3d, true); + Step(system, maxwell3d, true); return false; } return true; @@ -591,7 +588,7 @@ u32 MacroInterpreterImpl::GetALUResult(Macro::ALUOperation operation, u32 src_a, } /// Performs the result operation on the input result and stores it in the specified register (if necessary). -void MacroInterpreterImpl::ProcessResult(Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result) { +void MacroInterpreterImpl::ProcessResult(Core::System& system, Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result) { switch (operation) { case Macro::ResultOperation::IgnoreAndFetch: // Fetch parameter and ignore result. @@ -609,12 +606,12 @@ void MacroInterpreterImpl::ProcessResult(Engines::Maxwell3D& maxwell3d, Macro::R case Macro::ResultOperation::FetchAndSend: // Fetch parameter and send result. SetRegister(reg, FetchParameter()); - Send(maxwell3d, result); + Send(system, maxwell3d, result); break; case Macro::ResultOperation::MoveAndSend: // Move and send result. SetRegister(reg, result); - Send(maxwell3d, result); + Send(system, maxwell3d, result); break; case Macro::ResultOperation::FetchAndSetMethod: // Fetch parameter and use result as Method Address. @@ -625,13 +622,13 @@ void MacroInterpreterImpl::ProcessResult(Engines::Maxwell3D& maxwell3d, Macro::R // Move result and use as Method Address, then fetch and send parameter. SetRegister(reg, result); SetMethodAddress(result); - Send(maxwell3d, FetchParameter()); + Send(system, maxwell3d, FetchParameter()); break; case Macro::ResultOperation::MoveAndSetMethodSend: // Move result and use as Method Address, then send bits 12:17 of result. SetRegister(reg, result); SetMethodAddress(result); - Send(maxwell3d, (result >> 12) & 0b111111); + Send(system, maxwell3d, (result >> 12) & 0b111111); break; default: UNIMPLEMENTED_MSG("Unimplemented result operation {}", operation); @@ -672,8 +669,8 @@ void MacroInterpreterImpl::SetRegister(u32 register_id, u32 value) { } /// Calls a GPU Engine method with the input parameter. -void MacroInterpreterImpl::Send(Engines::Maxwell3D& maxwell3d, u32 value) { - maxwell3d.CallMethod(method_address.address, value, true); +void MacroInterpreterImpl::Send(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 value) { + maxwell3d.CallMethod(system, method_address.address, value, true); // Increment the method address by the method increment. method_address.address.Assign(method_address.address.Value() + method_address.increment.Value()); } @@ -724,34 +721,35 @@ static const auto default_cg_mode = nullptr; //Allow RWE #endif struct MacroJITx64Impl final : public Xbyak::CodeGenerator, public DynamicCachedMacro { - explicit MacroJITx64Impl(std::span code_) + explicit MacroJITx64Impl(Core::System& system, std::span code_) : Xbyak::CodeGenerator(MAX_CODE_SIZE, default_cg_mode) , code{code_} { - Compile(); + Compile(system); } - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) override; + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) override; - void Compile_ALU(Macro::Opcode opcode); - void Compile_AddImmediate(Macro::Opcode opcode); - void Compile_ExtractInsert(Macro::Opcode opcode); - void Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode); - void Compile_ExtractShiftLeftRegister(Macro::Opcode opcode); - void Compile_Read(Macro::Opcode opcode); + void Compile_ALU(Core::System& system, Macro::Opcode opcode); + void Compile_AddImmediate(Core::System& system, Macro::Opcode opcode); + void Compile_ExtractInsert(Core::System& system, Macro::Opcode opcode); + void Compile_ExtractShiftLeftImmediate(Core::System& system, Macro::Opcode opcode); + void Compile_ExtractShiftLeftRegister(Core::System& system, Macro::Opcode opcode); + void Compile_Read(Core::System& system, Macro::Opcode opcode); void Compile_Branch(Macro::Opcode opcode); void Optimizer_ScanFlags(); - void Compile(); - bool Compile_NextInstruction(); + void Compile(Core::System& system); + bool Compile_NextInstruction(Core::System& system); Xbyak::Reg32 Compile_FetchParameter(); Xbyak::Reg32 Compile_GetRegister(u32 index, Xbyak::Reg32 dst); - void Compile_ProcessResult(Macro::ResultOperation operation, u32 reg); - void Compile_Send(Xbyak::Reg32 value); + void Compile_ProcessResult(Core::System& system, Macro::ResultOperation operation, u32 reg); + void Compile_Send(Core::System& system, Xbyak::Reg32 value); Macro::Opcode GetOpCode() const; struct JITState { - Engines::Maxwell3D* maxwell3d{}; + Engines::Maxwell3D* maxwell3d = nullptr; + Core::System* system = nullptr; std::array registers{}; u32 carry_flag{}; }; @@ -777,15 +775,16 @@ struct MacroJITx64Impl final : public Xbyak::CodeGenerator, public DynamicCached std::span code; }; -void MacroJITx64Impl::Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) { +void MacroJITx64Impl::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) { ASSERT_OR_EXECUTE(program != nullptr, { return; }); JITState state{}; state.maxwell3d = &maxwell3d; + state.system = &system; state.registers = {}; program(&state, parameters.data(), parameters.data() + parameters.size()); } -void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ALU(Core::System& system, Macro::Opcode opcode) { const bool is_a_zero = opcode.src_a == 0; const bool is_b_zero = opcode.src_b == 0; const bool valid_operation = !is_a_zero && !is_b_zero; @@ -902,10 +901,10 @@ void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) { UNIMPLEMENTED_MSG("Unimplemented ALU operation {}", opcode.alu_operation.Value()); break; } - Compile_ProcessResult(opcode.result_operation, opcode.dst); + Compile_ProcessResult(system, opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_AddImmediate(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_AddImmediate(Core::System& system, Macro::Opcode opcode) { if (optimizer.skip_dummy_addimmediate) { // Games tend to use this as an exit instruction placeholder. It's to encode an instruction // without doing anything. In our case we can just not emit anything. @@ -940,10 +939,10 @@ void MacroJITx64Impl::Compile_AddImmediate(Macro::Opcode opcode) { sub(result, opcode.immediate * -1); } } - Compile_ProcessResult(opcode.result_operation, opcode.dst); + Compile_ProcessResult(system, opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_ExtractInsert(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ExtractInsert(Core::System& system, Macro::Opcode opcode) { auto dst = Compile_GetRegister(opcode.src_a, RESULT); auto src = Compile_GetRegister(opcode.src_b, eax); @@ -954,10 +953,10 @@ void MacroJITx64Impl::Compile_ExtractInsert(Macro::Opcode opcode) { shl(src, opcode.bf_dst_bit); or_(dst, src); - Compile_ProcessResult(opcode.result_operation, opcode.dst); + Compile_ProcessResult(system, opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Core::System& system, Macro::Opcode opcode) { const auto dst = Compile_GetRegister(opcode.src_a, ecx); const auto src = Compile_GetRegister(opcode.src_b, RESULT); @@ -965,10 +964,10 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) { and_(src, opcode.GetBitfieldMask()); shl(src, opcode.bf_dst_bit); - Compile_ProcessResult(opcode.result_operation, opcode.dst); + Compile_ProcessResult(system, opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Core::System& system, Macro::Opcode opcode) { const auto dst = Compile_GetRegister(opcode.src_a, ecx); const auto src = Compile_GetRegister(opcode.src_b, RESULT); @@ -976,10 +975,10 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) { and_(src, opcode.GetBitfieldMask()); shl(src, dst.cvt8()); - Compile_ProcessResult(opcode.result_operation, opcode.dst); + Compile_ProcessResult(system, opcode.result_operation, opcode.dst); } -void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_Read(Core::System& system, Macro::Opcode opcode) { if (optimizer.zero_reg_skip && opcode.src_a == 0) { if (opcode.immediate == 0) { xor_(RESULT, RESULT); @@ -1005,23 +1004,21 @@ void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { int3(); L(pass_range_check); } - mov(rax, qword[STATE]); - mov(RESULT, - dword[rax + offsetof(Engines::Maxwell3D, regs) + - offsetof(Engines::Maxwell3D::Regs, reg_array) + RESULT.cvt64() * sizeof(u32)]); - - Compile_ProcessResult(opcode.result_operation, opcode.dst); + mov(rax, qword[STATE + offsetof(JITState, maxwell3d)]); + mov(RESULT, dword[rax + offsetof(Engines::Maxwell3D, regs) + offsetof(Engines::Maxwell3D::Regs, reg_array) + RESULT.cvt64() * sizeof(u32)]); + Compile_ProcessResult(system, opcode.result_operation, opcode.dst); } -static void MacroJIT_SendThunk(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { - maxwell3d->CallMethod(method_address.address, value, true); +static void MacroJIT_SendThunk(Core::System* system, Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { + maxwell3d->CallMethod(*system, method_address.address, value, true); } -void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { +void MacroJITx64Impl::Compile_Send(Core::System& system, Xbyak::Reg32 value) { Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); - mov(Common::X64::ABI_PARAM1, qword[STATE]); - mov(Common::X64::ABI_PARAM2.cvt32(), METHOD_ADDRESS); - mov(Common::X64::ABI_PARAM3.cvt32(), value); + mov(Common::X64::ABI_PARAM1, qword[STATE + offsetof(JITState, system)]); + mov(Common::X64::ABI_PARAM2, qword[STATE + offsetof(JITState, maxwell3d)]); + mov(Common::X64::ABI_PARAM3.cvt32(), METHOD_ADDRESS); + mov(Common::X64::ABI_PARAM4.cvt32(), value); Common::X64::CallFarFunction(*this, &MacroJIT_SendThunk); Common::X64::ABI_PopRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); @@ -1045,9 +1042,8 @@ void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { } void MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { - ASSERT_MSG(!is_delay_slot, "Executing a branch in a delay slot is not valid"); - const s32 jump_address = - static_cast(pc) + static_cast(opcode.GetBranchTarget() / sizeof(s32)); + ASSERT(!is_delay_slot && "Executing a branch in a delay slot is not valid"); + const s32 jump_address = s32(pc) + s32(opcode.GetBranchTarget() / sizeof(s32)); Xbyak::Label end; auto value = Compile_GetRegister(opcode.src_a, eax); @@ -1116,7 +1112,7 @@ void MacroJITx64Impl::Optimizer_ScanFlags() { } } -void MacroJITx64Impl::Compile() { +void MacroJITx64Impl::Compile(Core::System& system) { // Matching PROTECT_RE needed for W^X systems setProtectMode(Xbyak::CodeArray::ProtectMode::PROTECT_RW); labels.fill(Xbyak::Label()); @@ -1158,7 +1154,7 @@ void MacroJITx64Impl::Compile() { next_opcode = {}; } pc = i; - Compile_NextInstruction(); + Compile_NextInstruction(system); } L(end_of_code); @@ -1170,7 +1166,7 @@ void MacroJITx64Impl::Compile() { program = getCode(); } -bool MacroJITx64Impl::Compile_NextInstruction() { +bool MacroJITx64Impl::Compile_NextInstruction(Core::System& system) { const auto opcode = GetOpCode(); if (labels[pc].getAddress()) { return false; @@ -1180,22 +1176,22 @@ bool MacroJITx64Impl::Compile_NextInstruction() { switch (opcode.operation) { case Macro::Operation::ALU: - Compile_ALU(opcode); + Compile_ALU(system, opcode); break; case Macro::Operation::AddImmediate: - Compile_AddImmediate(opcode); + Compile_AddImmediate(system, opcode); break; case Macro::Operation::ExtractInsert: - Compile_ExtractInsert(opcode); + Compile_ExtractInsert(system, opcode); break; case Macro::Operation::ExtractShiftLeftImmediate: - Compile_ExtractShiftLeftImmediate(opcode); + Compile_ExtractShiftLeftImmediate(system, opcode); break; case Macro::Operation::ExtractShiftLeftRegister: - Compile_ExtractShiftLeftRegister(opcode); + Compile_ExtractShiftLeftRegister(system, opcode); break; case Macro::Operation::Read: - Compile_Read(opcode); + Compile_Read(system, opcode); break; case Macro::Operation::Branch: Compile_Branch(opcode); @@ -1267,7 +1263,7 @@ Xbyak::Reg32 MacroJITx64Impl::Compile_GetRegister(u32 index, Xbyak::Reg32 dst) { return dst; } -void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u32 reg) { +void MacroJITx64Impl::Compile_ProcessResult(Core::System& system, Macro::ResultOperation operation, u32 reg) { const auto SetRegister = [this](u32 reg_index, const Xbyak::Reg32& result) { // Register 0 is supposed to always return 0. NOP is implemented as a store to the zero // register. @@ -1292,12 +1288,12 @@ void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u3 case Macro::ResultOperation::FetchAndSend: // Fetch parameter and send result. SetRegister(reg, Compile_FetchParameter()); - Compile_Send(RESULT); + Compile_Send(system, RESULT); break; case Macro::ResultOperation::MoveAndSend: // Move and send result. SetRegister(reg, RESULT); - Compile_Send(RESULT); + Compile_Send(system, RESULT); break; case Macro::ResultOperation::FetchAndSetMethod: // Fetch parameter and use result as Method Address. @@ -1308,7 +1304,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u3 // Move result and use as Method Address, then fetch and send parameter. SetRegister(reg, RESULT); SetMethodAddress(RESULT); - Compile_Send(Compile_FetchParameter()); + Compile_Send(system, Compile_FetchParameter()); break; case Macro::ResultOperation::MoveAndSetMethodSend: // Move result and use as Method Address, then send bits 12:17 of result. @@ -1316,7 +1312,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u3 SetMethodAddress(RESULT); shr(RESULT, 12); and_(RESULT, 0b111111); - Compile_Send(RESULT); + Compile_Send(system, RESULT); break; default: UNIMPLEMENTED_MSG("Unimplemented macro operation {}", operation); @@ -1357,36 +1353,36 @@ static void Dump(u64 hash, std::span code, bool decompiled = false) { macro_file.write(reinterpret_cast(code.data()), code.size_bytes()); } -void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters) { - auto const execute_variant = [&maxwell3d, ¶meters, method](AnyCachedMacro& acm) { +void MacroEngine::Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters) { + auto const execute_variant = [&system, &maxwell3d, ¶meters, method](AnyCachedMacro& acm) { if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if(&acm)) - a->Execute(maxwell3d, parameters, method); + a->Execute(system, maxwell3d, parameters, method); if (auto a = std::get_if>(&acm)) - a->get()->Execute(maxwell3d, parameters, method); + a->get()->Execute(system, maxwell3d, parameters, method); }; if (auto const it = macro_cache.find(method); it != macro_cache.end()) { auto& ci = it->second; @@ -1417,9 +1413,9 @@ void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, std::spansecond); + ci.program = Compile(system, maxwell3d, macro_code->second); ci.hash = Common::HashValue(macro_code->second); } if (CanBeHLEProgram(ci.hash) && !Settings::values.disable_macro_hle) { @@ -1434,10 +1430,10 @@ void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, std::span code) { +AnyCachedMacro MacroEngine::Compile(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span code) { #ifdef ARCHITECTURE_x86_64 if (!is_interpreted) - return std::make_unique(code); + return std::make_unique(system, code); #endif return MacroInterpreterImpl(code); } diff --git a/src/video_core/macro.h b/src/video_core/macro.h index a9a8f2de04..43b32ed920 100644 --- a/src/video_core/macro.h +++ b/src/video_core/macro.h @@ -14,6 +14,10 @@ #include "common/bit_field.h" #include "common/common_types.h" +namespace Core { +class System; +} + namespace Tegra { namespace Engines { @@ -106,61 +110,61 @@ struct HLEMacro { /// also assigning the base vertex/instance. struct HLE_DrawArraysIndirect final { HLE_DrawArraysIndirect(bool extended_) noexcept : extended{extended_} {} - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); bool extended; }; /// @note: these macros have two versions, a normal and extended version, with the extended version /// also assigning the base vertex/instance. struct HLE_DrawIndexedIndirect final { explicit HLE_DrawIndexedIndirect(bool extended_) noexcept : extended{extended_} {} - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); bool extended; }; struct HLE_MultiLayerClear final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_MultiDrawIndexedIndirectCount final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); }; struct HLE_DrawIndirectByteCount final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); - void Fallback(Engines::Maxwell3D& maxwell3d, std::span parameters); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Fallback(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters); }; struct HLE_C713C83D8F63CCF3 final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_D7333D26E0A93EDE final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_BindShader final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_SetRasterBoundingBox final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct HLE_ClearConstBuffer final { HLE_ClearConstBuffer(size_t base_size_) noexcept : base_size{base_size_} {} - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); size_t base_size; }; struct HLE_ClearMemory final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); std::vector zero_memory; }; struct HLE_TransformFeedbackSetup final { - void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, [[maybe_unused]] u32 method); }; struct MacroInterpreterImpl final { MacroInterpreterImpl() {} MacroInterpreterImpl(std::span code_) : code{code_} {} - void Execute(Engines::Maxwell3D& maxwell3d, std::span params, u32 method); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span params, u32 method); void Reset(); - bool Step(Engines::Maxwell3D& maxwell3d, bool is_delay_slot); + bool Step(Core::System& system, Engines::Maxwell3D& maxwell3d, bool is_delay_slot); u32 GetALUResult(Macro::ALUOperation operation, u32 src_a, u32 src_b); - void ProcessResult(Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result); + void ProcessResult(Core::System& system, Engines::Maxwell3D& maxwell3d, Macro::ResultOperation operation, u32 reg, u32 result); bool EvaluateBranchCondition(Macro::BranchCondition cond, u32 value) const; Macro::Opcode GetOpcode() const; u32 GetRegister(u32 register_id) const; @@ -169,7 +173,7 @@ struct MacroInterpreterImpl final { [[nodiscard]] inline void SetMethodAddress(u32 address) noexcept { method_address.raw = address; } - void Send(Engines::Maxwell3D& maxwell3d, u32 value); + void Send(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 value); u32 Read(Engines::Maxwell3D& maxwell3d, u32 method) const; u32 FetchParameter(); /// General purpose macro registers. @@ -192,7 +196,7 @@ struct DynamicCachedMacro { /// Executes the macro code with the specified input parameters. /// @param parameters The parameters of the macro /// @param method The method to execute - virtual void Execute(Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) = 0; + virtual void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span parameters, u32 method) = 0; }; using AnyCachedMacro = std::variant< @@ -227,8 +231,8 @@ struct MacroEngine { uploaded_macro_code.erase(method); } // Compiles the macro if its not in the cache, and executes the compiled macro - void Execute(Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters); - AnyCachedMacro Compile(Engines::Maxwell3D& maxwell3d, std::span code); + void Execute(Core::System& system, Engines::Maxwell3D& maxwell3d, u32 method, std::span parameters); + AnyCachedMacro Compile(Core::System& system, Engines::Maxwell3D& maxwell3d, std::span code); struct CacheInfo { AnyCachedMacro program; u64 hash{}; diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp index d53b422cac..dc91723300 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.cpp +++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -204,7 +207,7 @@ void SetupDirtyMisc(Tables& tables) { } // Anonymous namespace void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { - auto& tables{channel_state.maxwell_3d->dirty.tables}; + auto& tables{channel_state.payload->maxwell_3d.dirty.tables}; SetupDirtyFlags(tables); SetupDirtyColorMasks(tables); SetupDirtyViewports(tables); @@ -231,7 +234,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { } void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) { - flags = &channel_state.maxwell_3d->dirty.flags; + flags = &channel_state.payload->maxwell_3d.dirty.flags; } void StateTracker::InvalidateState() { diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 2bca1ba28f..d99e528bc0 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -502,9 +502,9 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, two_textures_set_layout(device.GetLogical().CreateDescriptorSetLayout( TWO_TEXTURES_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)), one_texture_descriptor_allocator{ - descriptor_pool.Allocator(*one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, + descriptor_pool.Allocator(device_, scheduler_, *one_texture_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<1>)}, two_textures_descriptor_allocator{ - descriptor_pool.Allocator(*two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, + descriptor_pool.Allocator(device_, scheduler_, *two_textures_set_layout, TEXTURE_DESCRIPTOR_BANK_INFO<2>)}, one_texture_pipeline_layout(device.GetLogical().CreatePipelineLayout(PipelineLayoutCreateInfo( one_texture_set_layout.address(), PUSH_CONSTANT_RANGE))), diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.cpp b/src/video_core/renderer_vulkan/pipeline_statistics.cpp index ad288436a8..04f42c71a6 100644 --- a/src/video_core/renderer_vulkan/pipeline_statistics.cpp +++ b/src/video_core/renderer_vulkan/pipeline_statistics.cpp @@ -31,14 +31,13 @@ static u64 GetUint64(const VkPipelineExecutableStatisticKHR& statistic) { } } -PipelineStatistics::PipelineStatistics(const Device& device_) : device{device_} {} +PipelineStatistics::PipelineStatistics(const Device& device_) {} -void PipelineStatistics::Collect(VkPipeline pipeline) { - const auto& dev{device.GetLogical()}; - const std::vector properties{dev.GetPipelineExecutablePropertiesKHR(pipeline)}; +void PipelineStatistics::Collect(const Device& device, VkPipeline pipeline) { + const std::vector properties{device.GetLogical().GetPipelineExecutablePropertiesKHR(pipeline)}; const u32 num_executables{static_cast(properties.size())}; for (u32 executable = 0; executable < num_executables; ++executable) { - const auto statistics{dev.GetPipelineExecutableStatisticsKHR(pipeline, executable)}; + const auto statistics{device.GetLogical().GetPipelineExecutableStatisticsKHR(pipeline, executable)}; if (statistics.empty()) { continue; } diff --git a/src/video_core/renderer_vulkan/pipeline_statistics.h b/src/video_core/renderer_vulkan/pipeline_statistics.h index 197bb09363..83e70b704f 100644 --- a/src/video_core/renderer_vulkan/pipeline_statistics.h +++ b/src/video_core/renderer_vulkan/pipeline_statistics.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,9 +19,7 @@ class Device; class PipelineStatistics { public: explicit PipelineStatistics(const Device& device_); - - void Collect(VkPipeline pipeline); - + void Collect(const Device& device, VkPipeline pipeline); void Report() const; private: @@ -30,8 +31,6 @@ private: u64 branches_count{}; u64 basic_block_count{}; }; - - const Device& device; mutable std::mutex mutex; std::vector collected_stats; }; diff --git a/src/video_core/renderer_vulkan/present/anti_alias_pass.h b/src/video_core/renderer_vulkan/present/anti_alias_pass.h index 4990e87502..8061d01208 100644 --- a/src/video_core/renderer_vulkan/present/anti_alias_pass.h +++ b/src/video_core/renderer_vulkan/present/anti_alias_pass.h @@ -11,12 +11,12 @@ namespace Vulkan { class Scheduler; +class Device; class AntiAliasPass { public: virtual ~AntiAliasPass() = default; - virtual void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, - VkImageView* inout_image_view) = 0; + virtual void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) = 0; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/fsr.cpp b/src/video_core/renderer_vulkan/present/fsr.cpp index ba6252ed95..894fb144f0 100644 --- a/src/video_core/renderer_vulkan/present/fsr.cpp +++ b/src/video_core/renderer_vulkan/present/fsr.cpp @@ -25,74 +25,74 @@ using namespace FSR; using PushConstants = std::array; -FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, - VkExtent2D extent) - : m_device{device}, m_memory_allocator{memory_allocator}, - m_image_count{image_count}, m_extent{extent} { - - CreateImages(); - CreateRenderPasses(); - CreateSampler(); - CreateShaders(); - CreateDescriptorPool(); - CreateDescriptorSetLayout(); - CreateDescriptorSets(); - CreatePipelineLayouts(); - CreatePipelines(); +FSR::FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent) + : m_memory_allocator{memory_allocator} + , m_image_count{image_count} + , m_extent{extent} +{ + CreateImages(device); + CreateRenderPasses(device); + CreateSampler(device); + CreateShaders(device); + CreateDescriptorPool(device); + CreateDescriptorSetLayout(device); + CreateDescriptorSets(device); + CreatePipelineLayouts(device); + CreatePipelines(device); } -void FSR::CreateImages() { +void FSR::CreateImages(const Device& device) { m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.images[Easu] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); images.images[Rcas] = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_views[Easu] = CreateWrappedImageView(m_device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_views[Rcas] = CreateWrappedImageView(m_device, images.images[Rcas], VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_views[Easu] = CreateWrappedImageView(device, images.images[Easu], VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_views[Rcas] = CreateWrappedImageView(device, images.images[Rcas], VK_FORMAT_R16G16B16A16_SFLOAT); } } -void FSR::CreateRenderPasses() { - m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); +void FSR::CreateRenderPasses(const Device& device) { + m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& images : m_dynamic_images) { - images.framebuffers[Easu] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Easu], m_extent); - images.framebuffers[Rcas] = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_views[Rcas], m_extent); + images.framebuffers[Easu] = CreateWrappedFramebuffer(device, m_renderpass, images.image_views[Easu], m_extent); + images.framebuffers[Rcas] = CreateWrappedFramebuffer(device, m_renderpass, images.image_views[Rcas], m_extent); } } -void FSR::CreateSampler() { - m_sampler = CreateBilinearSampler(m_device); +void FSR::CreateSampler(const Device& device) { + m_sampler = CreateBilinearSampler(device); } -void FSR::CreateShaders() { - m_vert_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_VERT_SPV); +void FSR::CreateShaders(const Device& device) { + m_vert_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_VERT_SPV); - if (m_device.IsFloat16Supported()) { - m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV); - m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV); + if (device.IsFloat16Supported()) { + m_easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP16_FRAG_SPV); + m_rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP16_FRAG_SPV); } else { - m_easu_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV); - m_rcas_shader = BuildShader(m_device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV); + m_easu_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_EASU_FP32_FRAG_SPV); + m_rcas_shader = BuildShader(device, VULKAN_FIDELITYFX_FSR_RCAS_FP32_FRAG_SPV); } } -void FSR::CreateDescriptorPool() { +void FSR::CreateDescriptorPool(const Device& device) { // EASU: 1 descriptor // RCAS: 1 descriptor // 2 descriptors, 2 descriptor sets per invocation - m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, 2 * m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(device, 2 * m_image_count, 2 * m_image_count); } -void FSR::CreateDescriptorSetLayout() { - m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); +void FSR::CreateDescriptorSetLayout(const Device& device) { + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void FSR::CreateDescriptorSets() { +void FSR::CreateDescriptorSets(const Device& device) { std::vector layouts(MaxFsrStage, *m_descriptor_set_layout); for (auto& images : m_dynamic_images) images.descriptor_sets = CreateWrappedDescriptorSets(m_descriptor_pool, layouts); } -void FSR::CreatePipelineLayouts() { +void FSR::CreatePipelineLayouts(const Device& device) { const VkPushConstantRange range{ .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, .offset = 0, @@ -108,17 +108,17 @@ void FSR::CreatePipelineLayouts() { .pPushConstantRanges = &range, }; - m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); + m_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); } -void FSR::CreatePipelines() { - m_easu_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, +void FSR::CreatePipelines(const Device& device) { + m_easu_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_easu_shader)); - m_rcas_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, + m_rcas_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_rcas_shader)); } -void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { +void FSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; image_infos.reserve(2); @@ -126,10 +126,10 @@ void FSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[Easu], 0), CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Easu], images.descriptor_sets[Rcas], 0) }; - m_device.GetLogical().UpdateDescriptorSets(updates, {}); + device.GetLogical().UpdateDescriptorSets(updates, {}); } -void FSR::UploadImages(Scheduler& scheduler) { +void FSR::UploadImages(const Device& device, Scheduler& scheduler) { if (!m_images_ready) { m_images_ready = true; scheduler.Record([&](vk::CommandBuffer cmdbuf) { @@ -142,7 +142,7 @@ void FSR::UploadImages(Scheduler& scheduler) { } } -VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, +VkImageView FSR::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; @@ -179,8 +179,8 @@ VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_i static_cast(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; FsrRcasCon(rcas_con.data(), sharpening); - UploadImages(scheduler); - UpdateDescriptorSets(source_image_view, image_index); + UploadImages(device, scheduler); + UpdateDescriptorSets(device, source_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/fsr.h b/src/video_core/renderer_vulkan/present/fsr.h index 8602e81465..7762480757 100644 --- a/src/video_core/renderer_vulkan/present/fsr.h +++ b/src/video_core/renderer_vulkan/present/fsr.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,27 +17,25 @@ class Scheduler; class FSR { public: - explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, - VkExtent2D extent); - VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, + explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent); + VkImageView Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); private: - void CreateImages(); - void CreateRenderPasses(); - void CreateSampler(); - void CreateShaders(); - void CreateDescriptorPool(); - void CreateDescriptorSetLayout(); - void CreateDescriptorSets(); - void CreatePipelineLayouts(); - void CreatePipelines(); + void CreateImages(const Device& device); + void CreateRenderPasses(const Device& device); + void CreateSampler(const Device& device); + void CreateShaders(const Device& device); + void CreateDescriptorPool(const Device& device); + void CreateDescriptorSetLayout(const Device& device); + void CreateDescriptorSets(const Device& device); + void CreatePipelineLayouts(const Device& device); + void CreatePipelines(const Device& device); - void UploadImages(Scheduler& scheduler); - void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + void UploadImages(const Device& device, Scheduler& scheduler); + void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); - const Device& m_device; MemoryAllocator& m_memory_allocator; const size_t m_image_count; const VkExtent2D m_extent; diff --git a/src/video_core/renderer_vulkan/present/fxaa.cpp b/src/video_core/renderer_vulkan/present/fxaa.cpp index bdafd1f4d0..62f79d490c 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.cpp +++ b/src/video_core/renderer_vulkan/present/fxaa.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,61 +17,60 @@ namespace Vulkan { FXAA::FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) - : m_device(device), m_allocator(allocator), m_extent(extent), - m_image_count(static_cast(image_count)) { - CreateImages(); - CreateRenderPasses(); - CreateSampler(); - CreateShaders(); - CreateDescriptorPool(); - CreateDescriptorSetLayouts(); - CreateDescriptorSets(); - CreatePipelineLayouts(); - CreatePipelines(); + : m_extent(extent) + , m_image_count(u32(image_count)) +{ + CreateImages(device, allocator); + CreateRenderPasses(device); + CreateSampler(device); + CreateShaders(device); + CreateDescriptorPool(device); + CreateDescriptorSetLayouts(device); + CreateDescriptorSets(device); + CreatePipelineLayouts(device); + CreatePipelines(device); } FXAA::~FXAA() = default; -void FXAA::CreateImages() { +void FXAA::CreateImages(const Device& device, MemoryAllocator& allocator) { for (u32 i = 0; i < m_image_count; i++) { Image& image = m_dynamic_images.emplace_back(); - - image.image = CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - image.image_view = - CreateWrappedImageView(m_device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT); + image.image = CreateWrappedImage(allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); + image.image_view = CreateWrappedImageView(device, image.image, VK_FORMAT_R16G16B16A16_SFLOAT); } } -void FXAA::CreateRenderPasses() { - m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); +void FXAA::CreateRenderPasses(const Device& device) { + m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& image : m_dynamic_images) { image.framebuffer = - CreateWrappedFramebuffer(m_device, m_renderpass, image.image_view, m_extent); + CreateWrappedFramebuffer(device, m_renderpass, image.image_view, m_extent); } } -void FXAA::CreateSampler() { - m_sampler = CreateWrappedSampler(m_device); +void FXAA::CreateSampler(const Device& device) { + m_sampler = CreateWrappedSampler(device); } -void FXAA::CreateShaders() { - m_vertex_shader = CreateWrappedShaderModule(m_device, FXAA_VERT_SPV); - m_fragment_shader = CreateWrappedShaderModule(m_device, FXAA_FRAG_SPV); +void FXAA::CreateShaders(const Device& device) { + m_vertex_shader = CreateWrappedShaderModule(device, FXAA_VERT_SPV); + m_fragment_shader = CreateWrappedShaderModule(device, FXAA_FRAG_SPV); } -void FXAA::CreateDescriptorPool() { +void FXAA::CreateDescriptorPool(const Device& device) { // 2 descriptors, 1 descriptor set per image - m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 2 * m_image_count, m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(device, 2 * m_image_count, m_image_count); } -void FXAA::CreateDescriptorSetLayouts() { +void FXAA::CreateDescriptorSetLayouts(const Device& device) { m_descriptor_set_layout = - CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void FXAA::CreateDescriptorSets() { +void FXAA::CreateDescriptorSets(const Device& device) { VkDescriptorSetLayout layout = *m_descriptor_set_layout; for (auto& images : m_dynamic_images) { @@ -76,30 +78,28 @@ void FXAA::CreateDescriptorSets() { } } -void FXAA::CreatePipelineLayouts() { - m_pipeline_layout = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layout); +void FXAA::CreatePipelineLayouts(const Device& device) { + m_pipeline_layout = CreateWrappedPipelineLayout(device, m_descriptor_set_layout); } -void FXAA::CreatePipelines() { - m_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, +void FXAA::CreatePipelines(const Device& device) { + m_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, std::tie(m_vertex_shader, m_fragment_shader)); } -void FXAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { +void FXAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { Image& image = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; image_infos.reserve(2); - updates.push_back( - CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0)); - updates.push_back( - CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1)); + updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 0)); + updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, image.descriptor_sets[0], 1)); - m_device.GetLogical().UpdateDescriptorSets(updates, {}); + device.GetLogical().UpdateDescriptorSets(updates, {}); } -void FXAA::UploadImages(Scheduler& scheduler) { +void FXAA::UploadImages(const Device& device, Scheduler& scheduler) { if (m_images_ready) { return; } @@ -114,8 +114,7 @@ void FXAA::UploadImages(Scheduler& scheduler) { m_images_ready = true; } -void FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, - VkImageView* inout_image_view) { +void FXAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) { const Image& image{m_dynamic_images[image_index]}; const VkImage input_image{*inout_image}; const VkImage output_image{*image.image}; @@ -126,8 +125,8 @@ void FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, const VkPipelineLayout layout{*m_pipeline_layout}; const VkExtent2D extent{m_extent}; - UploadImages(scheduler); - UpdateDescriptorSets(*inout_image_view, image_index); + UploadImages(device, scheduler); + UpdateDescriptorSets(device, *inout_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/fxaa.h b/src/video_core/renderer_vulkan/present/fxaa.h index 97a2e5c1cb..7eaf31f81c 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.h +++ b/src/video_core/renderer_vulkan/present/fxaa.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,38 +18,23 @@ class StagingBufferPool; class FXAA final : public AntiAliasPass { public: - explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, - VkExtent2D extent); + explicit FXAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent); ~FXAA() override; - void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, - VkImageView* inout_image_view) override; + void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) override; private: - void CreateImages(); - void CreateRenderPasses(); - void CreateSampler(); - void CreateShaders(); - void CreateDescriptorPool(); - void CreateDescriptorSetLayouts(); - void CreateDescriptorSets(); - void CreatePipelineLayouts(); - void CreatePipelines(); - void UpdateDescriptorSets(VkImageView image_view, size_t image_index); - void UploadImages(Scheduler& scheduler); - - const Device& m_device; - MemoryAllocator& m_allocator; - const VkExtent2D m_extent; - const u32 m_image_count; - - vk::ShaderModule m_vertex_shader{}; - vk::ShaderModule m_fragment_shader{}; - vk::DescriptorPool m_descriptor_pool{}; - vk::DescriptorSetLayout m_descriptor_set_layout{}; - vk::PipelineLayout m_pipeline_layout{}; - vk::Pipeline m_pipeline{}; - vk::RenderPass m_renderpass{}; + void CreateImages(const Device& device, MemoryAllocator& allocator); + void CreateRenderPasses(const Device& device); + void CreateSampler(const Device& device); + void CreateShaders(const Device& device); + void CreateDescriptorPool(const Device& device); + void CreateDescriptorSetLayouts(const Device& device); + void CreateDescriptorSets(const Device& device); + void CreatePipelineLayouts(const Device& device); + void CreatePipelines(const Device& device); + void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); + void UploadImages(const Device& device, Scheduler& scheduler); struct Image { vk::DescriptorSets descriptor_sets{}; @@ -55,9 +43,17 @@ private: vk::ImageView image_view{}; }; std::vector m_dynamic_images{}; - bool m_images_ready{}; - + const VkExtent2D m_extent; + const u32 m_image_count; + vk::ShaderModule m_vertex_shader{}; + vk::ShaderModule m_fragment_shader{}; + vk::DescriptorPool m_descriptor_pool{}; + vk::DescriptorSetLayout m_descriptor_set_layout{}; + vk::PipelineLayout m_pipeline_layout{}; + vk::Pipeline m_pipeline{}; + vk::RenderPass m_renderpass{}; vk::Sampler m_sampler{}; + bool m_images_ready{}; }; } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index e20473d2af..14935f92bb 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -56,13 +56,15 @@ VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { } // Anonymous namespace -Layer::Layer(const Device& device_, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, - Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_, - VkExtent2D output_size, VkDescriptorSetLayout layout, const PresentFilters& filters_) - : device(device_), memory_allocator(memory_allocator_), scheduler(scheduler_), - device_memory(device_memory_), filters(filters_), image_count(image_count_) { - CreateDescriptorPool(); - CreateDescriptorSets(layout); +Layer::Layer(const Device& device, MemoryAllocator& memory_allocator_, Scheduler& scheduler_, Tegra::MaxwellDeviceMemoryManager& device_memory_, size_t image_count_, VkExtent2D output_size, VkDescriptorSetLayout layout, const PresentFilters& filters_) + : memory_allocator(memory_allocator_) + , scheduler(scheduler_) + , device_memory(device_memory_) + , filters(filters_) + , image_count(image_count_) +{ + CreateDescriptorPool(device); + CreateDescriptorSets(device, layout); if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) { sr_filter.emplace(device, memory_allocator, image_count, output_size); } else if (filters.get_scaling_filter() == Settings::ScalingFilter::Sgsr) { @@ -76,7 +78,7 @@ Layer::~Layer() { ReleaseRawImages(); } -void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, +void Layer::ConfigureDraw(const Device& device, PresentPushConstants* out_push_constants, VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer, VkSampler sampler, size_t image_index, const Tegra::FramebufferConfig& framebuffer, @@ -89,8 +91,8 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, const u32 scaled_height = texture_info ? texture_info->scaled_height : texture_height; const bool use_accelerated = texture_info.has_value(); - RefreshResources(framebuffer); - SetAntiAliasPass(); + RefreshResources(device, framebuffer); + SetAntiAliasPass(device); // Finish any pending renderpass scheduler.RequestOutsideRenderPassOperationContext(); @@ -108,9 +110,9 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, texture_info ? texture_info->image_view : *raw_image_views[image_index]; if (auto* fxaa = std::get_if(&anti_alias)) { - fxaa->Draw(scheduler, image_index, &source_image, &source_image_view); + fxaa->Draw(device, scheduler, image_index, &source_image, &source_image_view); } else if (auto* smaa = std::get_if(&anti_alias)) { - smaa->Draw(scheduler, image_index, &source_image, &source_image_view); + smaa->Draw(device, scheduler, image_index, &source_image, &source_image_view); } auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); @@ -120,30 +122,30 @@ void Layer::ConfigureDraw(PresentPushConstants* out_push_constants, }; if (auto* fsr = std::get_if(&sr_filter)) { - source_image_view = fsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); + source_image_view = fsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; } else if (auto* sgsr = std::get_if(&sr_filter)) { - source_image_view = sgsr->Draw(scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); + source_image_view = sgsr->Draw(device, scheduler, image_index, source_image, source_image_view, render_extent, crop_rect); crop_rect = {0, 0, 1, 1}; } - SetMatrixData(*out_push_constants, layout); - SetVertexData(*out_push_constants, layout, crop_rect); + SetMatrixData(device, *out_push_constants, layout); + SetVertexData(device, *out_push_constants, layout, crop_rect); - UpdateDescriptorSet(source_image_view, sampler, image_index); + UpdateDescriptorSet(device, source_image_view, sampler, image_index); *out_descriptor_set = descriptor_sets[image_index]; } -void Layer::CreateDescriptorPool() { +void Layer::CreateDescriptorPool(const Device& device) { descriptor_pool = CreateWrappedDescriptorPool(device, image_count, image_count); } -void Layer::CreateDescriptorSets(VkDescriptorSetLayout layout) { +void Layer::CreateDescriptorSets(const Device& device, VkDescriptorSetLayout layout) { const std::vector layouts(image_count, layout); descriptor_sets = CreateWrappedDescriptorSets(descriptor_pool, layouts); } -void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { +void Layer::CreateStagingBuffer(const Device& device, const Tegra::FramebufferConfig& framebuffer) { const VkBufferCreateInfo ci{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, @@ -159,7 +161,7 @@ void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload); } -void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { +void Layer::CreateRawImages(const Device& device, const Tegra::FramebufferConfig& framebuffer) { const auto format = GetFormat(framebuffer); resource_ticks.resize(image_count); raw_images.resize(image_count); @@ -172,7 +174,7 @@ void Layer::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { } } -void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { +void Layer::RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer) { if (framebuffer.width == raw_width && framebuffer.height == raw_height && framebuffer.pixel_format == pixel_format && !raw_images.empty()) { return; @@ -184,11 +186,11 @@ void Layer::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { anti_alias.emplace(); ReleaseRawImages(); - CreateStagingBuffer(framebuffer); - CreateRawImages(framebuffer); + CreateStagingBuffer(device, framebuffer); + CreateRawImages(device, framebuffer); } -void Layer::SetAntiAliasPass() { +void Layer::SetAntiAliasPass(const Device& device) { if (!std::holds_alternative(anti_alias) && anti_alias_setting == filters.get_anti_aliasing()) return; @@ -229,20 +231,17 @@ u64 Layer::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, return GetSizeInBytes(framebuffer) * image_index; } -void Layer::SetMatrixData(PresentPushConstants& data, - const Layout::FramebufferLayout& layout) const { - data.modelview_matrix = - MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); +void Layer::SetMatrixData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout) const { + data.modelview_matrix = MakeOrthographicMatrix(f32(layout.width), static_cast(layout.height)); } -void Layer::SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout, - const Common::Rectangle& crop) const { +void Layer::SetVertexData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout, const Common::Rectangle& crop) const { // Map the coordinates to the screen. const auto& screen = layout.screen; - const auto x = static_cast(screen.left); - const auto y = static_cast(screen.top); - const auto w = static_cast(screen.GetWidth()); - const auto h = static_cast(screen.GetHeight()); + const auto x = f32(screen.left); + const auto y = f32(screen.top); + const auto w = f32(screen.GetWidth()); + const auto h = f32(screen.GetHeight()); data.vertices[0] = ScreenRectVertex(x, y, crop.left, crop.top); data.vertices[1] = ScreenRectVertex(x + w, y, crop.right, crop.top); @@ -250,7 +249,7 @@ void Layer::SetVertexData(PresentPushConstants& data, const Layout::FramebufferL data.vertices[3] = ScreenRectVertex(x + w, y + h, crop.right, crop.bottom); } -void Layer::UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index) { +void Layer::UpdateDescriptorSet(const Device& device, VkImageView image_view, VkSampler sampler, size_t image_index) { const VkDescriptorImageInfo image_info{ .sampler = sampler, .imageView = image_view, diff --git a/src/video_core/renderer_vulkan/present/layer.h b/src/video_core/renderer_vulkan/present/layer.h index 47a6a69218..4d75e86ba6 100644 --- a/src/video_core/renderer_vulkan/present/layer.h +++ b/src/video_core/renderer_vulkan/present/layer.h @@ -52,33 +52,31 @@ public: const PresentFilters& filters); ~Layer(); - void ConfigureDraw(PresentPushConstants* out_push_constants, + void ConfigureDraw(const Device& device, PresentPushConstants* out_push_constants, VkDescriptorSet* out_descriptor_set, RasterizerVulkan& rasterizer, VkSampler sampler, size_t image_index, const Tegra::FramebufferConfig& framebuffer, const Layout::FramebufferLayout& layout); private: - void CreateDescriptorPool(); - void CreateDescriptorSets(VkDescriptorSetLayout layout); - void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer); - void CreateRawImages(const Tegra::FramebufferConfig& framebuffer); + void CreateDescriptorPool(const Device& device); + void CreateDescriptorSets(const Device& device, VkDescriptorSetLayout layout); + void CreateStagingBuffer(const Device& device, const Tegra::FramebufferConfig& framebuffer); + void CreateRawImages(const Device& device, const Tegra::FramebufferConfig& framebuffer); - void RefreshResources(const Tegra::FramebufferConfig& framebuffer); - void SetAntiAliasPass(); + void RefreshResources(const Device& device, const Tegra::FramebufferConfig& framebuffer); + void SetAntiAliasPass(const Device& device); void ReleaseRawImages(); u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, size_t image_index) const; - void SetMatrixData(PresentPushConstants& data, const Layout::FramebufferLayout& layout) const; - void SetVertexData(PresentPushConstants& data, const Layout::FramebufferLayout& layout, - const Common::Rectangle& crop) const; - void UpdateDescriptorSet(VkImageView image_view, VkSampler sampler, size_t image_index); + void SetMatrixData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout) const; + void SetVertexData(const Device& device, PresentPushConstants& data, const Layout::FramebufferLayout& layout, const Common::Rectangle& crop) const; + void UpdateDescriptorSet(const Device& device, VkImageView image_view, VkSampler sampler, size_t image_index); void UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t image_index); private: - const Device& device; MemoryAllocator& memory_allocator; Scheduler& scheduler; Tegra::MaxwellDeviceMemoryManager& device_memory; diff --git a/src/video_core/renderer_vulkan/present/sgsr.cpp b/src/video_core/renderer_vulkan/present/sgsr.cpp index 4175190690..5fc746458d 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.cpp +++ b/src/video_core/renderer_vulkan/present/sgsr.cpp @@ -20,8 +20,7 @@ namespace Vulkan { using PushConstants = std::array; SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir) - : m_device{device} - , m_memory_allocator{memory_allocator} + : m_memory_allocator{memory_allocator} , m_image_count{image_count} , m_extent{extent} , m_edge_dir{edge_dir} @@ -30,21 +29,21 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image m_dynamic_images.resize(m_image_count); for (auto& images : m_dynamic_images) { images.image = CreateWrappedImage(m_memory_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); - images.image_view = CreateWrappedImageView(m_device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT); + images.image_view = CreateWrappedImageView(device, images.image, VK_FORMAT_R16G16B16A16_SFLOAT); } - m_renderpass = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); + m_renderpass = CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& images : m_dynamic_images) - images.framebuffer = CreateWrappedFramebuffer(m_device, m_renderpass, images.image_view, m_extent); + images.framebuffer = CreateWrappedFramebuffer(device, m_renderpass, images.image_view, m_extent); - m_sampler = CreateBilinearSampler(m_device); - m_vert_shader = BuildShader(m_device, SGSR1_SHADER_VERT_SPV); + m_sampler = CreateBilinearSampler(device); + m_vert_shader = BuildShader(device, SGSR1_SHADER_VERT_SPV); m_stage_shader = m_edge_dir - ? BuildShader(m_device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV) - : BuildShader(m_device, SGSR1_SHADER_MOBILE_FRAG_SPV); + ? BuildShader(device, SGSR1_SHADER_MOBILE_EDGE_DIRECTION_FRAG_SPV) + : BuildShader(device, SGSR1_SHADER_MOBILE_FRAG_SPV); // 2 descriptors, 2 descriptor sets per invocation - m_descriptor_pool = CreateWrappedDescriptorPool(m_device, m_image_count, m_image_count); - m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + m_descriptor_pool = CreateWrappedDescriptorPool(device, m_image_count, m_image_count); + m_descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); VkDescriptorSetLayout layout = *m_descriptor_set_layout; for (auto& images : m_dynamic_images) @@ -64,20 +63,20 @@ SGSR::SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image .pushConstantRangeCount = 1, .pPushConstantRanges = &range, }; - m_pipeline_layout = m_device.GetLogical().CreatePipelineLayout(ci); - m_stage_pipeline = CreateWrappedPipeline(m_device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader)); + m_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci); + m_stage_pipeline = CreateWrappedPipeline(device, m_renderpass, m_pipeline_layout, std::tie(m_vert_shader, m_stage_shader)); } -void SGSR::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { +void SGSR::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; image_infos.reserve(1); updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, image_view, images.descriptor_sets[0], 0)); - m_device.GetLogical().UpdateDescriptorSets(updates, {}); + device.GetLogical().UpdateDescriptorSets(updates, {}); } -void SGSR::UploadImages(Scheduler& scheduler) { +void SGSR::UploadImages(const Device& device, Scheduler& scheduler) { if (!m_images_ready) { scheduler.Record([&](vk::CommandBuffer cmdbuf) { for (auto& image : m_dynamic_images) @@ -88,7 +87,7 @@ void SGSR::UploadImages(Scheduler& scheduler) { } } -VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { +VkImageView SGSR::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect) { Images& images = m_dynamic_images[image_index]; auto const output_image = *images.image; auto const descriptor_set = images.descriptor_sets[0]; @@ -122,8 +121,8 @@ VkImageView SGSR::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ viewport_con[5] = std::bit_cast(viewport_height / input_image_height); viewport_con[6] = std::bit_cast(sharpening); - UploadImages(scheduler); - UpdateDescriptorSets(source_image_view, image_index); + UploadImages(device, scheduler); + UpdateDescriptorSets(device, source_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/sgsr.h b/src/video_core/renderer_vulkan/present/sgsr.h index 67b25be75d..42ba00898f 100644 --- a/src/video_core/renderer_vulkan/present/sgsr.h +++ b/src/video_core/renderer_vulkan/present/sgsr.h @@ -16,13 +16,12 @@ class SGSR { public: static constexpr size_t SGSR_STAGE_COUNT = 1; explicit SGSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, VkExtent2D extent, bool edge_dir); - VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); + VkImageView Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage source_image, VkImageView source_image_view, VkExtent2D input_image_extent, const Common::Rectangle& crop_rect); private: - void Initialize(); - void UploadImages(Scheduler& scheduler); - void UpdateDescriptorSets(VkImageView image_view, size_t image_index); + void Initialize(const Device& device); + void UploadImages(const Device& device, Scheduler& scheduler); + void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); - const Device& m_device; MemoryAllocator& m_memory_allocator; const size_t m_image_count; const VkExtent2D m_extent; diff --git a/src/video_core/renderer_vulkan/present/smaa.cpp b/src/video_core/renderer_vulkan/present/smaa.cpp index 686112f2f0..28b0427fa0 100644 --- a/src/video_core/renderer_vulkan/present/smaa.cpp +++ b/src/video_core/renderer_vulkan/present/smaa.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project @@ -27,22 +27,24 @@ namespace Vulkan { SMAA::SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent) - : m_device(device), m_allocator(allocator), m_extent(extent), - m_image_count(static_cast(image_count)) { - CreateImages(); - CreateRenderPasses(); - CreateSampler(); - CreateShaders(); - CreateDescriptorPool(); - CreateDescriptorSetLayouts(); - CreateDescriptorSets(); - CreatePipelineLayouts(); - CreatePipelines(); + : m_allocator(allocator) + , m_extent(extent) + , m_image_count(u32(image_count)) +{ + CreateImages(device); + CreateRenderPasses(device); + CreateSampler(device); + CreateShaders(device); + CreateDescriptorPool(device); + CreateDescriptorSetLayouts(device); + CreateDescriptorSets(device); + CreatePipelineLayouts(device); + CreatePipelines(device); } SMAA::~SMAA() = default; -void SMAA::CreateImages() { +void SMAA::CreateImages(const Device& device) { static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; @@ -50,9 +52,9 @@ void SMAA::CreateImages() { m_static_images[Search] = CreateWrappedImage(m_allocator, search_extent, VK_FORMAT_R8_UNORM); m_static_image_views[Area] = - CreateWrappedImageView(m_device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); + CreateWrappedImageView(device, m_static_images[Area], VK_FORMAT_R8G8_UNORM); m_static_image_views[Search] = - CreateWrappedImageView(m_device, m_static_images[Search], VK_FORMAT_R8_UNORM); + CreateWrappedImageView(device, m_static_images[Search], VK_FORMAT_R8_UNORM); for (u32 i = 0; i < m_image_count; i++) { Images& images = m_dynamic_images.emplace_back(); @@ -64,39 +66,39 @@ void SMAA::CreateImages() { CreateWrappedImage(m_allocator, m_extent, VK_FORMAT_R16G16B16A16_SFLOAT); images.image_views[Blend] = - CreateWrappedImageView(m_device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedImageView(device, images.images[Blend], VK_FORMAT_R16G16B16A16_SFLOAT); images.image_views[Edges] = - CreateWrappedImageView(m_device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT); + CreateWrappedImageView(device, images.images[Edges], VK_FORMAT_R16G16_SFLOAT); images.image_views[Output] = - CreateWrappedImageView(m_device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedImageView(device, images.images[Output], VK_FORMAT_R16G16B16A16_SFLOAT); } } -void SMAA::CreateRenderPasses() { - m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16_SFLOAT); +void SMAA::CreateRenderPasses(const Device& device) { + m_renderpasses[EdgeDetection] = CreateWrappedRenderPass(device, VK_FORMAT_R16G16_SFLOAT); m_renderpasses[BlendingWeightCalculation] = - CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); m_renderpasses[NeighborhoodBlending] = - CreateWrappedRenderPass(m_device, VK_FORMAT_R16G16B16A16_SFLOAT); + CreateWrappedRenderPass(device, VK_FORMAT_R16G16B16A16_SFLOAT); for (auto& images : m_dynamic_images) { images.framebuffers[EdgeDetection] = CreateWrappedFramebuffer( - m_device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent); + device, m_renderpasses[EdgeDetection], images.image_views[Edges], m_extent); images.framebuffers[BlendingWeightCalculation] = - CreateWrappedFramebuffer(m_device, m_renderpasses[BlendingWeightCalculation], + CreateWrappedFramebuffer(device, m_renderpasses[BlendingWeightCalculation], images.image_views[Blend], m_extent); images.framebuffers[NeighborhoodBlending] = CreateWrappedFramebuffer( - m_device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent); + device, m_renderpasses[NeighborhoodBlending], images.image_views[Output], m_extent); } } -void SMAA::CreateSampler() { - m_sampler = CreateWrappedSampler(m_device); +void SMAA::CreateSampler(const Device& device) { + m_sampler = CreateWrappedSampler(device); } -void SMAA::CreateShaders() { +void SMAA::CreateShaders(const Device& device) { // These match the order of the SMAAStage enum static constexpr std::array vert_shader_sources{ ARRAY_TO_SPAN(SMAA_EDGE_DETECTION_VERT_SPV), @@ -110,33 +112,33 @@ void SMAA::CreateShaders() { }; for (size_t i = 0; i < MaxSMAAStage; i++) { - m_vertex_shaders[i] = CreateWrappedShaderModule(m_device, vert_shader_sources[i]); - m_fragment_shaders[i] = CreateWrappedShaderModule(m_device, frag_shader_sources[i]); + m_vertex_shaders[i] = CreateWrappedShaderModule(device, vert_shader_sources[i]); + m_fragment_shaders[i] = CreateWrappedShaderModule(device, frag_shader_sources[i]); } } -void SMAA::CreateDescriptorPool() { +void SMAA::CreateDescriptorPool(const Device& device) { // Edge detection: 1 descriptor // Blending weight calculation: 3 descriptors // Neighborhood blending: 2 descriptors // 6 descriptors, 3 descriptor sets per image - m_descriptor_pool = CreateWrappedDescriptorPool(m_device, 6 * m_image_count, 3 * m_image_count); + m_descriptor_pool = CreateWrappedDescriptorPool(device, 6 * m_image_count, 3 * m_image_count); } -void SMAA::CreateDescriptorSetLayouts() { +void SMAA::CreateDescriptorSetLayouts(const Device& device) { m_descriptor_set_layouts[EdgeDetection] = - CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); + CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); m_descriptor_set_layouts[BlendingWeightCalculation] = - CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); m_descriptor_set_layouts[NeighborhoodBlending] = - CreateWrappedDescriptorSetLayout(m_device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void SMAA::CreateDescriptorSets() { +void SMAA::CreateDescriptorSets(const Device& device) { std::vector layouts(m_descriptor_set_layouts.size()); std::ranges::transform(m_descriptor_set_layouts, layouts.begin(), [](auto& layout) { return *layout; }); @@ -146,21 +148,21 @@ void SMAA::CreateDescriptorSets() { } } -void SMAA::CreatePipelineLayouts() { +void SMAA::CreatePipelineLayouts(const Device& device) { for (size_t i = 0; i < MaxSMAAStage; i++) { - m_pipeline_layouts[i] = CreateWrappedPipelineLayout(m_device, m_descriptor_set_layouts[i]); + m_pipeline_layouts[i] = CreateWrappedPipelineLayout(device, m_descriptor_set_layouts[i]); } } -void SMAA::CreatePipelines() { +void SMAA::CreatePipelines(const Device& device) { for (size_t i = 0; i < MaxSMAAStage; i++) { m_pipelines[i] = - CreateWrappedPipeline(m_device, m_renderpasses[i], m_pipeline_layouts[i], + CreateWrappedPipeline(device, m_renderpasses[i], m_pipeline_layouts[i], std::tie(m_vertex_shaders[i], m_fragment_shaders[i])); } } -void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { +void SMAA::UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index) { Images& images = m_dynamic_images[image_index]; std::vector image_infos; std::vector updates; @@ -184,10 +186,10 @@ void SMAA::UpdateDescriptorSets(VkImageView image_view, size_t image_index) { updates.push_back(CreateWriteDescriptorSet(image_infos, *m_sampler, *images.image_views[Blend], images.descriptor_sets[NeighborhoodBlending], 1)); - m_device.GetLogical().UpdateDescriptorSets(updates, {}); + device.GetLogical().UpdateDescriptorSets(updates, {}); } -void SMAA::UploadImages(Scheduler& scheduler) { +void SMAA::UploadImages(const Device& device, Scheduler& scheduler) { if (m_images_ready) { return; } @@ -195,9 +197,9 @@ void SMAA::UploadImages(Scheduler& scheduler) { static constexpr VkExtent2D area_extent{AREATEX_WIDTH, AREATEX_HEIGHT}; static constexpr VkExtent2D search_extent{SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}; - UploadImage(m_device, m_allocator, scheduler, m_static_images[Area], area_extent, + UploadImage(device, m_allocator, scheduler, m_static_images[Area], area_extent, VK_FORMAT_R8G8_UNORM, ARRAY_TO_SPAN(areaTexBytes)); - UploadImage(m_device, m_allocator, scheduler, m_static_images[Search], search_extent, + UploadImage(device, m_allocator, scheduler, m_static_images[Search], search_extent, VK_FORMAT_R8_UNORM, ARRAY_TO_SPAN(searchTexBytes)); scheduler.Record([&](vk::CommandBuffer cmdbuf) { @@ -212,8 +214,7 @@ void SMAA::UploadImages(Scheduler& scheduler) { m_images_ready = true; } -void SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, - VkImageView* inout_image_view) { +void SMAA::Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) { Images& images = m_dynamic_images[image_index]; VkImage input_image = *inout_image; @@ -232,8 +233,8 @@ void SMAA::Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, *images.framebuffers[BlendingWeightCalculation]; VkFramebuffer neighborhood_blending_framebuffer = *images.framebuffers[NeighborhoodBlending]; - UploadImages(scheduler); - UpdateDescriptorSets(*inout_image_view, image_index); + UploadImages(device, scheduler); + UpdateDescriptorSets(device, *inout_image_view, image_index); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([=, this](vk::CommandBuffer cmdbuf) { diff --git a/src/video_core/renderer_vulkan/present/smaa.h b/src/video_core/renderer_vulkan/present/smaa.h index fdf6def070..a547161395 100644 --- a/src/video_core/renderer_vulkan/present/smaa.h +++ b/src/video_core/renderer_vulkan/present/smaa.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,11 +19,10 @@ class StagingBufferPool; class SMAA final : public AntiAliasPass { public: - explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, - VkExtent2D extent); + explicit SMAA(const Device& device, MemoryAllocator& allocator, size_t image_count, VkExtent2D extent); ~SMAA() override; - void Draw(Scheduler& scheduler, size_t image_index, VkImage* inout_image, + void Draw(const Device& device, Scheduler& scheduler, size_t image_index, VkImage* inout_image, VkImageView* inout_image_view) override; private: @@ -44,19 +46,18 @@ private: MaxDynamicImage = 3, }; - void CreateImages(); - void CreateRenderPasses(); - void CreateSampler(); - void CreateShaders(); - void CreateDescriptorPool(); - void CreateDescriptorSetLayouts(); - void CreateDescriptorSets(); - void CreatePipelineLayouts(); - void CreatePipelines(); - void UpdateDescriptorSets(VkImageView image_view, size_t image_index); - void UploadImages(Scheduler& scheduler); + void CreateImages(const Device& device); + void CreateRenderPasses(const Device& device); + void CreateSampler(const Device& device); + void CreateShaders(const Device& device); + void CreateDescriptorPool(const Device& device); + void CreateDescriptorSetLayouts(const Device& device); + void CreateDescriptorSets(const Device& device); + void CreatePipelineLayouts(const Device& device); + void CreatePipelines(const Device& device); + void UpdateDescriptorSets(const Device& device, VkImageView image_view, size_t image_index); + void UploadImages(const Device& device, Scheduler& scheduler); - const Device& m_device; MemoryAllocator& m_allocator; const VkExtent2D m_extent; const u32 m_image_count; diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp index 22ffacf119..549b0660c1 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,19 +18,20 @@ namespace Vulkan { -WindowAdaptPass::WindowAdaptPass(const Device& device_, VkFormat frame_format, - vk::Sampler&& sampler_, vk::ShaderModule&& fragment_shader_) - : device(device_), sampler(std::move(sampler_)), fragment_shader(std::move(fragment_shader_)) { - CreateDescriptorSetLayout(); - CreatePipelineLayout(); - CreateVertexShader(); - CreateRenderPass(frame_format); - CreatePipelines(); +WindowAdaptPass::WindowAdaptPass(const Device& device, VkFormat frame_format, vk::Sampler&& sampler_, vk::ShaderModule&& fragment_shader_) + : sampler(std::move(sampler_)) + , fragment_shader(std::move(fragment_shader_)) +{ + CreateDescriptorSetLayout(device); + CreatePipelineLayout(device); + CreateVertexShader(device); + CreateRenderPass(device, frame_format); + CreatePipelines(device); } WindowAdaptPass::~WindowAdaptPass() = default; -void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, +void WindowAdaptPass::Draw(const Device& device, RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, std::list& layers, std::span configs, const Layout::FramebufferLayout& layout, Frame* dst) { @@ -60,7 +64,7 @@ void WindowAdaptPass::Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, s break; } - layer_it->ConfigureDraw(&push_constants[i], &descriptor_sets[i], rasterizer, *sampler, + layer_it->ConfigureDraw(device, &push_constants[i], &descriptor_sets[i], rasterizer, *sampler, image_index, configs[i], layout); layer_it++; } @@ -111,12 +115,12 @@ VkRenderPass WindowAdaptPass::GetRenderPass() { return *render_pass; } -void WindowAdaptPass::CreateDescriptorSetLayout() { +void WindowAdaptPass::CreateDescriptorSetLayout(const Device& device) { descriptor_set_layout = CreateWrappedDescriptorSetLayout(device, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}); } -void WindowAdaptPass::CreatePipelineLayout() { +void WindowAdaptPass::CreatePipelineLayout(const Device& device) { const VkPushConstantRange range{ .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, .offset = 0, @@ -134,15 +138,15 @@ void WindowAdaptPass::CreatePipelineLayout() { }); } -void WindowAdaptPass::CreateVertexShader() { +void WindowAdaptPass::CreateVertexShader(const Device& device) { vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); } -void WindowAdaptPass::CreateRenderPass(VkFormat frame_format) { +void WindowAdaptPass::CreateRenderPass(const Device& device, VkFormat frame_format) { render_pass = CreateWrappedRenderPass(device, frame_format, VK_IMAGE_LAYOUT_UNDEFINED); } -void WindowAdaptPass::CreatePipelines() { +void WindowAdaptPass::CreatePipelines(const Device& device) { opaque_pipeline = CreateWrappedPipeline(device, render_pass, pipeline_layout, std::tie(vertex_shader, fragment_shader)); premultiplied_pipeline = CreateWrappedPremultipliedBlendingPipeline( diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.h b/src/video_core/renderer_vulkan/present/window_adapt_pass.h index cf667a4fc6..58d6fc01c0 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.h +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +33,7 @@ public: vk::ShaderModule&& fragment_shader); ~WindowAdaptPass(); - void Draw(RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, + void Draw(const Device& device, RasterizerVulkan& rasterizer, Scheduler& scheduler, size_t image_index, std::list& layers, std::span configs, const Layout::FramebufferLayout& layout, Frame* dst); @@ -38,14 +41,12 @@ public: VkRenderPass GetRenderPass(); private: - void CreateDescriptorSetLayout(); - void CreatePipelineLayout(); - void CreateVertexShader(); - void CreateRenderPass(VkFormat frame_format); - void CreatePipelines(); + void CreateDescriptorSetLayout(const Device& device); + void CreatePipelineLayout(const Device& device); + void CreateVertexShader(const Device& device); + void CreateRenderPass(const Device& device, VkFormat frame_format); + void CreatePipelines(const Device& device); -private: - const Device& device; vk::DescriptorSetLayout descriptor_set_layout; vk::PipelineLayout pipeline_layout; vk::Sampler sampler; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 30a39ef81e..b0a7d0c579 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -188,7 +188,7 @@ void RendererVulkan::Composite(std::span framebu Frame* frame = present_manager.GetRenderFrame(); scheduler.RequestOutsideRenderPassOperationContext(); - blit_swapchain.DrawToFrame(rasterizer, frame, framebuffers, + blit_swapchain.DrawToFrame(device, rasterizer, frame, framebuffers, render_window.GetFramebufferLayout(), swapchain.GetImageCount(), swapchain.GetImageViewFormat()); scheduler.Flush(*frame->render_ready); @@ -226,12 +226,12 @@ vk::Buffer RendererVulkan::RenderToBuffer(std::span framebuffers, const Layout::FramebufferLayout& layout, size_t current_swapchain_image_count, @@ -107,8 +110,8 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, } if (resource_update_required) { - WaitIdle(); - SetWindowAdaptPass(); + WaitIdle(device); + SetWindowAdaptPass(device); if (presentation_recreate_required) { present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format, @@ -131,22 +134,22 @@ void BlitScreen::DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, } } - window_adapt->Draw(rasterizer, scheduler, image_index, layers, framebuffers, layout, frame); + window_adapt->Draw(device, rasterizer, scheduler, image_index, layers, framebuffers, layout, frame); if (++image_index >= image_count) { image_index = 0; } } -vk::Framebuffer BlitScreen::CreateFramebuffer(const Layout::FramebufferLayout& layout, +vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const Layout::FramebufferLayout& layout, VkImageView image_view, VkFormat current_view_format) { bool format_updated = swapchain_view_format != current_view_format; swapchain_view_format = current_view_format; if (!window_adapt || scaling_filter != filters.get_scaling_filter() || format_updated) { - WaitIdle(); - SetWindowAdaptPass(); + WaitIdle(device); + SetWindowAdaptPass(device); image_index = 0; } @@ -155,10 +158,10 @@ vk::Framebuffer BlitScreen::CreateFramebuffer(const Layout::FramebufferLayout& l .height = layout.height, }; - return CreateFramebuffer(image_view, extent, window_adapt->GetRenderPass()); + return CreateFramebuffer(device, image_view, extent, window_adapt->GetRenderPass()); } -vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent, +vk::Framebuffer BlitScreen::CreateFramebuffer(const Device& device, const VkImageView& image_view, VkExtent2D extent, VkRenderPass render_pass) { return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index 531c57fc5c..e50f0bcf33 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -52,23 +55,22 @@ public: Scheduler& scheduler, const PresentFilters& filters); ~BlitScreen(); - void DrawToFrame(RasterizerVulkan& rasterizer, Frame* frame, + void DrawToFrame(const Device& device, RasterizerVulkan& rasterizer, Frame* frame, std::span framebuffers, const Layout::FramebufferLayout& layout, size_t current_swapchain_image_count, VkFormat current_swapchain_view_format); - [[nodiscard]] vk::Framebuffer CreateFramebuffer(const Layout::FramebufferLayout& layout, + [[nodiscard]] vk::Framebuffer CreateFramebuffer(const Device& device, const Layout::FramebufferLayout& layout, VkImageView image_view, VkFormat current_view_format); private: - void WaitIdle(); - void SetWindowAdaptPass(); - vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent, + void WaitIdle(const Device& device); + void SetWindowAdaptPass(const Device& device); + vk::Framebuffer CreateFramebuffer(const Device& device, const VkImageView& image_view, VkExtent2D extent, VkRenderPass render_pass); Tegra::MaxwellDeviceMemoryManager& device_memory; - const Device& device; MemoryAllocator& memory_allocator; PresentManager& present_manager; Scheduler& scheduler; diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 55e8a9b3f0..c24b7a5757 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -234,7 +234,7 @@ struct ConditionalRenderingResolvePushConstants { }; } // Anonymous namespace -ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, +ComputePass::ComputePass(const Device& device_, Scheduler& scheduler, DescriptorPool& descriptor_pool, vk::Span bindings, vk::Span templates, const DescriptorBankInfo& bank_info, @@ -270,7 +270,7 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, .pipelineLayout = *layout, .set = 0, }); - descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); + descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, bank_info); } if (code.empty()) { return; @@ -313,7 +313,7 @@ ComputePass::~ComputePass() = default; Uint8Pass::Uint8Pass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, scheduler_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {}, VULKAN_UINT8_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, @@ -355,7 +355,7 @@ QuadIndexedPass::QuadIndexedPass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, VULKAN_QUAD_INDEXED_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, @@ -416,7 +416,7 @@ std::pair QuadIndexedPass::Assemble( ConditionalRenderingResolvePass::ConditionalRenderingResolvePass( const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, RESOLVE_CONDITIONAL_RENDER_COMP_SPV), @@ -470,7 +470,7 @@ QueriesPrefixScanPass::QueriesPrefixScanPass( const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) : ComputePass( - device_, descriptor_pool_, QUERIES_SCAN_DESCRIPTOR_SET_BINDINGS, + device_, scheduler_, descriptor_pool_, QUERIES_SCAN_DESCRIPTOR_SET_BINDINGS, QUERIES_SCAN_DESCRIPTOR_UPDATE_TEMPLATE, QUERIES_SCAN_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, device_.IsSubgroupFeatureSupported(VK_SUBGROUP_FEATURE_BASIC_BIT) && @@ -547,7 +547,7 @@ ASTCDecoderPass::ASTCDecoderPass(const Device& device_, Scheduler& scheduler_, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_, MemoryAllocator& memory_allocator_) - : ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO, COMPUTE_PUSH_CONSTANT_RANGE, ASTC_DECODER_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, @@ -746,7 +746,7 @@ BlockLinearUnswizzle3DPass::BlockLinearUnswizzle3DPass( StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) : ComputePass( - device_, descriptor_pool_, + device_, scheduler_, descriptor_pool_, BL3D_DESCRIPTOR_SET_BINDINGS, BL3D_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, BL3D_BANK_INFO, @@ -941,7 +941,7 @@ MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) - : ComputePass(device_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS, + : ComputePass(device_, scheduler_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS, MSAA_DESCRIPTOR_UPDATE_TEMPLATE, MSAA_BANK_INFO, {}, CONVERT_NON_MSAA_TO_MSAA_COMP_SPV), scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 0e5badce01..cb213dae7e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -35,7 +35,7 @@ struct StagingBufferRef; class ComputePass { public: - explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool, + explicit ComputePass(const Device& device, Scheduler& scheduler, DescriptorPool& descriptor_pool, vk::Span bindings, vk::Span templates, const DescriptorBankInfo& bank_info, diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 81ff8fe31a..2c1fd94e67 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -30,7 +30,7 @@ using Shader::ImageBufferDescriptor; using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET; using Tegra::Texture::TexturePair; -ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_, +ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk::PipelineCache& pipeline_cache_, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue_, Common::ThreadWorker* thread_worker, @@ -46,7 +46,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel std::copy_n(info.constant_buffer_used_sizes.begin(), uniform_buffer_sizes.size(), uniform_buffer_sizes.begin()); - auto func{[this, &descriptor_pool, shader_notify, pipeline_statistics] { + auto func{[this, &scheduler, &descriptor_pool, shader_notify, pipeline_statistics] { DescriptorLayoutBuilder builder{device}; builder.Add(info, VK_SHADER_STAGE_COMPUTE_BIT); @@ -56,7 +56,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel descriptor_update_template = builder.CreateTemplate(*descriptor_set_layout, *pipeline_layout, uses_push_descriptor); if (!uses_push_descriptor) { - descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, info); + descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, info); } const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, @@ -94,7 +94,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel } if (pipeline_statistics) { - pipeline_statistics->Collect(*pipeline); + pipeline_statistics->Collect(device, *pipeline); } std::scoped_lock lock{build_mutex}; is_built = true; diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index aa84c00e12..f3abe4c931 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h @@ -31,7 +31,7 @@ class Scheduler; class ComputePipeline { public: - explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache, + explicit ComputePipeline(const Device& device, Scheduler& scheduler, vk::PipelineCache& pipeline_cache, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue, Common::ThreadWorker* thread_worker, diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 3af9758a31..b020d99b93 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -125,27 +125,22 @@ vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) { throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY); } -DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler) - : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {} - +DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler) {} DescriptorPool::~DescriptorPool() = default; -DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, - std::span infos) { - return Allocator(layout, MakeBankInfo(infos)); +DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, std::span infos) { + return Allocator(device, scheduler, layout, MakeBankInfo(infos)); } -DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, - const Shader::Info& info) { - return Allocator(layout, MakeBankInfo(std::array{info})); +DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const Shader::Info& info) { + return Allocator(device, scheduler, layout, MakeBankInfo(std::array{info})); } -DescriptorAllocator DescriptorPool::Allocator(VkDescriptorSetLayout layout, - const DescriptorBankInfo& info) { - return DescriptorAllocator(device, master_semaphore, Bank(info), layout); +DescriptorAllocator DescriptorPool::Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const DescriptorBankInfo& info) { + return DescriptorAllocator(device, scheduler.GetMasterSemaphore(), Bank(device, info), layout); } -DescriptorBank& DescriptorPool::Bank(const DescriptorBankInfo& reqs) { +DescriptorBank& DescriptorPool::Bank(const Device& device, const DescriptorBankInfo& reqs) { std::shared_lock read_lock{banks_mutex}; const auto it = std::ranges::find_if(bank_infos, [&reqs](const DescriptorBankInfo& bank) { return std::abs(bank.score - reqs.score) < SCORE_THRESHOLD && bank.IsSuperset(reqs); diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h index 4aada5a006..4efeb60373 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -68,17 +71,12 @@ public: DescriptorPool& operator=(const DescriptorPool&) = delete; DescriptorPool(const DescriptorPool&) = delete; - DescriptorAllocator Allocator(VkDescriptorSetLayout layout, - std::span infos); - DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const Shader::Info& info); - DescriptorAllocator Allocator(VkDescriptorSetLayout layout, const DescriptorBankInfo& info); + DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, std::span infos); + DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const Shader::Info& info); + DescriptorAllocator Allocator(const Device& device, Scheduler& scheduler, VkDescriptorSetLayout layout, const DescriptorBankInfo& info); private: - DescriptorBank& Bank(const DescriptorBankInfo& reqs); - - const Device& device; - MasterSemaphore& master_semaphore; - + DescriptorBank& Bank(const Device& device, const DescriptorBankInfo& reqs); std::shared_mutex banks_mutex; std::vector bank_infos; std::vector> banks; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 728554d6e6..3b5338a058 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -276,7 +276,7 @@ GraphicsPipeline::GraphicsPipeline( descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor); if (!uses_push_descriptor) { - descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos); + descriptor_allocator = descriptor_pool.Allocator(device, scheduler, *descriptor_set_layout, stage_infos); } const VkDescriptorSetLayout set_layout{*descriptor_set_layout}; @@ -288,7 +288,7 @@ GraphicsPipeline::GraphicsPipeline( Validate(); MakePipeline(render_pass); if (pipeline_statistics) { - pipeline_statistics->Collect(*pipeline); + pipeline_statistics->Collect(device, *pipeline); } std::scoped_lock lock{build_mutex}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 23bfbceccb..798499141e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -915,7 +915,7 @@ std::unique_ptr PipelineCache::CreateComputePipeline( spv_module.SetObjectNameEXT(name.c_str()); } Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr}; - return std::make_unique(device, vulkan_pipeline_cache, descriptor_pool, + return std::make_unique(device, scheduler, vulkan_pipeline_cache, descriptor_pool, guest_descriptor_queue, thread_worker, statistics, &shader_notify, program.info, std::move(spv_module)); diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index f0c704b700..06d405c2f5 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -126,16 +126,14 @@ public: current_query = nullptr; amend_value = 0; accumulation_value = 0; - queries_prefix_scan_pass = std::make_unique( - device, scheduler, descriptor_pool, compute_pass_descriptor_queue); + queries_prefix_scan_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue); const VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, .size = 8, - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, @@ -592,8 +590,7 @@ private: VideoCommon::HostQueryBase* current_query; bool has_started{}; std::mutex flush_guard; - - std::unique_ptr queries_prefix_scan_pass; + std::optional queries_prefix_scan_pass; }; // Transform feedback queries @@ -1266,41 +1263,23 @@ private: } // namespace struct QueryCacheRuntimeImpl { - QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, - Tegra::MaxwellDeviceMemoryManager& device_memory_, - Vulkan::BufferCache& buffer_cache_, const Device& device_, - const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, - StagingBufferPool& staging_pool_, - ComputePassDescriptorQueue& compute_pass_descriptor_queue, - DescriptorPool& descriptor_pool, TextureCache& texture_cache_) - : rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_}, - device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, - staging_pool{staging_pool_}, guest_streamer(0, runtime), - sample_streamer(static_cast(QueryType::ZPassPixelCount64), runtime, rasterizer, - texture_cache_, device, scheduler, memory_allocator, - compute_pass_descriptor_queue, descriptor_pool), - tfb_streamer(static_cast(QueryType::StreamingByteCount), runtime, device, - scheduler, memory_allocator, staging_pool), - primitives_succeeded_streamer( - static_cast(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, - device_memory_), - primitives_needed_minus_succeeded_streamer( - static_cast(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u), - hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { + QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_, Vulkan::BufferCache& buffer_cache_, const Device& device_, const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_) + : rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_} + , device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} + , staging_pool{staging_pool_}, guest_streamer(0, runtime) + , sample_streamer(size_t(QueryType::ZPassPixelCount64), runtime, rasterizer, texture_cache_, device, scheduler, memory_allocator, compute_pass_descriptor_queue, descriptor_pool) + , tfb_streamer(size_t(QueryType::StreamingByteCount), runtime, device, scheduler, memory_allocator, staging_pool) + , primitives_succeeded_streamer(size_t(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, device_memory_) + , primitives_needed_minus_succeeded_streamer(size_t(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u) + , hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { hcr_setup.sType = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT; hcr_setup.pNext = nullptr; hcr_setup.flags = 0; - const bool has_conditional_rendering = device.IsExtConditionalRendering(); - if (has_conditional_rendering) { - conditional_resolve_pass = std::make_unique( - device, scheduler, descriptor_pool, compute_pass_descriptor_queue); - } - - VkBufferUsageFlags hcr_buffer_usage = - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - if (has_conditional_rendering) { + VkBufferUsageFlags hcr_buffer_usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + if (device.IsExtConditionalRendering()) { + conditional_resolve_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue); hcr_buffer_usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT; } @@ -1339,7 +1318,7 @@ struct QueryCacheRuntimeImpl { std::vector> copies_setup; // Host conditional rendering data - std::unique_ptr conditional_resolve_pass; + std::optional conditional_resolve_pass; vk::Buffer hcr_resolve_buffer; VkConditionalRenderingBeginInfoEXT hcr_setup; VkBuffer hcr_buffer; @@ -1351,13 +1330,7 @@ struct QueryCacheRuntimeImpl { Maxwell3D* maxwell3d; }; -QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, - Tegra::MaxwellDeviceMemoryManager& device_memory_, - Vulkan::BufferCache& buffer_cache_, const Device& device_, - const MemoryAllocator& memory_allocator_, - Scheduler& scheduler_, StagingBufferPool& staging_pool_, - ComputePassDescriptorQueue& compute_pass_descriptor_queue, - DescriptorPool& descriptor_pool, TextureCache& texture_cache_) { +QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, Tegra::MaxwellDeviceMemoryManager& device_memory_, Vulkan::BufferCache& buffer_cache_, const Device& device_, const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, StagingBufferPool& staging_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_) { impl = std::make_unique( *this, rasterizer, device_memory_, buffer_cache_, device_, memory_allocator_, scheduler_, staging_pool_, compute_pass_descriptor_queue, descriptor_pool, texture_cache_); @@ -1686,8 +1659,7 @@ void QueryCacheRuntime::SyncValues(std::span values, VkBuffer ba } impl->scheduler.RequestOutsideRenderPassOperationContext(); - impl->scheduler.Record([src_buffer, dst_buffers = std::move(impl->buffers_to_upload_to), - vk_copies = std::move(impl->copies_setup)](vk::CommandBuffer cmdbuf) { + impl->scheduler.Record([src_buffer, dst_buffers = std::move(impl->buffers_to_upload_to), vk_copies = std::move(impl->copies_setup)](vk::CommandBuffer cmdbuf) { size_t size = dst_buffers.size(); for (size_t i = 0; i < size; i++) { cmdbuf.CopyBuffer(src_buffer, dst_buffers[i].first, vk_copies[i]); diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index a7b7c46f39..0b132c97d6 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp @@ -235,7 +235,7 @@ void SetupRasterModes(Maxwell3D::DirtyState::Tables &tables) { } // Anonymous namespace void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { - auto& tables{channel_state.maxwell_3d->dirty.tables}; + auto& tables{channel_state.payload->maxwell_3d.dirty.tables}; SetupDirtyFlags(tables); SetupDirtyViewports(tables); SetupDirtyScissors(tables); @@ -258,7 +258,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) { } void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) { - flags = &channel_state.maxwell_3d->dirty.flags; + flags = &channel_state.payload->maxwell_3d.dirty.flags; } void StateTracker::InvalidateState() { diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h index 82fce298da..1497108b16 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.h +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h @@ -1,10 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include - +#include #include "video_core/vulkan_common/vulkan_wrapper.h" namespace Vulkan { @@ -12,20 +15,15 @@ namespace Vulkan { class Device; class Scheduler; -struct DescriptorUpdateEntry { - struct Empty {}; - +union DescriptorUpdateEntry { DescriptorUpdateEntry() = default; DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {} DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {} DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {} - - union { - Empty empty{}; - VkDescriptorImageInfo image; - VkDescriptorBufferInfo buffer; - VkBufferView texel_buffer; - }; + std::monostate empty{}; + VkDescriptorImageInfo image; + VkDescriptorBufferInfo buffer; + VkBufferView texel_buffer; }; class UpdateDescriptorQueue final { diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 1ac7a0bc35..54fb8f6239 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -45,23 +45,23 @@ std::unique_ptr CreateRenderer(Core::System& system, Co namespace VideoCore { -std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { +/// @brief Creates an emulated GPU instance using the given system context. +void CreateGPU(std::optional& gpu, Core::Frontend::EmuWindow& emu_window, Core::System& system) { Settings::UpdateRescalingInfo(); const auto nvdec_value = Settings::values.nvdec_emulation.GetValue(); const bool use_nvdec = nvdec_value != Settings::NvdecEmulation::Off; const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); - auto gpu = std::make_unique(system, use_async, use_nvdec); + gpu.emplace(system, use_async, use_nvdec); auto context = emu_window.CreateSharedContext(); auto scope = context->Acquire(); try { auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); gpu->BindRenderer(std::move(renderer)); - return gpu; } catch (const std::runtime_error& exception) { scope.Cancel(); LOG_ERROR(HW_GPU, "Failed to initialize GPU: {}", exception.what()); - return nullptr; + gpu.reset(); } } diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index f8e2444f33..1a56dd99b6 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include +#include namespace Core { class System; @@ -20,8 +24,6 @@ class GPU; namespace VideoCore { class RendererBase; - -/// Creates an emulated GPU instance using the given system context. -std::unique_ptr CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system); +void CreateGPU(std::optional& gpu, Core::Frontend::EmuWindow& emu_window, Core::System& system); } // namespace VideoCore