From 0058dc28e82a073fbc61c50785e9168488b6d2fe Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Thu, 31 Mar 2022 08:37:55 +0200 Subject: [PATCH] early-access version 2624 --- README.md | 2 +- src/core/hle/kernel/hle_ipc.cpp | 11 +++++++++-- src/core/hle/kernel/hle_ipc.h | 3 ++- src/core/hle/kernel/kernel.cpp | 14 +++++++++++++- src/core/hle/kernel/kernel.h | 16 +++++++++++++--- src/core/hle/service/audio/audout_u.cpp | 7 ++++--- src/core/hle/service/audio/audren_u.cpp | 3 ++- src/core/hle/service/filesystem/fsp_srv.cpp | 13 ++++++++----- src/core/hle/service/hid/hid.cpp | 4 ++++ src/core/hle/service/service.cpp | 8 +++++--- src/core/hle/service/service.h | 15 ++++++++++----- src/core/hle/service/sm/sm.cpp | 2 +- src/core/hle/service/sockets/bsd.cpp | 3 ++- src/core/hle/service/vi/vi.cpp | 3 ++- 14 files changed, 76 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 01c2da965..b47ac65bb 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2623. +This is the source code for early-access 2624. ## Legal Notice diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 42d1b0e31..90e0662cf 100755 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -24,8 +24,15 @@ namespace Kernel { -SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_) - : kernel{kernel_}, service_thread{kernel.CreateServiceThread(service_name_)} {} +SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_, + bool create_service_thread_) + : kernel{kernel_} { + if (create_service_thread_) { + service_thread = kernel.CreateServiceThread(service_name_); + } else { + service_thread = kernel.GetDefaultServiceThread(); + } +} SessionRequestHandler::~SessionRequestHandler() { kernel.ReleaseServiceThread(service_thread); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 670cc741c..07ce83ab4 100755 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -57,7 +57,8 @@ enum class ThreadWakeupReason; */ class SessionRequestHandler : public std::enable_shared_from_this { public: - SessionRequestHandler(KernelCore& kernel, const char* service_name_); + SessionRequestHandler(KernelCore& kernel_, const char* service_name_, + bool create_service_thread_); virtual ~SessionRequestHandler(); /** diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index df05f5ddb..763e83187 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -61,6 +61,7 @@ struct KernelCore::Impl { global_scheduler_context = std::make_unique(kernel); global_handle_table = std::make_unique(kernel); global_handle_table->Initialize(KHandleTable::MaxTableSize); + default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread"); is_phantom_mode_for_singlecore = false; @@ -686,6 +687,12 @@ struct KernelCore::Impl { void ReleaseServiceThread(std::weak_ptr service_thread) { if (auto strong_ptr = service_thread.lock()) { + if (strong_ptr == default_service_thread.lock()) { + // Nothing to do here, the service is using default_service_thread, which will be + // released on shutdown. + return; + } + service_threads_manager.QueueWork( [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); }); } @@ -749,7 +756,8 @@ struct KernelCore::Impl { std::unique_ptr memory_layout; // Threads used for services - std::unordered_set> service_threads; + std::unordered_set> service_threads; + std::weak_ptr default_service_thread; Common::ThreadWorker service_threads_manager; std::array suspend_threads; @@ -1083,6 +1091,10 @@ std::weak_ptr KernelCore::CreateServiceThread(const std:: return impl->CreateServiceThread(*this, name); } +std::weak_ptr KernelCore::GetDefaultServiceThread() { + return impl->default_service_thread; +} + void KernelCore::ReleaseServiceThread(std::weak_ptr service_thread) { impl->ReleaseServiceThread(service_thread); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 0757d74a7..77901e5a9 100755 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -277,15 +277,25 @@ public: void ExitSVCProfile(); /** - * Creates an HLE service thread, which are used to execute service routines asynchronously. - * While these are allocated per ServerSession, these need to be owned and managed outside - * of ServerSession to avoid a circular dependency. + * Creates a host thread to execute HLE service requests, which are used to execute service + * routines asynchronously. While these are allocated per ServerSession, these need to be owned + * and managed outside of ServerSession to avoid a circular dependency. In general, most + * services can just use the default service thread, and not need their own host service thread. + * See GetDefaultServiceThread. * @param name String name for the ServerSession creating this thread, used for debug * purposes. * @returns The a weak pointer newly created service thread. */ std::weak_ptr CreateServiceThread(const std::string& name); + /** + * Gets the default host service thread, which executes HLE service requests. Unless service + * requests need to block on the host, the default service thread should be used in favor of + * creating a new service thread. + * @returns The a weak pointer for the default service thread. + */ + std::weak_ptr GetDefaultServiceThread(); + /** * Releases a HLE service thread, instructing KernelCore to free it. This should be called when * the ServerSession associated with the thread is destroyed. diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index affa7971c..834ac14ca 100755 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -41,9 +41,10 @@ public: explicit IAudioOut(Core::System& system_, AudoutParams audio_params_, AudioCore::AudioOut& audio_core_, std::string&& device_name_, std::string&& unique_name) - : ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_}, - device_name{std::move(device_name_)}, audio_params{audio_params_}, - main_memory{system.Memory()}, service_context{system_, "IAudioOut"} { + : ServiceFramework{system_, "IAudioOut", true /*create_service_thread*/}, + audio_core{audio_core_}, device_name{std::move(device_name_)}, + audio_params{audio_params_}, main_memory{system.Memory()}, service_context{system_, + "IAudioOut"} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index f45e5cecc..8df874fcf 100755 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -24,7 +24,8 @@ public: explicit IAudioRenderer(Core::System& system_, const AudioCommon::AudioRendererParameter& audren_params, const std::size_t instance_number) - : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"} { + : ServiceFramework{system_, "IAudioRenderer", true /*create_service_thread*/}, + service_context{system_, "IAudioRenderer"} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index b087e7bba..9feccfbb8 100755 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -58,7 +58,8 @@ enum class FileSystemType : u8 { class IStorage final : public ServiceFramework { public: explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) - : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { + : ServiceFramework{system_, "IStorage", true /*create_service_thread*/}, + backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, @@ -116,7 +117,8 @@ private: class IFile final : public ServiceFramework { public: explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) - : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { + : ServiceFramework{system_, "IFile", true /*create_service_thread*/}, + backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, @@ -252,7 +254,8 @@ static void BuildEntryIndex(std::vector& entries, const std::vec class IDirectory final : public ServiceFramework { public: explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_) - : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { + : ServiceFramework{system_, "IDirectory", true /*create_service_thread*/}, + backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IDirectory::Read, "Read"}, {1, &IDirectory::GetEntryCount, "GetEntryCount"}, @@ -308,8 +311,8 @@ private: class IFileSystem final : public ServiceFramework { public: explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) - : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( - size_)} { + : ServiceFramework{system_, "IFileSystem", true /*create_service_thread*/}, + backend{std::move(backend_)}, size{std::move(size_)} { static const FunctionInfo functions[] = { {0, &IFileSystem::CreateFile, "CreateFile"}, {1, &IFileSystem::DeleteFile, "DeleteFile"}, diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 8a2635ee4..9d3e0a658 100755 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -879,6 +879,10 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); + // Games expect this event to be signaled after calling this function + applet_resource->GetController(HidController::NPad) + .SignalStyleSetChangedEvent(parameters.npad_id); + IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); rb.PushCopyObjects(applet_resource->GetController(HidController::NPad) diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ab3286db9..04eb0d6ea 100755 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -91,9 +91,11 @@ namespace Service { } ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, - u32 max_sessions_, InvokerFn* handler_invoker_) - : SessionRequestHandler(system_.Kernel(), service_name_), system{system_}, - service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {} + bool create_service_thread_, u32 max_sessions_, + InvokerFn* handler_invoker_) + : SessionRequestHandler(system_.Kernel(), service_name_, create_service_thread_), + system{system_}, service_name{service_name_}, max_sessions{max_sessions_}, + handler_invoker{handler_invoker_} {} ServiceFrameworkBase::~ServiceFrameworkBase() { // Wait for other threads to release access before destroying diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index b9ab2c465..778b6da4e 100755 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -114,7 +114,8 @@ private: Kernel::HLERequestContext& ctx); explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_, - u32 max_sessions_, InvokerFn* handler_invoker_); + bool create_service_thread_, u32 max_sessions_, + InvokerFn* handler_invoker_); ~ServiceFrameworkBase() override; void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); @@ -176,14 +177,18 @@ protected: /** * Initializes the handler with no functions installed. * - * @param system_ The system context to construct this service under. + * @param system_ The system context to construct this service under. * @param service_name_ Name of the service. - * @param max_sessions_ Maximum number of sessions that can be - * connected to this service at the same time. + * @param create_service_thread_ Creates a service thread for this if true, otherwise use the + * default service thread. + * @param max_sessions_ Maximum number of sessions that can be connected to this service at the + * same time. */ explicit ServiceFramework(Core::System& system_, const char* service_name_, + bool create_service_thread_ = false, u32 max_sessions_ = ServerSessionCountMax) - : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {} + : ServiceFrameworkBase(system_, service_name_, create_service_thread_, max_sessions_, + Invoker) {} /// Registers handlers in the service. template diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 695a1faa6..5233e5b33 100755 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -206,7 +206,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) { } SM::SM(ServiceManager& service_manager_, Core::System& system_) - : ServiceFramework{system_, "sm:", 4}, + : ServiceFramework{system_, "sm:", false /*create_service_thread*/, 4}, service_manager{service_manager_}, kernel{system_.Kernel()} { RegisterHandlers({ {0, &SM::Initialize, "Initialize"}, diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index fc93fb743..3970879c8 100755 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -837,7 +837,8 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co rb.PushEnum(bsd_errno); } -BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { +BSD::BSD(Core::System& system_, const char* name) + : ServiceFramework{system_, name, true /*create_service_thread*/} { // clang-format off static const FunctionInfo functions[] = { {0, &BSD::RegisterClient, "RegisterClient"}, diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 430cbc546..3284de519 100755 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -77,7 +77,8 @@ static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); class IHOSBinderDriver final : public ServiceFramework { public: explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_) - : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { + : ServiceFramework{system_, "IHOSBinderDriver", true /*create_service_thread*/}, + server(server_) { static const FunctionInfo functions[] = { {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},