mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
util::unique_lock, update loader to new sf semantics
This commit is contained in:
parent
3761f80592
commit
e4e278bb3d
9 changed files with 262 additions and 39 deletions
|
@ -42,9 +42,9 @@ namespace ams::fssrv::impl {
|
|||
private:
|
||||
ams::sf::SharedPointer<FileSystemInterfaceAdapter> parent_filesystem;
|
||||
std::unique_ptr<fs::fsa::IFile> base_file;
|
||||
std::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
public:
|
||||
FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, std::unique_lock<fssystem::SemaphoreAdapter> &&sema);
|
||||
FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema);
|
||||
~FileInterfaceAdapter();
|
||||
private:
|
||||
void InvalidateCache();
|
||||
|
@ -64,9 +64,9 @@ namespace ams::fssrv::impl {
|
|||
private:
|
||||
ams::sf::SharedPointer<FileSystemInterfaceAdapter> parent_filesystem;
|
||||
std::unique_ptr<fs::fsa::IDirectory> base_dir;
|
||||
std::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
public:
|
||||
DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, std::unique_lock<fssystem::SemaphoreAdapter> &&sema);
|
||||
DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema);
|
||||
~DirectoryInterfaceAdapter();
|
||||
public:
|
||||
/* Command API */
|
||||
|
@ -79,7 +79,7 @@ namespace ams::fssrv::impl {
|
|||
NON_COPYABLE(FileSystemInterfaceAdapter);
|
||||
private:
|
||||
std::shared_ptr<fs::fsa::IFileSystem> base_fs;
|
||||
std::unique_lock<fssystem::SemaphoreAdapter> mount_count_semaphore;
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> mount_count_semaphore;
|
||||
os::ReadWriteLock invalidation_lock;
|
||||
bool open_count_limited;
|
||||
bool deep_retry_enabled = false;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace ams::fssrv::impl {
|
|||
private:
|
||||
/* TODO: Nintendo uses fssystem::AsynchronousAccessStorage here. */
|
||||
std::shared_ptr<fs::IStorage> base_storage;
|
||||
std::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
os::ReadWriteLock invalidation_lock;
|
||||
/* TODO: DataStorageContext. */
|
||||
bool deep_retry_enabled = false;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
FileInterfaceAdapter::FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, std::unique_lock<fssystem::SemaphoreAdapter> &&sema)
|
||||
FileInterfaceAdapter::FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema)
|
||||
: parent_filesystem(parent, true), base_file(std::move(file)), open_count_semaphore(std::move(sema))
|
||||
{
|
||||
/* ... */
|
||||
|
@ -89,7 +89,7 @@ namespace ams::fssrv::impl {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, std::unique_lock<fssystem::SemaphoreAdapter> &&sema)
|
||||
DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock<fssystem::SemaphoreAdapter> &&sema)
|
||||
: parent_filesystem(parent, true), base_dir(std::move(dir)), open_count_semaphore(std::move(sema))
|
||||
{
|
||||
/* ... */
|
||||
|
@ -236,7 +236,7 @@ namespace ams::fssrv::impl {
|
|||
Result FileSystemInterfaceAdapter::OpenFile(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFile>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
|
||||
std::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
if (this->open_count_limited) {
|
||||
/* TODO: This calls into fssrv::FileSystemProxyImpl, which we don't have yet. */
|
||||
AMS_ABORT_UNLESS(false);
|
||||
|
@ -264,7 +264,7 @@ namespace ams::fssrv::impl {
|
|||
Result FileSystemInterfaceAdapter::OpenDirectory(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDirectory>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
auto read_lock = this->AcquireCacheInvalidationReadLock();
|
||||
|
||||
std::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
util::unique_lock<fssystem::SemaphoreAdapter> open_count_semaphore;
|
||||
if (this->open_count_limited) {
|
||||
/* TODO: This calls into fssrv::FileSystemProxyImpl, which we don't have yet. */
|
||||
AMS_ABORT_UNLESS(false);
|
||||
|
|
|
@ -22,10 +22,10 @@ namespace ams::fssystem {
|
|||
NON_COPYABLE(KeySlotCacheAccessor);
|
||||
NON_MOVEABLE(KeySlotCacheAccessor);
|
||||
private:
|
||||
std::unique_lock<os::Mutex> lk;
|
||||
util::unique_lock<os::Mutex> lk;
|
||||
const s32 slot_index;
|
||||
public:
|
||||
KeySlotCacheAccessor(s32 idx, std::unique_lock<os::Mutex> &&l) : lk(std::move(l)), slot_index(idx) { /* ... */ }
|
||||
KeySlotCacheAccessor(s32 idx, util::unique_lock<os::Mutex> &&l) : lk(std::move(l)), slot_index(idx) { /* ... */ }
|
||||
|
||||
s32 GetKeySlotIndex() const { return this->slot_index; }
|
||||
};
|
||||
|
@ -79,7 +79,7 @@ namespace ams::fssystem {
|
|||
}
|
||||
|
||||
Result Find(std::unique_ptr<KeySlotCacheAccessor> *out, const void *key, size_t key_size, s32 key2) {
|
||||
std::unique_lock lk(this->mutex);
|
||||
util::unique_lock lk(this->mutex);
|
||||
|
||||
KeySlotCacheEntryList *lists[2] = { std::addressof(this->high_priority_mru_list), std::addressof(this->low_priority_mru_list) };
|
||||
for (auto list : lists) {
|
||||
|
@ -100,12 +100,12 @@ namespace ams::fssystem {
|
|||
}
|
||||
|
||||
void AddEntry(KeySlotCacheEntry *entry) {
|
||||
std::unique_lock lk(this->mutex);
|
||||
util::unique_lock lk(this->mutex);
|
||||
this->low_priority_mru_list.push_front(*entry);
|
||||
}
|
||||
private:
|
||||
Result AllocateFromLru(std::unique_ptr<KeySlotCacheAccessor> *out, KeySlotCacheEntryList &dst_list, const void *key, size_t key_size, s32 key2) {
|
||||
std::unique_lock lk(this->mutex);
|
||||
util::unique_lock lk(this->mutex);
|
||||
|
||||
KeySlotCacheEntryList &src_list = this->low_priority_mru_list.empty() ? this->high_priority_mru_list : this->low_priority_mru_list;
|
||||
AMS_ASSERT(!src_list.empty());
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <vapours/util/util_overlap.hpp>
|
||||
#include <vapours/util/util_string_util.hpp>
|
||||
#include <vapours/util/util_string_view.hpp>
|
||||
#include <vapours/util/util_mutex_utils.hpp>
|
||||
#include <vapours/util/util_variadic.hpp>
|
||||
#include <vapours/util/util_character_encoding.hpp>
|
||||
#include <vapours/util/util_format_string.hpp>
|
||||
|
|
141
libraries/libvapours/include/vapours/util/util_mutex_utils.hpp
Normal file
141
libraries/libvapours/include/vapours/util/util_mutex_utils.hpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
template<typename _Mutex>
|
||||
class unique_lock {
|
||||
NON_COPYABLE(unique_lock);
|
||||
public:
|
||||
using mutex_type = _Mutex;
|
||||
private:
|
||||
mutex_type *m_mutex;
|
||||
bool m_owns;
|
||||
public:
|
||||
unique_lock() noexcept : m_mutex(nullptr), m_owns(false) { /* ... */ }
|
||||
|
||||
explicit unique_lock(mutex_type &m) noexcept : m_mutex(std::addressof(m)), m_owns(false) {
|
||||
this->lock();
|
||||
m_owns = true;
|
||||
}
|
||||
|
||||
unique_lock(mutex_type &m, std::defer_lock_t) noexcept : m_mutex(std::addressof(m)), m_owns(false) { /* ... */ }
|
||||
unique_lock(mutex_type &m, std::try_to_lock_t) noexcept : m_mutex(std::addressof(m)), m_owns(m_mutex->try_lock()) { /* ... */ }
|
||||
unique_lock(mutex_type &m, std::adopt_lock_t) noexcept : m_mutex(std::addressof(m)), m_owns(true) { /* ... */ }
|
||||
|
||||
template<typename _Clock, typename _Duration>
|
||||
unique_lock(mutex_type &m, const std::chrono::time_point<_Clock, _Duration> &time) noexcept : m_mutex(std::addressof(m)), m_owns(m_mutex->try_lock_until(time)) { /* ... */ }
|
||||
|
||||
template<typename _Rep, typename _Period>
|
||||
unique_lock(mutex_type &m, const std::chrono::duration<_Rep, _Period> &time) noexcept : m_mutex(std::addressof(m)), m_owns(m_mutex->try_lock_for(time)) { /* ... */ }
|
||||
|
||||
~unique_lock() noexcept {
|
||||
if (m_owns) {
|
||||
this->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
unique_lock(unique_lock &&rhs) noexcept : m_mutex(rhs.m_mutex), m_owns(rhs.m_owns) {
|
||||
rhs.m_mutex = nullptr;
|
||||
rhs.m_owns = false;
|
||||
}
|
||||
|
||||
unique_lock &operator=(unique_lock &&rhs) noexcept {
|
||||
if (m_owns) {
|
||||
this->unlock();
|
||||
}
|
||||
|
||||
unique_lock(std::move(rhs)).swap(*this);
|
||||
|
||||
rhs.m_mutex = nullptr;
|
||||
rhs.m_owns = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void lock() noexcept {
|
||||
AMS_ABORT_UNLESS(m_mutex);
|
||||
AMS_ABORT_UNLESS(!m_owns);
|
||||
|
||||
m_mutex->lock();
|
||||
m_owns = true;
|
||||
}
|
||||
|
||||
bool try_lock() noexcept {
|
||||
AMS_ABORT_UNLESS(m_mutex);
|
||||
AMS_ABORT_UNLESS(!m_owns);
|
||||
|
||||
m_owns = m_mutex->try_lock();
|
||||
return m_owns;
|
||||
}
|
||||
|
||||
template<typename _Clock, typename _Duration>
|
||||
bool try_lock_until(const std::chrono::time_point<_Clock, _Duration> &time) noexcept {
|
||||
AMS_ABORT_UNLESS(m_mutex);
|
||||
AMS_ABORT_UNLESS(!m_owns);
|
||||
m_owns = m_mutex->try_lock_until(time);
|
||||
return m_owns;
|
||||
}
|
||||
|
||||
template<typename _Rep, typename _Period>
|
||||
bool try_lock_for(const std::chrono::duration<_Rep, _Period> &time) noexcept {
|
||||
AMS_ABORT_UNLESS(m_mutex);
|
||||
AMS_ABORT_UNLESS(!m_owns);
|
||||
m_owns = m_mutex->try_lock_for(time);
|
||||
return m_owns;
|
||||
}
|
||||
|
||||
|
||||
void unlock() noexcept {
|
||||
AMS_ABORT_UNLESS(m_owns);
|
||||
if (m_mutex) {
|
||||
m_mutex->unlock();
|
||||
m_owns = false;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(unique_lock &rhs) noexcept {
|
||||
std::swap(m_mutex, rhs.m_mutex);
|
||||
std::swap(m_owns, rhs.m_owns);
|
||||
}
|
||||
|
||||
mutex_type *release() noexcept {
|
||||
mutex_type *ret = m_mutex;
|
||||
m_mutex = nullptr;
|
||||
m_owns = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool owns_lock() const noexcept {
|
||||
return m_owns;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return this->owns_lock();
|
||||
}
|
||||
|
||||
mutex_type *mutex() const noexcept {
|
||||
return m_mutex;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Mutex>
|
||||
inline void swap(unique_lock<_Mutex> &lhs, unique_lock<_Mutex> &rhs) noexcept { return lhs.swap(rhs); }
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
namespace ams::ldr {
|
||||
|
||||
class LoaderService final {
|
||||
class LoaderService {
|
||||
public:
|
||||
/* Official commands. */
|
||||
Result CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle reslimit_h);
|
||||
|
|
|
@ -23,7 +23,7 @@ extern "C" {
|
|||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x8000
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
|
@ -35,6 +35,9 @@ extern "C" {
|
|||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_thread_alloc(size_t size);
|
||||
void __libnx_thread_free(void *mem);
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
@ -55,6 +58,78 @@ void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
|||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
namespace ams::ldr {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_heap_memory[16_KB];
|
||||
lmem::HeapHandle g_server_heap_handle;
|
||||
constinit ams::sf::ExpHeapAllocator g_server_allocator;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
g_server_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
|
||||
g_server_allocator.Attach(g_server_heap_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct ServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
/* ldr:pm, ldr:shel, ldr:dmnt. */
|
||||
enum PortIndex {
|
||||
PortIndex_ProcessManager,
|
||||
PortIndex_Shell,
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr sm::ServiceName ProcessManagerServiceName = sm::ServiceName::Encode("ldr:pm");
|
||||
constexpr size_t ProcessManagerMaxSessions = 1;
|
||||
|
||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("ldr:shel");
|
||||
constexpr size_t ShellMaxSessions = 3;
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ldr:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 3;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<impl::IProcessManagerInterface, LoaderService> g_pm_service;
|
||||
constinit sf::UnmanagedServiceObject<impl::IShellInterface, LoaderService> g_shell_service;
|
||||
constinit sf::UnmanagedServiceObject<impl::IDebugMonitorInterface, LoaderService> g_dmnt_service;
|
||||
|
||||
constexpr size_t MaxSessions = ProcessManagerMaxSessions + ShellMaxSessions + DebugMonitorMaxSessions + 1;
|
||||
|
||||
using ServerManager = ams::sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions>;
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
void RegisterServiceSessions() {
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_pm_service.GetShared(), ProcessManagerServiceName, ProcessManagerMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_shell_service.GetShared(), ShellServiceName, ShellMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_dmnt_service.GetShared(), DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
}
|
||||
|
||||
void LoopProcess() {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
@ -65,11 +140,15 @@ void __libnx_initheap(void) {
|
|||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
ams::ldr::InitializeHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(ldr::Allocate, ldr::Deallocate);
|
||||
|
||||
/* Initialize services we need. */
|
||||
sm::DoWithSession([&]() {
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
@ -89,28 +168,32 @@ void __appExit(void) {
|
|||
fsExit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
namespace ams {
|
||||
|
||||
struct ServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
void *Malloc(size_t size) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
|
||||
constexpr sm::ServiceName ProcessManagerServiceName = sm::ServiceName::Encode("ldr:pm");
|
||||
constexpr size_t ProcessManagerMaxSessions = 1;
|
||||
void Free(void *ptr) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
|
||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("ldr:shel");
|
||||
constexpr size_t ShellMaxSessions = 3;
|
||||
}
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ldr:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 3;
|
||||
void *operator new(size_t size) {
|
||||
return ldr::Allocate(size);
|
||||
}
|
||||
|
||||
/* ldr:pm, ldr:shel, ldr:dmnt. */
|
||||
constexpr size_t NumServers = 3;
|
||||
constexpr size_t MaxSessions = ProcessManagerMaxSessions + ShellMaxSessions + DebugMonitorMaxSessions + 1;
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions> g_server_manager;
|
||||
void operator delete(void *p) {
|
||||
return ldr::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void *__libnx_thread_alloc(size_t size) {
|
||||
AMS_ABORT("__libnx_thread_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_thread_free(void *mem) {
|
||||
AMS_ABORT("__libnx_thread_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -128,13 +211,11 @@ int main(int argc, char **argv)
|
|||
ldr::SetDevelopmentForAntiDowngradeCheck(spl::IsDevelopment());
|
||||
ldr::SetDevelopmentForAcidSignatureCheck(spl::IsDevelopment());
|
||||
|
||||
/* Add services to manager. */
|
||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::impl::IProcessManagerInterface, ldr::LoaderService>(ProcessManagerServiceName, ProcessManagerMaxSessions)));
|
||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::impl::IShellInterface, ldr::LoaderService>(ShellServiceName, ShellMaxSessions)));
|
||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::impl::IDebugMonitorInterface, ldr::LoaderService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
|
||||
/* Register the loader services. */
|
||||
ldr::RegisterServiceSessions();
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
g_server_manager.LoopProcess();
|
||||
ldr::LoopProcess();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -654,7 +654,7 @@ namespace ams::ldr {
|
|||
fssystem::DestroyExternalCode(loc.program_id);
|
||||
|
||||
/* Note that we've created the program. */
|
||||
SetLaunchedProgram(loc.program_id);
|
||||
SetLaunchedBootProgram(loc.program_id);
|
||||
|
||||
/* Move the process handle to output. */
|
||||
*out = info.process_handle.Move();
|
||||
|
|
Loading…
Reference in a new issue