Преглед изворни кода

hle: service: Acquire and release a lock on requests.

- This makes it such that we can safely access service members from CoreTiming thread.
bunnei пре 5 година
родитељ
комит
7d77a3f88f

+ 5 - 8
src/audio_core/audio_renderer.cpp

@@ -11,7 +11,6 @@
 #include "audio_core/info_updater.h"
 #include "audio_core/voice_context.h"
 #include "common/logging/log.h"
-#include "core/hle/kernel/writable_event.h"
 #include "core/memory.h"
 #include "core/settings.h"
 
@@ -71,10 +70,9 @@ namespace {
 namespace AudioCore {
 AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_,
                              AudioCommon::AudioRendererParameter params,
-                             std::shared_ptr<Kernel::WritableEvent> buffer_event_,
+                             Stream::ReleaseCallback&& release_callback,
                              std::size_t instance_number)
-    : worker_params{params}, buffer_event{buffer_event_},
-      memory_pool_info(params.effect_count + params.voice_count * 4),
+    : worker_params{params}, memory_pool_info(params.effect_count + params.voice_count * 4),
       voice_context(params.voice_count), effect_context(params.effect_count), mix_context(),
       sink_context(params.sink_count), splitter_context(),
       voices(params.voice_count), memory{memory_},
@@ -85,10 +83,9 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory
                                 params.num_splitter_send_channels);
     mix_context.Initialize(behavior_info, params.submix_count + 1, params.effect_count);
     audio_out = std::make_unique<AudioCore::AudioOut>();
-    stream =
-        audio_out->OpenStream(core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS,
-                              fmt::format("AudioRenderer-Instance{}", instance_number),
-                              [=]() { buffer_event_->Signal(); });
+    stream = audio_out->OpenStream(
+        core_timing, params.sample_rate, AudioCommon::STREAM_NUM_CHANNELS,
+        fmt::format("AudioRenderer-Instance{}", instance_number), std::move(release_callback));
     audio_out->StartStream(stream);
 
     QueueMixedBuffer(0);

+ 1 - 7
src/audio_core/audio_renderer.h

@@ -27,10 +27,6 @@ namespace Core::Timing {
 class CoreTiming;
 }
 
-namespace Kernel {
-class WritableEvent;
-}
-
 namespace Core::Memory {
 class Memory;
 }
@@ -44,8 +40,7 @@ class AudioRenderer {
 public:
     AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_,
                   AudioCommon::AudioRendererParameter params,
-                  std::shared_ptr<Kernel::WritableEvent> buffer_event_,
-                  std::size_t instance_number);
+                  Stream::ReleaseCallback&& release_callback, std::size_t instance_number);
     ~AudioRenderer();
 
     [[nodiscard]] ResultCode UpdateAudioRenderer(const std::vector<u8>& input_params,
@@ -61,7 +56,6 @@ private:
     BehaviorInfo behavior_info{};
 
     AudioCommon::AudioRendererParameter worker_params;
-    std::shared_ptr<Kernel::WritableEvent> buffer_event;
     std::vector<ServerMemoryPoolInfo> memory_pool_info;
     VoiceContext voice_context;
     EffectContext effect_context;

+ 4 - 2
src/core/hle/service/audio/audout_u.cpp

@@ -70,8 +70,10 @@ public:
             Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased");
 
         stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
-                                       audio_params.channel_count, std::move(unique_name),
-                                       [this] { buffer_event.writable->Signal(); });
+                                       audio_params.channel_count, std::move(unique_name), [this] {
+                                           const auto guard = LockService();
+                                           buffer_event.writable->Signal();
+                                       });
     }
 
 private:

+ 7 - 7
src/core/hle/service/audio/audren_u.cpp

@@ -49,16 +49,16 @@ public:
 
         system_event =
             Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
-        renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), system.Memory(),
-                                                              audren_params, system_event.writable,
-                                                              instance_number);
+        renderer = std::make_unique<AudioCore::AudioRenderer>(
+            system.CoreTiming(), system.Memory(), audren_params,
+            [this]() {
+                const auto guard = LockService();
+                system_event.writable->Signal();
+            },
+            instance_number);
     }
 
 private:
