early-access version 2624
This commit is contained in:
parent
9d7ef4030f
commit
0058dc28e8
14 changed files with 76 additions and 28 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2623.
|
This is the source code for early-access 2624.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,15 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_)
|
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
|
||||||
: kernel{kernel_}, service_thread{kernel.CreateServiceThread(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() {
|
SessionRequestHandler::~SessionRequestHandler() {
|
||||||
kernel.ReleaseServiceThread(service_thread);
|
kernel.ReleaseServiceThread(service_thread);
|
||||||
|
|
|
@ -57,7 +57,8 @@ enum class ThreadWakeupReason;
|
||||||
*/
|
*/
|
||||||
class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
|
class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
|
||||||
public:
|
public:
|
||||||
SessionRequestHandler(KernelCore& kernel, const char* service_name_);
|
SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
|
||||||
|
bool create_service_thread_);
|
||||||
virtual ~SessionRequestHandler();
|
virtual ~SessionRequestHandler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -61,6 +61,7 @@ struct KernelCore::Impl {
|
||||||
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
|
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
|
||||||
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
|
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
|
||||||
global_handle_table->Initialize(KHandleTable::MaxTableSize);
|
global_handle_table->Initialize(KHandleTable::MaxTableSize);
|
||||||
|
default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
|
||||||
|
|
||||||
is_phantom_mode_for_singlecore = false;
|
is_phantom_mode_for_singlecore = false;
|
||||||
|
|
||||||
|
@ -686,6 +687,12 @@ struct KernelCore::Impl {
|
||||||
|
|
||||||
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
||||||
if (auto strong_ptr = service_thread.lock()) {
|
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(
|
service_threads_manager.QueueWork(
|
||||||
[this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
|
[this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
|
||||||
}
|
}
|
||||||
|
@ -749,7 +756,8 @@ struct KernelCore::Impl {
|
||||||
std::unique_ptr<KMemoryLayout> memory_layout;
|
std::unique_ptr<KMemoryLayout> memory_layout;
|
||||||
|
|
||||||
// Threads used for services
|
// Threads used for services
|
||||||
std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
|
std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
|
||||||
|
std::weak_ptr<ServiceThread> default_service_thread;
|
||||||
Common::ThreadWorker service_threads_manager;
|
Common::ThreadWorker service_threads_manager;
|
||||||
|
|
||||||
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
|
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
|
||||||
|
@ -1083,6 +1091,10 @@ std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::
|
||||||
return impl->CreateServiceThread(*this, name);
|
return impl->CreateServiceThread(*this, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() {
|
||||||
|
return impl->default_service_thread;
|
||||||
|
}
|
||||||
|
|
||||||
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
||||||
impl->ReleaseServiceThread(service_thread);
|
impl->ReleaseServiceThread(service_thread);
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,15 +277,25 @@ public:
|
||||||
void ExitSVCProfile();
|
void ExitSVCProfile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an HLE service thread, which are used to execute service routines asynchronously.
|
* Creates a host thread to execute HLE service requests, which are used to execute service
|
||||||
* While these are allocated per ServerSession, these need to be owned and managed outside
|
* routines asynchronously. While these are allocated per ServerSession, these need to be owned
|
||||||
* of ServerSession to avoid a circular dependency.
|
* 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
|
* @param name String name for the ServerSession creating this thread, used for debug
|
||||||
* purposes.
|
* purposes.
|
||||||
* @returns The a weak pointer newly created service thread.
|
* @returns The a weak pointer newly created service thread.
|
||||||
*/
|
*/
|
||||||
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name);
|
std::weak_ptr<Kernel::ServiceThread> 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<Kernel::ServiceThread> GetDefaultServiceThread();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when
|
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when
|
||||||
* the ServerSession associated with the thread is destroyed.
|
* the ServerSession associated with the thread is destroyed.
|
||||||
|
|
|
@ -41,9 +41,10 @@ public:
|
||||||
explicit IAudioOut(Core::System& system_, AudoutParams audio_params_,
|
explicit IAudioOut(Core::System& system_, AudoutParams audio_params_,
|
||||||
AudioCore::AudioOut& audio_core_, std::string&& device_name_,
|
AudioCore::AudioOut& audio_core_, std::string&& device_name_,
|
||||||
std::string&& unique_name)
|
std::string&& unique_name)
|
||||||
: ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_},
|
: ServiceFramework{system_, "IAudioOut", true /*create_service_thread*/},
|
||||||
device_name{std::move(device_name_)}, audio_params{audio_params_},
|
audio_core{audio_core_}, device_name{std::move(device_name_)},
|
||||||
main_memory{system.Memory()}, service_context{system_, "IAudioOut"} {
|
audio_params{audio_params_}, main_memory{system.Memory()}, service_context{system_,
|
||||||
|
"IAudioOut"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
|
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
|
||||||
|
|
|
@ -24,7 +24,8 @@ public:
|
||||||
explicit IAudioRenderer(Core::System& system_,
|
explicit IAudioRenderer(Core::System& system_,
|
||||||
const AudioCommon::AudioRendererParameter& audren_params,
|
const AudioCommon::AudioRendererParameter& audren_params,
|
||||||
const std::size_t instance_number)
|
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
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
|
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
|
||||||
|
|
|
@ -58,7 +58,8 @@ enum class FileSystemType : u8 {
|
||||||
class IStorage final : public ServiceFramework<IStorage> {
|
class IStorage final : public ServiceFramework<IStorage> {
|
||||||
public:
|
public:
|
||||||
explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_)
|
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[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IStorage::Read, "Read"},
|
{0, &IStorage::Read, "Read"},
|
||||||
{1, nullptr, "Write"},
|
{1, nullptr, "Write"},
|
||||||
|
@ -116,7 +117,8 @@ private:
|
||||||
class IFile final : public ServiceFramework<IFile> {
|
class IFile final : public ServiceFramework<IFile> {
|
||||||
public:
|
public:
|
||||||
explicit IFile(Core::System& system_, FileSys::VirtualFile backend_)
|
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[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IFile::Read, "Read"},
|
{0, &IFile::Read, "Read"},
|
||||||
{1, &IFile::Write, "Write"},
|
{1, &IFile::Write, "Write"},
|
||||||
|
@ -252,7 +254,8 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec
|
||||||
class IDirectory final : public ServiceFramework<IDirectory> {
|
class IDirectory final : public ServiceFramework<IDirectory> {
|
||||||
public:
|
public:
|
||||||
explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_)
|
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[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IDirectory::Read, "Read"},
|
{0, &IDirectory::Read, "Read"},
|
||||||
{1, &IDirectory::GetEntryCount, "GetEntryCount"},
|
{1, &IDirectory::GetEntryCount, "GetEntryCount"},
|
||||||
|
@ -308,8 +311,8 @@ private:
|
||||||
class IFileSystem final : public ServiceFramework<IFileSystem> {
|
class IFileSystem final : public ServiceFramework<IFileSystem> {
|
||||||
public:
|
public:
|
||||||
explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_)
|
explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_)
|
||||||
: ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move(
|
: ServiceFramework{system_, "IFileSystem", true /*create_service_thread*/},
|
||||||
size_)} {
|
backend{std::move(backend_)}, size{std::move(size_)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IFileSystem::CreateFile, "CreateFile"},
|
{0, &IFileSystem::CreateFile, "CreateFile"},
|
||||||
{1, &IFileSystem::DeleteFile, "DeleteFile"},
|
{1, &IFileSystem::DeleteFile, "DeleteFile"},
|
||||||
|
|
|
@ -879,6 +879,10 @@ void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
|
LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}",
|
||||||
parameters.npad_id, parameters.applet_resource_user_id, parameters.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<Controller_NPad>(HidController::NPad)
|
||||||
|
.SignalStyleSetChangedEvent(parameters.npad_id);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||||
|
|
|
@ -91,9 +91,11 @@ namespace Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
||||||
u32 max_sessions_, InvokerFn* handler_invoker_)
|
bool create_service_thread_, u32 max_sessions_,
|
||||||
: SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
|
InvokerFn* handler_invoker_)
|
||||||
service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{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() {
|
ServiceFrameworkBase::~ServiceFrameworkBase() {
|
||||||
// Wait for other threads to release access before destroying
|
// Wait for other threads to release access before destroying
|
||||||
|
|
|
@ -114,7 +114,8 @@ private:
|
||||||
Kernel::HLERequestContext& ctx);
|
Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
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;
|
~ServiceFrameworkBase() override;
|
||||||
|
|
||||||
void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
|
void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
|
||||||
|
@ -178,12 +179,16 @@ protected:
|
||||||
*
|
*
|
||||||
* @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 service_name_ Name of the service.
|
||||||
* @param max_sessions_ Maximum number of sessions that can be
|
* @param create_service_thread_ Creates a service thread for this if true, otherwise use the
|
||||||
* connected to this service at the same time.
|
* 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_,
|
explicit ServiceFramework(Core::System& system_, const char* service_name_,
|
||||||
|
bool create_service_thread_ = false,
|
||||||
u32 max_sessions_ = ServerSessionCountMax)
|
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.
|
/// Registers handlers in the service.
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
|
|
|
@ -206,7 +206,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SM::SM(ServiceManager& service_manager_, Core::System& system_)
|
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()} {
|
service_manager{service_manager_}, kernel{system_.Kernel()} {
|
||||||
RegisterHandlers({
|
RegisterHandlers({
|
||||||
{0, &SM::Initialize, "Initialize"},
|
{0, &SM::Initialize, "Initialize"},
|
||||||
|
|
|
@ -837,7 +837,8 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co
|
||||||
rb.PushEnum(bsd_errno);
|
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
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &BSD::RegisterClient, "RegisterClient"},
|
{0, &BSD::RegisterClient, "RegisterClient"},
|
||||||
|
|
|
@ -77,7 +77,8 @@ static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
|
||||||
class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
|
class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
|
||||||
public:
|
public:
|
||||||
explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_)
|
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[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
|
{0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
|
||||||
{1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
|
{1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
|
||||||
|
|
Loading…
Reference in a new issue