early-access version 1258

This commit is contained in:
pineappleEA
2020-12-29 09:13:52 +00:00
parent 78b48028e1
commit c7d8d0947d
18 changed files with 73 additions and 159 deletions

View File

@@ -8,7 +8,7 @@
#include <functional>
#include <memory>
#include <thread>
#include <unordered_set>
#include <unordered_map>
#include <utility>
#include "common/assert.h"
@@ -35,7 +35,6 @@
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/synchronization.h"
#include "core/hle/kernel/thread.h"
@@ -108,9 +107,6 @@ struct KernelCore::Impl {
std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(),
std::thread::id{});
std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
// Ensures all service threads gracefully shutdown
service_threads.clear();
}
void InitializePhysicalCores() {
@@ -349,9 +345,6 @@ struct KernelCore::Impl {
std::shared_ptr<Kernel::SharedMemory> irs_shared_mem;
std::shared_ptr<Kernel::SharedMemory> time_shared_mem;
// Threads used for services
std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
@@ -646,16 +639,4 @@ void KernelCore::ExitSVCProfile() {
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
}
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name);
impl->service_threads.emplace(service_thread);
return service_thread;
}
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
if (auto strong_ptr = service_thread.lock()) {
impl->service_threads.erase(strong_ptr);
}
}
} // namespace Kernel

View File

@@ -42,7 +42,6 @@ class Process;
class ResourceLimit;
class KScheduler;
class SharedMemory;
class ServiceThread;
class Synchronization;
class Thread;
class TimeManager;
@@ -228,22 +227,6 @@ 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.
* @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<Kernel::ServiceThread> CreateServiceThread(const std::string& name);
/**
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when
* the ServerSession associated with the thread is destroyed.
* @param service_thread Service thread to release.
*/
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread);
private:
friend class Object;
friend class Process;

View File

@@ -25,10 +25,7 @@
namespace Kernel {
ServerSession::ServerSession(KernelCore& kernel) : SynchronizationObject{kernel} {}
ServerSession::~ServerSession() {
kernel.ReleaseServiceThread(service_thread);
}
ServerSession::~ServerSession() = default;
ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kernel,
std::shared_ptr<Session> parent,
@@ -37,7 +34,7 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern
session->name = std::move(name);
session->parent = std::move(parent);
session->service_thread = kernel.CreateServiceThread(session->name);
session->service_thread = std::make_unique<ServiceThread>(kernel, 1);
return MakeResult(std::move(session));
}
@@ -142,11 +139,7 @@ ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<Thread> thread,
std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread));
context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
if (auto strong_ptr = service_thread.lock()) {
strong_ptr->QueueSyncRequest(*this, std::move(context));
return RESULT_SUCCESS;
}
service_thread->QueueSyncRequest(*this, std::move(context));
return RESULT_SUCCESS;
}

View File

@@ -167,7 +167,7 @@ private:
std::string name;
/// Thread to dispatch service requests
std::weak_ptr<ServiceThread> service_thread;
std::unique_ptr<ServiceThread> service_thread;
};
} // namespace Kernel

View File

@@ -11,7 +11,6 @@
#include "common/assert.h"
#include "common/scope_exit.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/server_session.h"
@@ -23,7 +22,7 @@ namespace Kernel {
class ServiceThread::Impl final {
public:
explicit Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name);
explicit Impl(KernelCore& kernel, std::size_t num_threads);
~Impl();
void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context);
@@ -33,17 +32,12 @@ private:
std::queue<std::function<void()>> requests;
std::mutex queue_mutex;
std::condition_variable condition;
const std::string service_name;
bool stop{};
};
ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name)
: service_name{name} {
ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads) {
for (std::size_t i = 0; i < num_threads; ++i)
threads.emplace_back([this, &kernel] {
Common::SetCurrentThreadName(std::string{"Hle_" + service_name}.c_str());
threads.emplace_back([&] {
// Wait for first request before trying to acquire a render context
{
std::unique_lock lock{queue_mutex};
@@ -58,7 +52,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std
{
std::unique_lock lock{queue_mutex};
condition.wait(lock, [this] { return stop || !requests.empty(); });
if (stop || requests.empty()) {
if (stop && requests.empty()) {
return;
}
task = std::move(requests.front());
@@ -93,8 +87,8 @@ ServiceThread::Impl::~Impl() {
}
}
ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_thread, const std::string& name)
: impl{std::make_unique<Impl>(kernel, num_thread, name)} {}
ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads)
: impl{std::make_unique<Impl>(kernel, num_threads)} {}
ServiceThread::~ServiceThread() = default;

View File

@@ -5,7 +5,6 @@
#pragma once
#include <memory>
#include <string>
namespace Kernel {
@@ -15,7 +14,7 @@ class ServerSession;
class ServiceThread final {
public:
explicit ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name);
explicit ServiceThread(KernelCore& kernel, std::size_t num_threads);
~ServiceThread();
void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context);

View File

@@ -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:

View File

@@ -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");

View File

@@ -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);
});

View File

@@ -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};

View File

@@ -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;
};
/**