-    void UpdateAudioCallback() {
-        system_event.writable->Signal();
-    }
-
     void GetSampleRate(Kernel::HLERequestContext& ctx) {
         LOG_DEBUG(Service_Audio, "called");
 

+ 2 - 0
src/core/hle/service/hid/hid.cpp

@@ -78,11 +78,13 @@ IAppletResource::IAppletResource(Core::System& system_)
     pad_update_event = Core::Timing::CreateEvent(
         "HID::UpdatePadCallback",
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+            const auto guard = LockService();
             UpdateControllers(user_data, ns_late);
         });
     motion_update_event = Core::Timing::CreateEvent(
         "HID::MotionPadCallback",
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+            const auto guard = LockService();
             UpdateMotion(user_data, ns_late);
         });
 

+ 10 - 12
src/core/hle/service/service.cpp

@@ -95,9 +95,14 @@ ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* se
     : system{system_}, service_name{service_name_}, max_sessions{max_sessions_},
       handler_invoker{handler_invoker_} {}
 
-ServiceFrameworkBase::~ServiceFrameworkBase() = default;
+ServiceFrameworkBase::~ServiceFrameworkBase() {
+    // Wait for other threads to release access before destroying
+    const auto guard = LockService();
+}
 
 void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
+    const auto guard = LockService();
+
     ASSERT(!port_installed);
 
     auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap();
@@ -106,6 +111,8 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
 }
 
 void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
+    const auto guard = LockService();
+
     ASSERT(!port_installed);
 
     auto [server_port, client_port] =
@@ -115,17 +122,6 @@ void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
     port_installed = true;
 }
 
-std::shared_ptr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) {
-    ASSERT(!port_installed);
-
-    auto [server_port, client_port] =
-        Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
-    auto port = MakeResult(std::move(server_port)).Unwrap();
-    port->SetHleHandler(shared_from_this());
-    port_installed = true;
-    return client_port;
-}
-
 void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
     handlers.reserve(handlers.size() + n);
     for (std::size_t i = 0; i < n; ++i) {
@@ -164,6 +160,8 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
 }
 
 ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) {
+    const auto guard = LockService();
+
     switch (context.GetCommandType()) {
     case IPC::CommandType::Close: {
         IPC::ResponseBuilder rb{context, 2};

+ 12 - 4
src/core/hle/service/service.h

@@ -5,9 +5,11 @@
 #pragma once
 
 #include <cstddef>
+#include <mutex>
 #include <string>
 #include <boost/container/flat_map.hpp>
 #include "common/common_types.h"
+#include "common/spin_lock.h"
 #include "core/hle/kernel/hle_ipc.h"
 #include "core/hle/kernel/object.h"
 
@@ -68,11 +70,9 @@ public:
     void InstallAsService(SM::ServiceManager& service_manager);
     /// Creates a port pair and registers it on the kernel's global port registry.
     void InstallAsNamedPort(Kernel::KernelCore& kernel);
-    /// Creates and returns an unregistered port for the service.
-    std::shared_ptr<Kernel::ClientPort> CreatePort(Kernel::KernelCore& kernel);
-
+    /// Invokes a service request routine.
     void InvokeRequest(Kernel::HLERequestContext& ctx);
-
+    /// Handles a synchronization request for the service.
     ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) override;
 
 protected:
@@ -80,6 +80,11 @@ protected:
     template <typename Self>
     using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&);
 
+    /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
+    [[nodiscard]] std::scoped_lock<Common::SpinLock> LockService() {
+        return std::scoped_lock{lock_service};
+    }
+
     /// System context that the service operates under.
     Core::System& system;
 
@@ -115,6 +120,9 @@ private:
     /// Function used to safely up-cast pointers to the derived class before invoking a handler.
     InvokerFn* handler_invoker;
     boost::container::flat_map<u32, FunctionInfoBase> handlers;
+
+    /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread.
+    Common::SpinLock lock_service;
 };
 
 /**