hle: service: Acquire and release a lock on requests.
- This makes it such that we can safely access service members from CoreTiming thread.
This commit is contained in:
		@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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};
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user