Merge pull request #4341 from wwylele/kernel-global

Kernel: make a kernel instance and remove object ID counter from global state
This commit is contained in:
Weiyi Wang 2018-10-21 18:53:36 -04:00 committed by GitHub
commit 6f1759c5bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
91 changed files with 620 additions and 443 deletions

View file

@ -191,13 +191,13 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) {
rpc_server = std::make_unique<RPC::RPCServer>(); rpc_server = std::make_unique<RPC::RPCServer>();
#endif #endif
service_manager = std::make_shared<Service::SM::ServiceManager>(); service_manager = std::make_shared<Service::SM::ServiceManager>(*this);
shared_page_handler = std::make_shared<SharedPage::Handler>(); shared_page_handler = std::make_shared<SharedPage::Handler>();
archive_manager = std::make_unique<Service::FS::ArchiveManager>(); archive_manager = std::make_unique<Service::FS::ArchiveManager>(*this);
HW::Init(); HW::Init();
Kernel::Init(system_mode); kernel = std::make_unique<Kernel::KernelSystem>(system_mode);
Service::Init(*this, service_manager); Service::Init(*this);
GDBStub::Init(); GDBStub::Init();
ResultStatus result = VideoCore::Init(emu_window); ResultStatus result = VideoCore::Init(emu_window);
@ -230,6 +230,14 @@ const Service::FS::ArchiveManager& System::ArchiveManager() const {
return *archive_manager; return *archive_manager;
} }
Kernel::KernelSystem& System::Kernel() {
return *kernel;
}
const Kernel::KernelSystem& System::Kernel() const {
return *kernel;
}
void System::RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd) { void System::RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard> swkbd) {
registered_swkbd = std::move(swkbd); registered_swkbd = std::move(swkbd);
} }
@ -248,7 +256,7 @@ void System::Shutdown() {
GDBStub::Shutdown(); GDBStub::Shutdown();
VideoCore::Shutdown(); VideoCore::Shutdown();
Service::Shutdown(); Service::Shutdown();
Kernel::Shutdown(); kernel.reset();
HW::Shutdown(); HW::Shutdown();
telemetry_session.reset(); telemetry_session.reset();
#ifdef ENABLE_SCRIPTING #ifdef ENABLE_SCRIPTING

View file

@ -36,6 +36,10 @@ class ArchiveManager;
} }
} // namespace Service } // namespace Service
namespace Kernel {
class KernelSystem;
}
namespace Core { namespace Core {
class System { class System {
@ -167,6 +171,12 @@ public:
/// Gets a const reference to the archive manager /// Gets a const reference to the archive manager
const Service::FS::ArchiveManager& ArchiveManager() const; const Service::FS::ArchiveManager& ArchiveManager() const;
/// Gets a reference to the kernel
Kernel::KernelSystem& Kernel();
/// Gets a const reference to the kernel
const Kernel::KernelSystem& Kernel() const;
PerfStats perf_stats; PerfStats perf_stats;
FrameLimiter frame_limiter; FrameLimiter frame_limiter;
@ -241,6 +251,8 @@ private:
std::unique_ptr<Service::FS::ArchiveManager> archive_manager; std::unique_ptr<Service::FS::ArchiveManager> archive_manager;
std::unique_ptr<Kernel::KernelSystem> kernel;
static System s_instance; static System s_instance;
ResultStatus status = ResultStatus::Success; ResultStatus status = ResultStatus::Success;

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/erreula.h" #include "core/hle/applets/erreula.h"
#include "core/hle/service/apt/apt.h" #include "core/hle/service/apt/apt.h"
@ -30,7 +31,7 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
// Allocate a heap block of the required size for this applet. // Allocate a heap block of the required size for this applet.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Kernel::SharedMemory::CreateForApplet( framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"ErrEula Memory"); "ErrEula Memory");

View file

@ -7,6 +7,7 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/mii_selector.h" #include "core/hle/applets/mii_selector.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/shared_memory.h"
@ -37,7 +38,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
// Allocate a heap block of the required size for this applet. // Allocate a heap block of the required size for this applet.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Kernel::SharedMemory::CreateForApplet( framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"MiiSelector Memory"); "MiiSelector Memory");

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/mint.h" #include "core/hle/applets/mint.h"
#include "core/hle/service/apt/apt.h" #include "core/hle/service/apt/apt.h"
@ -30,7 +31,7 @@ ResultCode Mint::ReceiveParameter(const Service::APT::MessageParameter& paramete
// Allocate a heap block of the required size for this applet. // Allocate a heap block of the required size for this applet.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Kernel::SharedMemory::CreateForApplet( framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"Mint Memory"); "Mint Memory");

View file

@ -8,6 +8,7 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/swkbd.h" #include "core/hle/applets/swkbd.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/shared_memory.h"
@ -41,7 +42,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
// Allocate a heap block of the required size for this applet. // Allocate a heap block of the required size for this applet.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// Create a SharedMemory that directly points to this heap block. // Create a SharedMemory that directly points to this heap block.
framebuffer_memory = Kernel::SharedMemory::CreateForApplet( framebuffer_memory = Core::System::GetInstance().Kernel().CreateSharedMemoryForApplet(
heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
"SoftwareKeyboard Memory"); "SoftwareKeyboard Memory");

View file

@ -7,6 +7,7 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
#include "core/memory.h" #include "core/memory.h"
@ -64,11 +65,11 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
return thread; return thread;
} }
AddressArbiter::AddressArbiter() {} AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel) {}
AddressArbiter::~AddressArbiter() {} AddressArbiter::~AddressArbiter() {}
SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter(*this));
address_arbiter->name = std::move(name); address_arbiter->name = std::move(name);

View file

@ -31,14 +31,6 @@ enum class ArbitrationType : u32 {
class AddressArbiter final : public Object { class AddressArbiter final : public Object {
public: public:
/**
* Creates an address arbiter.
*
* @param name Optional name used for debugging.
* @returns The created AddressArbiter.
*/
static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "Arbiter"; return "Arbiter";
} }
@ -57,7 +49,7 @@ public:
s32 value, u64 nanoseconds); s32 value, u64 nanoseconds);
private: private:
AddressArbiter(); explicit AddressArbiter(KernelSystem& kernel);
~AddressArbiter() override; ~AddressArbiter() override;
/// Puts the thread to wait on the specified arbitration address under this address arbiter. /// Puts the thread to wait on the specified arbitration address under this address arbiter.
@ -72,6 +64,8 @@ private:
/// Threads waiting for the address arbiter to be signaled. /// Threads waiting for the address arbiter to be signaled.
std::vector<SharedPtr<Thread>> waiting_threads; std::vector<SharedPtr<Thread>> waiting_threads;
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -13,7 +13,7 @@
namespace Kernel { namespace Kernel {
ClientPort::ClientPort() = default; ClientPort::ClientPort(KernelSystem& kernel) : kernel(kernel), Object(kernel) {}
ClientPort::~ClientPort() = default; ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() { ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
@ -26,7 +26,7 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
active_sessions++; active_sessions++;
// Create a new session pair, let the created sessions inherit the parent port's HLE handler. // Create a new session pair, let the created sessions inherit the parent port's HLE handler.
auto sessions = ServerSession::CreateSessionPair(server_port->GetName(), this); auto sessions = kernel.CreateSessionPair(server_port->GetName(), this);
if (server_port->hle_handler) if (server_port->hle_handler)
server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));

View file

@ -48,13 +48,16 @@ public:
void ConnectionClosed(); void ConnectionClosed();
private: private:
ClientPort(); explicit ClientPort(KernelSystem& kernel);
~ClientPort() override; ~ClientPort() override;
KernelSystem& kernel;
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
u32 active_sessions = 0; ///< Number of currently open sessions to this port u32 active_sessions = 0; ///< Number of currently open sessions to this port
std::string name; ///< Name of client port (optional) std::string name; ///< Name of client port (optional)
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -13,7 +13,7 @@
namespace Kernel { namespace Kernel {
ClientSession::ClientSession() = default; ClientSession::ClientSession(KernelSystem& kernel) : Object(kernel) {}
ClientSession::~ClientSession() { ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by // This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application. // the emulated application.

View file

@ -12,13 +12,12 @@
namespace Kernel { namespace Kernel {
class ServerSession;
class Session; class Session;
class Thread; class Thread;
class ClientSession final : public Object { class ClientSession final : public Object {
public: public:
friend class ServerSession; friend class KernelSystem;
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "ClientSession"; return "ClientSession";
@ -46,7 +45,7 @@ public:
std::shared_ptr<Session> parent; std::shared_ptr<Session> parent;
private: private:
ClientSession(); explicit ClientSession(KernelSystem& kernel);
~ClientSession() override; ~ClientSession() override;
}; };

View file

@ -7,16 +7,16 @@
#include <vector> #include <vector>
#include "common/assert.h" #include "common/assert.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
namespace Kernel { namespace Kernel {
Event::Event() {} Event::Event(KernelSystem& kernel) : WaitObject(kernel) {}
Event::~Event() {} Event::~Event() {}
SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { SharedPtr<Event> KernelSystem::CreateEvent(ResetType reset_type, std::string name) {
SharedPtr<Event> evt(new Event); SharedPtr<Event> evt(new Event(*this));
evt->signaled = false; evt->signaled = false;
evt->reset_type = reset_type; evt->reset_type = reset_type;

View file

@ -12,13 +12,6 @@ namespace Kernel {
class Event final : public WaitObject { class Event final : public WaitObject {
public: public:
/**
* Creates an event
* @param reset_type ResetType describing how to create event
* @param name Optional name of event
*/
static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "Event"; return "Event";
} }
@ -47,13 +40,15 @@ public:
void Clear(); void Clear();
private: private:
Event(); explicit Event(KernelSystem& kernel);
~Event() override; ~Event() override;
ResetType reset_type; ///< Current ResetType ResetType reset_type; ///< Current ResetType
bool signaled; ///< Whether the event has already been signaled bool signaled; ///< Whether the event has already been signaled
std::string name; ///< Name of event (optional) std::string name; ///< Name of event (optional)
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h" #include "core/hle/kernel/hle_ipc.h"
@ -55,7 +56,8 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
cmd_buff.size() * sizeof(u32)); cmd_buff.size() * sizeof(u32));
}; };
auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason); auto event = Core::System::GetInstance().Kernel().CreateEvent(Kernel::ResetType::OneShot,
"HLE Pause Event: " + reason);
thread->status = ThreadStatus::WaitHleEvent; thread->status = ThreadStatus::WaitHleEvent;
thread->wait_objects = {event}; thread->wait_objects = {event};
event->AddWaitingThread(thread); event->AddWaitingThread(thread);

View file

@ -14,34 +14,41 @@
namespace Kernel { namespace Kernel {
std::atomic<u32> Object::next_object_id{0};
/// Initialize the kernel /// Initialize the kernel
void Init(u32 system_mode) { KernelSystem::KernelSystem(u32 system_mode) {
ConfigMem::Init(); ConfigMem::Init();
Kernel::MemoryInit(system_mode); Kernel::MemoryInit(system_mode);
Kernel::ResourceLimitsInit(); resource_limits = std::make_unique<ResourceLimitList>(*this);
Kernel::ThreadingInit(); Kernel::ThreadingInit();
Kernel::TimersInit(); Kernel::TimersInit();
Object::next_object_id = 0;
// TODO(Subv): Start the process ids from 10 for now, as lower PIDs are // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
// reserved for low-level services // reserved for low-level services
Process::next_process_id = 10; Process::next_process_id = 10;
} }
/// Shutdown the kernel /// Shutdown the kernel
void Shutdown() { KernelSystem::~KernelSystem() {
g_handle_table.Clear(); // Free all kernel objects g_handle_table.Clear(); // Free all kernel objects
Kernel::ThreadingShutdown(); Kernel::ThreadingShutdown();
g_current_process = nullptr; g_current_process = nullptr;
Kernel::TimersShutdown(); Kernel::TimersShutdown();
Kernel::ResourceLimitsShutdown();
Kernel::MemoryShutdown(); Kernel::MemoryShutdown();
} }
ResourceLimitList& KernelSystem::ResourceLimit() {
return *resource_limits;
}
const ResourceLimitList& KernelSystem::ResourceLimit() const {
return *resource_limits;
}
u32 KernelSystem::GenerateObjectID() {
return next_object_id++;
}
} // namespace Kernel } // namespace Kernel

View file

@ -4,14 +4,185 @@
#pragma once #pragma once
#include <atomic>
#include <memory>
#include <string>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/result.h"
namespace Kernel { namespace Kernel {
/// Initialize the kernel with the specified system mode. class AddressArbiter;
void Init(u32 system_mode); class Event;
class Mutex;
class CodeSet;
class Process;
class Thread;
class Semaphore;
class Timer;
class ClientPort;
class ServerPort;
class ClientSession;
class ServerSession;
class ResourceLimitList;
class SharedMemory;
/// Shutdown the kernel enum class ResetType {
void Shutdown(); OneShot,
Sticky,
Pulse,
};
/// Permissions for mapped shared memory blocks
enum class MemoryPermission : u32 {
None = 0,
Read = (1u << 0),
Write = (1u << 1),
ReadWrite = (Read | Write),
Execute = (1u << 2),
ReadExecute = (Read | Execute),
WriteExecute = (Write | Execute),
ReadWriteExecute = (Read | Write | Execute),
DontCare = (1u << 28)
};
enum class MemoryRegion : u16 {
APPLICATION = 1,
SYSTEM = 2,
BASE = 3,
};
template <typename T>
using SharedPtr = boost::intrusive_ptr<T>;
class KernelSystem {
public:
explicit KernelSystem(u32 system_mode);
~KernelSystem();
/**
* Creates an address arbiter.
*
* @param name Optional name used for debugging.
* @returns The created AddressArbiter.
*/
SharedPtr<AddressArbiter> CreateAddressArbiter(std::string name = "Unknown");
/**
* Creates an event
* @param reset_type ResetType describing how to create event
* @param name Optional name of event
*/
SharedPtr<Event> CreateEvent(ResetType reset_type, std::string name = "Unknown");
/**
* Creates a mutex.
* @param initial_locked Specifies if the mutex should be locked initially
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
SharedPtr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown");
SharedPtr<CodeSet> CreateCodeSet(std::string name, u64 program_id);
SharedPtr<Process> CreateProcess(SharedPtr<CodeSet> code_set);
/**
* Creates and returns a new thread. The new thread is immediately scheduled
* @param name The friendly name desired for the thread
* @param entry_point The address at which the thread should start execution
* @param priority The thread's priority
* @param arg User data to pass to the thread
* @param processor_id The ID(s) of the processors on which the thread is desired to be run
* @param stack_top The address of the thread's stack top
* @param owner_process The parent process for the thread
* @return A shared pointer to the newly created thread
*/
ResultVal<SharedPtr<Thread>> CreateThread(std::string name, VAddr entry_point, u32 priority,
u32 arg, s32 processor_id, VAddr stack_top,
SharedPtr<Process> owner_process);
/**
* Creates a semaphore.
* @param initial_count Number of slots reserved for other threads
* @param max_count Maximum number of slots the semaphore can have
* @param name Optional name of semaphore
* @return The created semaphore
*/
ResultVal<SharedPtr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count,
std::string name = "Unknown");
/**
* Creates a timer
* @param reset_type ResetType describing how to create the timer
* @param name Optional name of timer
* @return The created Timer
*/
SharedPtr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
/**
* Creates a pair of ServerPort and an associated ClientPort.
*
* @param max_sessions Maximum number of sessions to the port
* @param name Optional name of the ports
* @return The created port tuple
*/
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
u32 max_sessions, std::string name = "UnknownPort");
/**
* Creates a pair of ServerSession and an associated ClientSession.
* @param name Optional name of the ports.
* @param client_port Optional The ClientPort that spawned this session.
* @return The created session tuple
*/
std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> CreateSessionPair(
const std::string& name = "Unknown", SharedPtr<ClientPort> client_port = nullptr);
ResourceLimitList& ResourceLimit();
const ResourceLimitList& ResourceLimit() const;
/**
* Creates a shared memory object.
* @param owner_process Process that created this shared memory object.
* @param size Size of the memory block. Must be page-aligned.
* @param permissions Permission restrictions applied to the process which created the block.
* @param other_permissions Permission restrictions applied to other processes mapping the
* block.
* @param address The address from which to map the Shared Memory.
* @param region If the address is 0, the shared memory will be allocated in this region of the
* linear heap.
* @param name Optional object name, used for debugging purposes.
*/
SharedPtr<SharedMemory> CreateSharedMemory(SharedPtr<Process> owner_process, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
VAddr address = 0,
MemoryRegion region = MemoryRegion::BASE,
std::string name = "Unknown");
/**
* Creates a shared memory object from a block of memory managed by an HLE applet.
* @param heap_block Heap block of the HLE applet.
* @param offset The offset into the heap block that the SharedMemory will map.
* @param size Size of the memory block. Must be page-aligned.
* @param permissions Permission restrictions applied to the process which created the block.
* @param other_permissions Permission restrictions applied to other processes mapping the
* block.
* @param name Optional object name, used for debugging purposes.
*/
SharedPtr<SharedMemory> CreateSharedMemoryForApplet(std::shared_ptr<std::vector<u8>> heap_block,
u32 offset, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
u32 GenerateObjectID();
private:
std::unique_ptr<ResourceLimitList> resource_limits;
std::atomic<u32> next_object_id{0};
};
} // namespace Kernel } // namespace Kernel

View file

@ -24,11 +24,11 @@ void ReleaseThreadMutexes(Thread* thread) {
thread->held_mutexes.clear(); thread->held_mutexes.clear();
} }
Mutex::Mutex() {} Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel) {}
Mutex::~Mutex() {} Mutex::~Mutex() {}
SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
SharedPtr<Mutex> mutex(new Mutex); SharedPtr<Mutex> mutex(new Mutex(*this));
mutex->lock_count = 0; mutex->lock_count = 0;
mutex->name = std::move(name); mutex->name = std::move(name);

View file

@ -16,14 +16,6 @@ class Thread;
class Mutex final : public WaitObject { class Mutex final : public WaitObject {
public: public:
/**
* Creates a mutex.
* @param initial_locked Specifies if the mutex should be locked initially
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "Mutex"; return "Mutex";
} }
@ -61,8 +53,10 @@ public:
ResultCode Release(Thread* thread); ResultCode Release(Thread* thread);
private: private:
Mutex(); explicit Mutex(KernelSystem& kernel);
~Mutex() override; ~Mutex() override;
friend class KernelSystem;
}; };
/** /**

View file

@ -3,10 +3,13 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/assert.h" #include "common/assert.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
namespace Kernel { namespace Kernel {
Object::Object(KernelSystem& kernel) : object_id{kernel.GenerateObjectID()} {}
Object::~Object() = default; Object::~Object() = default;
bool Object::IsWaitable() const { bool Object::IsWaitable() const {

View file

@ -6,13 +6,13 @@
#include <atomic> #include <atomic>
#include <string> #include <string>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel { namespace Kernel {
class KernelSystem;
using Handle = u32; using Handle = u32;
enum class HandleType : u32 { enum class HandleType : u32 {
@ -37,14 +37,9 @@ enum {
DEFAULT_STACK_SIZE = 0x4000, DEFAULT_STACK_SIZE = 0x4000,
}; };
enum class ResetType {
OneShot,
Sticky,
Pulse,
};
class Object : NonCopyable { class Object : NonCopyable {
public: public:
explicit Object(KernelSystem& kernel);
virtual ~Object(); virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only. /// Returns a unique identifier for the object. For debugging purposes only.
@ -66,15 +61,12 @@ public:
*/ */
bool IsWaitable() const; bool IsWaitable() const;
public:
static std::atomic<u32> next_object_id;
private: private:
friend void intrusive_ptr_add_ref(Object*); friend void intrusive_ptr_add_ref(Object*);
friend void intrusive_ptr_release(Object*); friend void intrusive_ptr_release(Object*);
std::atomic<u32> ref_count{0}; std::atomic<u32> ref_count{0};
std::atomic<u32> object_id{next_object_id++}; std::atomic<u32> object_id;
}; };
// Special functions used by boost::instrusive_ptr to do automatic ref-counting // Special functions used by boost::instrusive_ptr to do automatic ref-counting
@ -88,9 +80,6 @@ inline void intrusive_ptr_release(Object* object) {
} }
} }
template <typename T>
using SharedPtr = boost::intrusive_ptr<T>;
/** /**
* Attempts to downcast the given Object pointer to a pointer to T. * Attempts to downcast the given Object pointer to a pointer to T.
* @return Derived pointer to the object, or `nullptr` if `object` isn't of type T. * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.

View file

@ -20,8 +20,8 @@ namespace Kernel {
// Lists all processes that exist in the current session. // Lists all processes that exist in the current session.
static std::vector<SharedPtr<Process>> process_list; static std::vector<SharedPtr<Process>> process_list;
SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
SharedPtr<CodeSet> codeset(new CodeSet); SharedPtr<CodeSet> codeset(new CodeSet(*this));
codeset->name = std::move(name); codeset->name = std::move(name);
codeset->program_id = program_id; codeset->program_id = program_id;
@ -29,13 +29,13 @@ SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) {
return codeset; return codeset;
} }
CodeSet::CodeSet() {} CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {}
CodeSet::~CodeSet() {} CodeSet::~CodeSet() {}
u32 Process::next_process_id; u32 Process::next_process_id;
SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) { SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) {
SharedPtr<Process> process(new Process); SharedPtr<Process> process(new Process(*this));
process->codeset = std::move(code_set); process->codeset = std::move(code_set);
process->flags.raw = 0; process->flags.raw = 0;
@ -155,7 +155,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
status = ProcessStatus::Running; status = ProcessStatus::Running;
vm_manager.LogLayout(Log::Level::Debug); vm_manager.LogLayout(Log::Level::Debug);
Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this); Kernel::SetupMainThread(kernel, codeset->entrypoint, main_thread_priority, this);
} }
VAddr Process::GetLinearHeapAreaAddress() const { VAddr Process::GetLinearHeapAreaAddress() const {
@ -304,7 +304,7 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
Kernel::Process::Process() {} Kernel::Process::Process(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
Kernel::Process::~Process() {} Kernel::Process::~Process() {}
void ClearProcessList() { void ClearProcessList() {

View file

@ -26,12 +26,6 @@ struct AddressMapping {
bool unk_flag; bool unk_flag;
}; };
enum class MemoryRegion : u16 {
APPLICATION = 1,
SYSTEM = 2,
BASE = 3,
};
union ProcessFlags { union ProcessFlags {
u16 raw; u16 raw;
@ -62,8 +56,6 @@ struct CodeSet final : public Object {
u32 size = 0; u32 size = 0;
}; };
static SharedPtr<CodeSet> Create(std::string name, u64 program_id);
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "CodeSet"; return "CodeSet";
} }
@ -111,14 +103,14 @@ struct CodeSet final : public Object {
u64 program_id; u64 program_id;
private: private:
CodeSet(); explicit CodeSet(KernelSystem& kernel);
~CodeSet() override; ~CodeSet() override;
friend class KernelSystem;
}; };
class Process final : public Object { class Process final : public Object {
public: public:
static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "Process"; return "Process";
} }
@ -201,8 +193,11 @@ public:
ResultCode LinearFree(VAddr target, u32 size); ResultCode LinearFree(VAddr target, u32 size);
private: private:
Process(); explicit Process(Kernel::KernelSystem& kernel);
~Process() override; ~Process() override;
friend class KernelSystem;
KernelSystem& kernel;
}; };
void ClearProcessList(); void ClearProcessList();

View file

@ -9,19 +9,17 @@
namespace Kernel { namespace Kernel {
static SharedPtr<ResourceLimit> resource_limits[4]; ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
ResourceLimit::ResourceLimit() {}
ResourceLimit::~ResourceLimit() {} ResourceLimit::~ResourceLimit() {}
SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { SharedPtr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));
resource_limit->name = std::move(name); resource_limit->name = std::move(name);
return resource_limit; return resource_limit;
} }
SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { SharedPtr<ResourceLimit> ResourceLimitList::GetForCategory(ResourceLimitCategory category) {
switch (category) { switch (category) {
case ResourceLimitCategory::APPLICATION: case ResourceLimitCategory::APPLICATION:
case ResourceLimitCategory::SYS_APPLET: case ResourceLimitCategory::SYS_APPLET:
@ -90,10 +88,10 @@ u32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
} }
} }
void ResourceLimitsInit() { ResourceLimitList::ResourceLimitList(KernelSystem& kernel) {
// Create the four resource limits that the system uses // Create the four resource limits that the system uses
// Create the APPLICATION resource limit // Create the APPLICATION resource limit
SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications"); SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
resource_limit->max_priority = 0x18; resource_limit->max_priority = 0x18;
resource_limit->max_commit = 0x4000000; resource_limit->max_commit = 0x4000000;
resource_limit->max_threads = 0x20; resource_limit->max_threads = 0x20;
@ -107,7 +105,7 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit; resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
// Create the SYS_APPLET resource limit // Create the SYS_APPLET resource limit
resource_limit = ResourceLimit::Create("System Applets"); resource_limit = ResourceLimit::Create(kernel, "System Applets");
resource_limit->max_priority = 0x4; resource_limit->max_priority = 0x4;
resource_limit->max_commit = 0x5E00000; resource_limit->max_commit = 0x5E00000;
resource_limit->max_threads = 0x1D; resource_limit->max_threads = 0x1D;
@ -121,7 +119,7 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit; resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
// Create the LIB_APPLET resource limit // Create the LIB_APPLET resource limit
resource_limit = ResourceLimit::Create("Library Applets"); resource_limit = ResourceLimit::Create(kernel, "Library Applets");
resource_limit->max_priority = 0x4; resource_limit->max_priority = 0x4;
resource_limit->max_commit = 0x600000; resource_limit->max_commit = 0x600000;
resource_limit->max_threads = 0xE; resource_limit->max_threads = 0xE;
@ -135,7 +133,7 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit; resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
// Create the OTHER resource limit // Create the OTHER resource limit
resource_limit = ResourceLimit::Create("Others"); resource_limit = ResourceLimit::Create(kernel, "Others");
resource_limit->max_priority = 0x4; resource_limit->max_priority = 0x4;
resource_limit->max_commit = 0x2180000; resource_limit->max_commit = 0x2180000;
resource_limit->max_threads = 0xE1; resource_limit->max_threads = 0xE1;
@ -149,6 +147,6 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
} }
void ResourceLimitsShutdown() {} ResourceLimitList::~ResourceLimitList() = default;
} // namespace Kernel } // namespace Kernel

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <array>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
@ -34,14 +35,7 @@ public:
/** /**
* Creates a resource limit object. * Creates a resource limit object.
*/ */
static SharedPtr<ResourceLimit> Create(std::string name = "Unknown"); static SharedPtr<ResourceLimit> Create(KernelSystem& kernel, std::string name = "Unknown");
/**
* Retrieves the resource limit associated with the specified resource limit category.
* @param category The resource limit category
* @returns The resource limit associated with the category
*/
static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "ResourceLimit"; return "ResourceLimit";
@ -113,14 +107,24 @@ public:
s32 current_cpu_time = 0; s32 current_cpu_time = 0;
private: private:
ResourceLimit(); explicit ResourceLimit(KernelSystem& kernel);
~ResourceLimit() override; ~ResourceLimit() override;
}; };
/// Initializes the resource limits class ResourceLimitList {
void ResourceLimitsInit(); public:
explicit ResourceLimitList(KernelSystem& kernel);
~ResourceLimitList();
// Destroys the resource limits /**
void ResourceLimitsShutdown(); * Retrieves the resource limit associated with the specified resource limit category.
* @param category The resource limit category
* @returns The resource limit associated with the category
*/
SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
private:
std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
};
} // namespace Kernel } // namespace Kernel

View file

@ -10,16 +10,16 @@
namespace Kernel { namespace Kernel {
Semaphore::Semaphore() {} Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
Semaphore::~Semaphore() {} Semaphore::~Semaphore() {}
ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, ResultVal<SharedPtr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count, s32 max_count,
std::string name) { std::string name) {
if (initial_count > max_count) if (initial_count > max_count)
return ERR_INVALID_COMBINATION_KERNEL; return ERR_INVALID_COMBINATION_KERNEL;
SharedPtr<Semaphore> semaphore(new Semaphore); SharedPtr<Semaphore> semaphore(new Semaphore(*this));
// When the semaphore is created, some slots are reserved for other threads, // When the semaphore is created, some slots are reserved for other threads,
// and the rest is reserved for the caller thread // and the rest is reserved for the caller thread

View file

@ -15,16 +15,6 @@ namespace Kernel {
class Semaphore final : public WaitObject { class Semaphore final : public WaitObject {
public: public:
/**
* Creates a semaphore.
* @param initial_count Number of slots reserved for other threads
* @param max_count Maximum number of slots the semaphore can have
* @param name Optional name of semaphore
* @return The created semaphore
*/
static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "Semaphore"; return "Semaphore";
} }
@ -52,8 +42,10 @@ public:
ResultVal<s32> Release(s32 release_count); ResultVal<s32> Release(s32 release_count);
private: private:
Semaphore(); explicit Semaphore(KernelSystem& kernel);
~Semaphore() override; ~Semaphore() override;
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -13,7 +13,7 @@
namespace Kernel { namespace Kernel {
ServerPort::ServerPort() {} ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {}
ServerPort::~ServerPort() {} ServerPort::~ServerPort() {}
ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() { ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
@ -35,11 +35,11 @@ void ServerPort::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
} }
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair( std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> KernelSystem::CreatePortPair(
u32 max_sessions, std::string name) { u32 max_sessions, std::string name) {
SharedPtr<ServerPort> server_port(new ServerPort); SharedPtr<ServerPort> server_port(new ServerPort(*this));
SharedPtr<ClientPort> client_port(new ClientPort); SharedPtr<ClientPort> client_port(new ClientPort(*this));
server_port->name = name + "_Server"; server_port->name = name + "_Server";
client_port->name = name + "_Client"; client_port->name = name + "_Client";

View file

@ -20,16 +20,6 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject { class ServerPort final : public WaitObject {
public: public:
/**
* Creates a pair of ServerPort and an associated ClientPort.
*
* @param max_sessions Maximum number of sessions to the port
* @param name Optional name of the ports
* @return The created port tuple
*/
static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
u32 max_sessions, std::string name = "UnknownPort");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "ServerPort"; return "ServerPort";
} }
@ -69,8 +59,10 @@ public:
void Acquire(Thread* thread) override; void Acquire(Thread* thread) override;
private: private:
ServerPort(); explicit ServerPort(KernelSystem& kernel);
~ServerPort() override; ~ServerPort() override;
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -13,7 +13,7 @@
namespace Kernel { namespace Kernel {
ServerSession::ServerSession() = default; ServerSession::ServerSession(KernelSystem& kernel) : WaitObject(kernel) {}
ServerSession::~ServerSession() { ServerSession::~ServerSession() {
// This destructor will be called automatically when the last ServerSession handle is closed by // This destructor will be called automatically when the last ServerSession handle is closed by
// the emulated application. // the emulated application.
@ -28,8 +28,8 @@ ServerSession::~ServerSession() {
parent->server = nullptr; parent->server = nullptr;
} }
ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) { ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelSystem& kernel, std::string name) {
SharedPtr<ServerSession> server_session(new ServerSession); SharedPtr<ServerSession> server_session(new ServerSession(kernel));
server_session->name = std::move(name); server_session->name = std::move(name);
server_session->parent = nullptr; server_session->parent = nullptr;
@ -100,10 +100,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name, std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> KernelSystem::CreateSessionPair(
SharedPtr<ClientPort> port) { const std::string& name, SharedPtr<ClientPort> port) {
auto server_session = ServerSession::Create(name + "_Server").Unwrap(); auto server_session = ServerSession::Create(*this, name + "_Server").Unwrap();
SharedPtr<ClientSession> client_session(new ClientSession); SharedPtr<ClientSession> client_session(new ClientSession(*this));
client_session->name = name + "_Client"; client_session->name = name + "_Client";
std::shared_ptr<Session> parent(new Session); std::shared_ptr<Session> parent(new Session);

View file

@ -48,17 +48,6 @@ public:
return HANDLE_TYPE; return HANDLE_TYPE;
} }
using SessionPair = std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>>;
/**
* Creates a pair of ServerSession and an associated ClientSession.
* @param name Optional name of the ports.
* @param client_port Optional The ClientPort that spawned this session.
* @return The created session tuple
*/
static SessionPair CreateSessionPair(const std::string& name = "Unknown",
SharedPtr<ClientPort> client_port = nullptr);
/** /**
* Sets the HLE handler for the session. This handler will be called to service IPC requests * Sets the HLE handler for the session. This handler will be called to service IPC requests
* instead of the regular IPC machinery. (The regular IPC machinery is currently not * instead of the regular IPC machinery. (The regular IPC machinery is currently not
@ -95,16 +84,20 @@ public:
SharedPtr<Thread> currently_handling; SharedPtr<Thread> currently_handling;
private: private:
ServerSession(); explicit ServerSession(KernelSystem& kernel);
~ServerSession() override; ~ServerSession() override;
/** /**
* Creates a server session. The server session can have an optional HLE handler, * Creates a server session. The server session can have an optional HLE handler,
* which will be invoked to handle the IPC requests that this session receives. * which will be invoked to handle the IPC requests that this session receives.
* @param kernel The kernel instance to create the server session on
* @param name Optional name of the server session. * @param name Optional name of the server session.
* @return The created server session * @return The created server session
*/ */
static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown"); static ResultVal<SharedPtr<ServerSession>> Create(KernelSystem& kernel,
std::string name = "Unknown");
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -11,14 +11,15 @@
namespace Kernel { namespace Kernel {
SharedMemory::SharedMemory() {} SharedMemory::SharedMemory(KernelSystem& kernel) : Object(kernel) {}
SharedMemory::~SharedMemory() {} SharedMemory::~SharedMemory() {}
SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(SharedPtr<Process> owner_process, u32 size,
MemoryPermission permissions, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address, MemoryPermission other_permissions,
MemoryRegion region, std::string name) { VAddr address, MemoryRegion region,
SharedPtr<SharedMemory> shared_memory(new SharedMemory); std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory(*this));
shared_memory->owner_process = owner_process; shared_memory->owner_process = owner_process;
shared_memory->name = std::move(name); shared_memory->name = std::move(name);
@ -74,12 +75,10 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
return shared_memory; return shared_memory;
} }
SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, SharedPtr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
u32 offset, u32 size, std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, MemoryPermission permissions,
MemoryPermission permissions, MemoryPermission other_permissions, std::string name) {
MemoryPermission other_permissions, SharedPtr<SharedMemory> shared_memory(new SharedMemory(*this));
std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory);
shared_memory->owner_process = nullptr; shared_memory->owner_process = nullptr;
shared_memory->name = std::move(name); shared_memory->name = std::move(name);

View file

@ -12,55 +12,8 @@
namespace Kernel { namespace Kernel {
/// Permissions for mapped shared memory blocks
enum class MemoryPermission : u32 {
None = 0,
Read = (1u << 0),
Write = (1u << 1),
ReadWrite = (Read | Write),
Execute = (1u << 2),
ReadExecute = (Read | Execute),
WriteExecute = (Write | Execute),
ReadWriteExecute = (Read | Write | Execute),
DontCare = (1u << 28)
};
class SharedMemory final : public Object { class SharedMemory final : public Object {
public: public:
/**
* Creates a shared memory object.
* @param owner_process Process that created this shared memory object.
* @param size Size of the memory block. Must be page-aligned.
* @param permissions Permission restrictions applied to the process which created the block.
* @param other_permissions Permission restrictions applied to other processes mapping the
* block.
* @param address The address from which to map the Shared Memory.
* @param region If the address is 0, the shared memory will be allocated in this region of the
* linear heap.
* @param name Optional object name, used for debugging purposes.
*/
static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address = 0,
MemoryRegion region = MemoryRegion::BASE,
std::string name = "Unknown");
/**
* Creates a shared memory object from a block of memory managed by an HLE applet.
* @param heap_block Heap block of the HLE applet.
* @param offset The offset into the heap block that the SharedMemory will map.
* @param size Size of the memory block. Must be page-aligned.
* @param permissions Permission restrictions applied to the process which created the block.
* @param other_permissions Permission restrictions applied to other processes mapping the
* block.
* @param name Optional object name, used for debugging purposes.
*/
static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
u32 offset, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "SharedMemory"; return "SharedMemory";
} }
@ -125,8 +78,10 @@ public:
std::string name; std::string name;
private: private:
SharedMemory(); explicit SharedMemory(KernelSystem& kernel);
~SharedMemory() override; ~SharedMemory() override;
friend class KernelSystem;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -615,7 +615,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
/// Create an address arbiter (to allocate access to shared resources) /// Create an address arbiter (to allocate access to shared resources)
static ResultCode CreateAddressArbiter(Handle* out_handle) { static ResultCode CreateAddressArbiter(Handle* out_handle) {
SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create(); SharedPtr<AddressArbiter> arbiter = Core::System::GetInstance().Kernel().CreateAddressArbiter();
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(arbiter))); CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(arbiter)));
LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle); LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
return RESULT_SUCCESS; return RESULT_SUCCESS;
@ -761,9 +761,9 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
break; break;
} }
CASCADE_RESULT(SharedPtr<Thread> thread, CASCADE_RESULT(SharedPtr<Thread> thread, Core::System::GetInstance().Kernel().CreateThread(
Thread::Create(name, entry_point, priority, arg, processor_id, stack_top, name, entry_point, priority, arg, processor_id,
g_current_process)); stack_top, g_current_process));
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
FPSCR_ROUND_TOZERO); // 0x03C00000 FPSCR_ROUND_TOZERO); // 0x03C00000
@ -828,7 +828,7 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
/// Create a mutex /// Create a mutex
static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); SharedPtr<Mutex> mutex = Core::System::GetInstance().Kernel().CreateMutex(initial_locked != 0);
mutex->name = fmt::format("mutex-{:08x}", Core::CPU().GetReg(14)); mutex->name = fmt::format("mutex-{:08x}", Core::CPU().GetReg(14));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(mutex))); CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(mutex)));
@ -891,7 +891,8 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) {
/// Creates a semaphore /// Creates a semaphore
static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) { static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count)); CASCADE_RESULT(SharedPtr<Semaphore> semaphore,
Core::System::GetInstance().Kernel().CreateSemaphore(initial_count, max_count));
semaphore->name = fmt::format("semaphore-{:08x}", Core::CPU().GetReg(14)); semaphore->name = fmt::format("semaphore-{:08x}", Core::CPU().GetReg(14));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(semaphore))); CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(semaphore)));
@ -942,8 +943,8 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32
/// Create an event /// Create an event
static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
SharedPtr<Event> evt = Event::Create(static_cast<ResetType>(reset_type), SharedPtr<Event> evt = Core::System::GetInstance().Kernel().CreateEvent(
fmt::format("event-{:08x}", Core::CPU().GetReg(14))); static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(evt))); CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(evt)));
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
@ -985,8 +986,8 @@ static ResultCode ClearEvent(Handle handle) {
/// Creates a timer /// Creates a timer
static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type), SharedPtr<Timer> timer = Core::System::GetInstance().Kernel().CreateTimer(
fmt ::format("timer-{:08x}", Core::CPU().GetReg(14))); static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", Core::CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(timer))); CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(timer)));
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
@ -1104,8 +1105,8 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
if (addr == 0 && g_current_process->flags.shared_device_mem) if (addr == 0 && g_current_process->flags.shared_device_mem)
region = g_current_process->flags.memory_region; region = g_current_process->flags.memory_region;
shared_memory = shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory(
SharedMemory::Create(g_current_process, size, static_cast<MemoryPermission>(my_permission), g_current_process, size, static_cast<MemoryPermission>(my_permission),
static_cast<MemoryPermission>(other_permission), addr, region); static_cast<MemoryPermission>(other_permission), addr, region);
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory))); CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory)));
@ -1118,7 +1119,7 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam
// TODO(Subv): Implement named ports. // TODO(Subv): Implement named ports.
ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented"); ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
auto ports = ServerPort::CreatePortPair(max_sessions); auto ports = Core::System::GetInstance().Kernel().CreatePortPair(max_sessions);
CASCADE_RESULT(*client_port, CASCADE_RESULT(*client_port,
g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports))));
// Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
@ -1141,7 +1142,7 @@ static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_
} }
static ResultCode CreateSession(Handle* server_session, Handle* client_session) { static ResultCode CreateSession(Handle* server_session, Handle* client_session) {
auto sessions = ServerSession::CreateSessionPair(); auto sessions = Core::System::GetInstance().Kernel().CreateSessionPair();
auto& server = std::get<SharedPtr<ServerSession>>(sessions); auto& server = std::get<SharedPtr<ServerSession>>(sessions);
CASCADE_RESULT(*server_session, g_handle_table.Create(std::move(server))); CASCADE_RESULT(*server_session, g_handle_table.Create(std::move(server)));

View file

@ -60,7 +60,7 @@ inline static u32 const NewThreadId() {
return next_thread_id++; return next_thread_id++;
} }
Thread::Thread() : context(Core::CPU().NewContext()) {} Thread::Thread(KernelSystem& kernel) : WaitObject(kernel), context(Core::CPU().NewContext()) {}
Thread::~Thread() {} Thread::~Thread() {}
Thread* GetCurrentThread() { Thread* GetCurrentThread() {
@ -320,8 +320,9 @@ static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContex
context->SetCpsr(USER32MODE | ((entry_point & 1) << 5)); // Usermode and THUMB mode context->SetCpsr(USER32MODE | ((entry_point & 1) << 5)); // Usermode and THUMB mode
} }
ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority, ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
u32 arg, s32 processor_id, VAddr stack_top, u32 priority, u32 arg, s32 processor_id,
VAddr stack_top,
SharedPtr<Process> owner_process) { SharedPtr<Process> owner_process) {
// Check if priority is in ranged. Lowest priority -> highest priority id. // Check if priority is in ranged. Lowest priority -> highest priority id.
if (priority > ThreadPrioLowest) { if (priority > ThreadPrioLowest) {
@ -343,7 +344,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
ErrorSummary::InvalidArgument, ErrorLevel::Permanent); ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
} }
SharedPtr<Thread> thread(new Thread); SharedPtr<Thread> thread(new Thread(*this));
thread_list.push_back(thread); thread_list.push_back(thread);
ready_queue.prepare(priority); ready_queue.prepare(priority);
@ -443,10 +444,11 @@ void Thread::BoostPriority(u32 priority) {
current_priority = priority; current_priority = priority;
} }
SharedPtr<Thread> SetupMainThread(u32 entry_point, u32 priority, SharedPtr<Process> owner_process) { SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
SharedPtr<Process> owner_process) {
// Initialize new "main" thread // Initialize new "main" thread
auto thread_res = auto thread_res =
Thread::Create("main", entry_point, priority, 0, owner_process->ideal_processor, kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor,
Memory::HEAP_VADDR_END, owner_process); Memory::HEAP_VADDR_END, owner_process);
SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); SharedPtr<Thread> thread = std::move(thread_res).Unwrap();

View file

@ -55,21 +55,6 @@ enum class ThreadWakeupReason {
class Thread final : public WaitObject { class Thread final : public WaitObject {
public: public:
/**
* Creates and returns a new thread. The new thread is immediately scheduled
* @param name The friendly name desired for the thread
* @param entry_point The address at which the thread should start execution
* @param priority The thread's priority
* @param arg User data to pass to the thread
* @param processor_id The ID(s) of the processors on which the thread is desired to be run
* @param stack_top The address of the thread's stack top
* @param owner_process The parent process for the thread
* @return A shared pointer to the newly created thread
*/
static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, u32 priority,
u32 arg, s32 processor_id, VAddr stack_top,
SharedPtr<Process> owner_process);
std::string GetName() const override { std::string GetName() const override {
return name; return name;
} }
@ -225,18 +210,22 @@ public:
std::function<WakeupCallback> wakeup_callback; std::function<WakeupCallback> wakeup_callback;
private: private:
Thread(); explicit Thread(KernelSystem&);
~Thread() override; ~Thread() override;
friend class KernelSystem;
}; };
/** /**
* Sets up the primary application thread * Sets up the primary application thread
* @param kernel The kernel instance on which the thread is created
* @param entry_point The address at which the thread should start execution * @param entry_point The address at which the thread should start execution
* @param priority The priority to give the main thread * @param priority The priority to give the main thread
* @param owner_process The parent process for the main thread * @param owner_process The parent process for the main thread
* @return A shared pointer to the main thread * @return A shared pointer to the main thread
*/ */
SharedPtr<Thread> SetupMainThread(u32 entry_point, u32 priority, SharedPtr<Process> owner_process); SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
SharedPtr<Process> owner_process);
/** /**
* Returns whether there are any threads that are ready to run. * Returns whether there are any threads that are ready to run.

View file

@ -19,11 +19,11 @@ static CoreTiming::EventType* timer_callback_event_type = nullptr;
// us to simply use a pool index or similar. // us to simply use a pool index or similar.
static Kernel::HandleTable timer_callback_handle_table; static Kernel::HandleTable timer_callback_handle_table;
Timer::Timer() {} Timer::Timer(KernelSystem& kernel) : WaitObject(kernel) {}
Timer::~Timer() {} Timer::~Timer() {}
SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
SharedPtr<Timer> timer(new Timer); SharedPtr<Timer> timer(new Timer(*this));
timer->reset_type = reset_type; timer->reset_type = reset_type;
timer->signaled = false; timer->signaled = false;

View file

@ -12,14 +12,6 @@ namespace Kernel {
class Timer final : public WaitObject { class Timer final : public WaitObject {
public: public:
/**
* Creates a timer
* @param reset_type ResetType describing how to create the timer
* @param name Optional name of timer
* @return The created Timer
*/
static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {
return "Timer"; return "Timer";
} }
@ -68,7 +60,7 @@ public:
void Signal(s64 cycles_late); void Signal(s64 cycles_late);
private: private:
Timer(); explicit Timer(KernelSystem& kernel);
~Timer() override; ~Timer() override;
ResetType reset_type; ///< The ResetType of this timer ResetType reset_type; ///< The ResetType of this timer
@ -81,6 +73,8 @@ private:
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue. /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle; Handle callback_handle;
friend class KernelSystem;
}; };
/// Initializes the required variables for timers /// Initializes the required variables for timers

View file

@ -16,6 +16,8 @@ class Thread;
/// Class that represents a Kernel object that a thread can be waiting on /// Class that represents a Kernel object that a thread can be waiting on
class WaitObject : public Object { class WaitObject : public Object {
public: public:
using Object::Object;
/** /**
* Check if the specified thread should wait until the object is available * Check if the specified thread should wait until the object is available
* @param thread The thread about which we're deciding. * @param thread The thread about which we're deciding.

View file

@ -1026,8 +1026,8 @@ void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) {
// Create our CIAFile handle for the app to write to, and while the app writes // Create our CIAFile handle for the app to write to, and while the app writes
// Citra will store contents out to sdmc/nand // Citra will store contents out to sdmc/nand
const FileSys::Path cia_path = {}; const FileSys::Path cia_path = {};
auto file = auto file = std::make_shared<Service::FS::File>(
std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(media_type), cia_path); am->system, std::make_unique<CIAFile>(media_type), cia_path);
am->cia_installing = true; am->cia_installing = true;
@ -1053,8 +1053,8 @@ void Module::Interface::BeginImportProgramTemporarily(Kernel::HLERequestContext&
// Create our CIAFile handle for the app to write to, and while the app writes Citra will store // Create our CIAFile handle for the app to write to, and while the app writes Citra will store
// contents out to sdmc/nand // contents out to sdmc/nand
const FileSys::Path cia_path = {}; const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(FS::MediaType::NAND), auto file = std::make_shared<Service::FS::File>(
cia_path); am->system, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path);
am->cia_installing = true; am->cia_installing = true;
@ -1455,16 +1455,16 @@ void Module::Interface::GetMetaDataFromCia(Kernel::HLERequestContext& ctx) {
rb.PushMappedBuffer(output_buffer); rb.PushMappedBuffer(output_buffer);
} }
Module::Module() { Module::Module(Core::System& system) : system(system) {
ScanForAllTitles(); ScanForAllTitles();
system_updater_mutex = Kernel::Mutex::Create(false, "AM::SystemUpdaterMutex"); system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
} }
Module::~Module() = default; Module::~Module() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto am = std::make_shared<Module>(); auto am = std::make_shared<Module>(system);
std::make_shared<AM_APP>(am)->InstallAsService(service_manager); std::make_shared<AM_APP>(am)->InstallAsService(service_manager);
std::make_shared<AM_NET>(am)->InstallAsService(service_manager); std::make_shared<AM_NET>(am)->InstallAsService(service_manager);
std::make_shared<AM_SYS>(am)->InstallAsService(service_manager); std::make_shared<AM_SYS>(am)->InstallAsService(service_manager);

View file

@ -149,7 +149,7 @@ std::string GetMediaTitlePath(Service::FS::MediaType media_type);
class Module final { class Module final {
public: public:
Module(); explicit Module(Core::System& system);
~Module(); ~Module();
class Interface : public ServiceFramework<Interface> { class Interface : public ServiceFramework<Interface> {
@ -573,6 +573,7 @@ private:
*/ */
void ScanForAllTitles(); void ScanForAllTitles();
Core::System& system;
bool cia_installing = false; bool cia_installing = false;
std::array<std::vector<u64_le>, 3> am_title_list; std::array<std::vector<u64_le>, 3> am_title_list;
Kernel::SharedPtr<Kernel::Mutex> system_updater_mutex; Kernel::SharedPtr<Kernel::Mutex> system_updater_mutex;

View file

@ -572,9 +572,9 @@ AppletManager::AppletManager(Core::System& system) : system(system) {
slot_data.registered = false; slot_data.registered = false;
slot_data.loaded = false; slot_data.loaded = false;
slot_data.notification_event = slot_data.notification_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Notification"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Notification");
slot_data.parameter_event = slot_data.parameter_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "APT:Parameter"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "APT:Parameter");
} }
HLE::Applets::Init(); HLE::Applets::Init();
} }

View file

@ -855,11 +855,11 @@ Module::Module(Core::System& system) : system(system) {
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
shared_font_mem = shared_font_mem =
Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB system.Kernel().CreateSharedMemory(nullptr, 0x332000, // 3272 KB
MemoryPermission::ReadWrite, MemoryPermission::Read, 0, MemoryPermission::ReadWrite, MemoryPermission::Read, 0,
Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); Kernel::MemoryRegion::SYSTEM, "APT:SharedFont");
lock = Kernel::Mutex::Create(false, "APT_U:Lock"); lock = system.Kernel().CreateMutex(false, "APT_U:Lock");
} }
Module::~Module() {} Module::~Module() {}

View file

@ -903,15 +903,16 @@ void Module::Interface::GetNsDataNewFlagPrivileged(Kernel::HLERequestContext& ct
Module::Interface::Interface(std::shared_ptr<Module> boss, const char* name, u32 max_session) Module::Interface::Interface(std::shared_ptr<Module> boss, const char* name, u32 max_session)
: ServiceFramework(name, max_session), boss(std::move(boss)) {} : ServiceFramework(name, max_session), boss(std::move(boss)) {}
Module::Module() { Module::Module(Core::System& system) {
using namespace Kernel; using namespace Kernel;
// TODO: verify ResetType // TODO: verify ResetType
task_finish_event = Event::Create(Kernel::ResetType::OneShot, "BOSS::task_finish_event"); task_finish_event =
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "BOSS::task_finish_event");
} }
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto boss = std::make_shared<Module>(); auto boss = std::make_shared<Module>(system);
std::make_shared<BOSS_P>(boss)->InstallAsService(service_manager); std::make_shared<BOSS_P>(boss)->InstallAsService(service_manager);
std::make_shared<BOSS_U>(boss)->InstallAsService(service_manager); std::make_shared<BOSS_U>(boss)->InstallAsService(service_manager);
} }

View file

@ -15,7 +15,7 @@ namespace Service::BOSS {
class Module final { class Module final {
public: public:
Module(); explicit Module(Core::System& system);
~Module() = default; ~Module() = default;
class Interface : public ServiceFramework<Interface> { class Interface : public ServiceFramework<Interface> {

View file

@ -1019,14 +1019,15 @@ void Module::Interface::DriverFinalize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_CAM, "called"); LOG_DEBUG(Service_CAM, "called");
} }
Module::Module() { Module::Module(Core::System& system) {
using namespace Kernel; using namespace Kernel;
for (PortConfig& port : ports) { for (PortConfig& port : ports) {
port.completion_event = Event::Create(ResetType::Sticky, "CAM::completion_event"); port.completion_event =
system.Kernel().CreateEvent(ResetType::Sticky, "CAM::completion_event");
port.buffer_error_interrupt_event = port.buffer_error_interrupt_event =
Event::Create(ResetType::OneShot, "CAM::buffer_error_interrupt_event"); system.Kernel().CreateEvent(ResetType::OneShot, "CAM::buffer_error_interrupt_event");
port.vsync_interrupt_event = port.vsync_interrupt_event =
Event::Create(ResetType::OneShot, "CAM::vsync_interrupt_event"); system.Kernel().CreateEvent(ResetType::OneShot, "CAM::vsync_interrupt_event");
} }
completion_event_callback = CoreTiming::RegisterEvent( completion_event_callback = CoreTiming::RegisterEvent(
"CAM::CompletionEventCallBack", "CAM::CompletionEventCallBack",
@ -1061,7 +1062,7 @@ std::shared_ptr<Module> GetModule(Core::System& system) {
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto cam = std::make_shared<Module>(); auto cam = std::make_shared<Module>(system);
std::make_shared<CAM_U>(cam)->InstallAsService(service_manager); std::make_shared<CAM_U>(cam)->InstallAsService(service_manager);
std::make_shared<CAM_S>(cam)->InstallAsService(service_manager); std::make_shared<CAM_S>(cam)->InstallAsService(service_manager);

View file

@ -241,7 +241,7 @@ static_assert(sizeof(PackageParameterWithContextDetail) == 28,
class Module final { class Module final {
public: public:
Module(); explicit Module(Core::System& system);
~Module(); ~Module();
void ReloadCameraDevices(); void ReloadCameraDevices();

View file

@ -1351,10 +1351,11 @@ Module::SessionData::~SessionData() {
Module::Interface::Interface(std::shared_ptr<Module> cecd, const char* name, u32 max_session) Module::Interface::Interface(std::shared_ptr<Module> cecd, const char* name, u32 max_session)
: ServiceFramework(name, max_session), cecd(std::move(cecd)) {} : ServiceFramework(name, max_session), cecd(std::move(cecd)) {}
Module::Module() { Module::Module(Core::System& system) {
using namespace Kernel; using namespace Kernel;
cecinfo_event = Event::Create(Kernel::ResetType::OneShot, "CECD::cecinfo_event"); cecinfo_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "CECD::cecinfo_event");
change_state_event = Event::Create(Kernel::ResetType::OneShot, "CECD::change_state_event"); change_state_event =
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "CECD::change_state_event");
std::string nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); std::string nand_directory = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
FileSys::ArchiveFactory_SystemSaveData systemsavedata_factory(nand_directory); FileSys::ArchiveFactory_SystemSaveData systemsavedata_factory(nand_directory);
@ -1433,7 +1434,7 @@ Module::~Module() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto cecd = std::make_shared<Module>(); auto cecd = std::make_shared<Module>(system);
std::make_shared<CECD_NDM>(cecd)->InstallAsService(service_manager); std::make_shared<CECD_NDM>(cecd)->InstallAsService(service_manager);
std::make_shared<CECD_S>(cecd)->InstallAsService(service_manager); std::make_shared<CECD_S>(cecd)->InstallAsService(service_manager);
std::make_shared<CECD_U>(cecd)->InstallAsService(service_manager); std::make_shared<CECD_U>(cecd)->InstallAsService(service_manager);

View file

@ -23,7 +23,7 @@ namespace Service::CECD {
class Module final { class Module final {
public: public:
Module(); explicit Module(Core::System& system);
~Module(); ~Module();
enum class CecCommand : u32 { enum class CecCommand : u32 {

View file

@ -19,9 +19,9 @@ void CSND_SND::Initialize(Kernel::HLERequestContext& ctx) {
const u32 offset3 = rp.Pop<u32>(); const u32 offset3 = rp.Pop<u32>();
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
mutex = Kernel::Mutex::Create(false, "CSND:mutex"); mutex = system.Kernel().CreateMutex(false, "CSND:mutex");
shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite, shared_memory = system.Kernel().CreateSharedMemory(
MemoryPermission::ReadWrite, 0, nullptr, size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0,
Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
IPC::RequestBuilder rb = rp.MakeBuilder(1, 3); IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
@ -173,7 +173,7 @@ void CSND_SND::Reset(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_CSND, "(STUBBED) called"); LOG_WARNING(Service_CSND, "(STUBBED) called");
} }
CSND_SND::CSND_SND() : ServiceFramework("csnd:SND", 4) { CSND_SND::CSND_SND(Core::System& system) : ServiceFramework("csnd:SND", 4), system(system) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
// clang-format off // clang-format off
{0x00010140, &CSND_SND::Initialize, "Initialize"}, {0x00010140, &CSND_SND::Initialize, "Initialize"},
@ -196,7 +196,7 @@ CSND_SND::CSND_SND() : ServiceFramework("csnd:SND", 4) {
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
std::make_shared<CSND_SND>()->InstallAsService(service_manager); std::make_shared<CSND_SND>(system)->InstallAsService(service_manager);
} }
} // namespace Service::CSND } // namespace Service::CSND

View file

@ -16,7 +16,7 @@ namespace Service::CSND {
class CSND_SND final : public ServiceFramework<CSND_SND> { class CSND_SND final : public ServiceFramework<CSND_SND> {
public: public:
CSND_SND(); explicit CSND_SND(Core::System& system);
~CSND_SND() = default; ~CSND_SND() = default;
private: private:
@ -174,6 +174,8 @@ private:
}; };
static_assert(sizeof(Type0Command) == 0x20, "Type0Command structure size is wrong"); static_assert(sizeof(Type0Command) == 0x20, "Type0Command structure size is wrong");
Core::System& system;
Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr; Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr;
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr; Kernel::SharedPtr<Kernel::SharedMemory> shared_memory = nullptr;

View file

@ -350,7 +350,7 @@ bool DSP_DSP::HasTooManyEventsRegistered() const {
return number >= max_number_of_interrupt_events; return number >= max_number_of_interrupt_events;
} }
DSP_DSP::DSP_DSP() : ServiceFramework("dsp::DSP", DefaultMaxSessions) { DSP_DSP::DSP_DSP(Core::System& system) : ServiceFramework("dsp::DSP", DefaultMaxSessions) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
// clang-format off // clang-format off
{0x00010040, &DSP_DSP::RecvData, "RecvData"}, {0x00010040, &DSP_DSP::RecvData, "RecvData"},
@ -391,7 +391,8 @@ DSP_DSP::DSP_DSP() : ServiceFramework("dsp::DSP", DefaultMaxSessions) {
RegisterHandlers(functions); RegisterHandlers(functions);
semaphore_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "DSP_DSP::semaphore_event"); semaphore_event =
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "DSP_DSP::semaphore_event");
} }
DSP_DSP::~DSP_DSP() { DSP_DSP::~DSP_DSP() {
@ -401,7 +402,7 @@ DSP_DSP::~DSP_DSP() {
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto dsp = std::make_shared<DSP_DSP>(); auto dsp = std::make_shared<DSP_DSP>(system);
dsp->InstallAsService(service_manager); dsp->InstallAsService(service_manager);
Core::DSP().SetServiceToInterrupt(std::move(dsp)); Core::DSP().SetServiceToInterrupt(std::move(dsp));
} }

View file

@ -17,7 +17,7 @@ namespace Service::DSP {
class DSP_DSP final : public ServiceFramework<DSP_DSP> { class DSP_DSP final : public ServiceFramework<DSP_DSP> {
public: public:
DSP_DSP(); explicit DSP_DSP(Core::System& system);
~DSP_DSP(); ~DSP_DSP();
/// There are three types of interrupts /// There are three types of interrupts

View file

@ -244,7 +244,7 @@ ERR_F::~ERR_F() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto errf = std::make_shared<ERR_F>(system); auto errf = std::make_shared<ERR_F>(system);
errf->InstallAsNamedPort(); errf->InstallAsNamedPort(system.Kernel());
} }
} // namespace Service::ERR } // namespace Service::ERR

View file

@ -87,7 +87,7 @@ ResultVal<std::shared_ptr<File>> ArchiveManager::OpenFileFromArchive(ArchiveHand
if (backend.Failed()) if (backend.Failed())
return backend.Code(); return backend.Code();
auto file = std::shared_ptr<File>(new File(std::move(backend).Unwrap(), path)); auto file = std::shared_ptr<File>(new File(system, std::move(backend).Unwrap(), path));
return MakeResult<std::shared_ptr<File>>(std::move(file)); return MakeResult<std::shared_ptr<File>>(std::move(file));
} }
@ -348,7 +348,7 @@ void ArchiveManager::RegisterSelfNCCH(Loader::AppLoader& app_loader) {
factory->Register(app_loader); factory->Register(app_loader);
} }
ArchiveManager::ArchiveManager() { ArchiveManager::ArchiveManager(Core::System& system) : system(system) {
RegisterArchiveTypes(); RegisterArchiveTypes();
} }

View file

@ -24,6 +24,10 @@ namespace Loader {
class AppLoader; class AppLoader;
} }
namespace Core {
class System;
}
namespace Service::FS { namespace Service::FS {
/// Supported archive types /// Supported archive types
@ -50,7 +54,8 @@ using FileSys::ArchiveFactory;
class ArchiveManager { class ArchiveManager {
public: public:
ArchiveManager(); explicit ArchiveManager(Core::System& system);
/** /**
* Opens an archive * Opens an archive
* @param id_code IdCode of the archive to open * @param id_code IdCode of the archive to open
@ -224,6 +229,8 @@ public:
void RegisterSelfNCCH(Loader::AppLoader& app_loader); void RegisterSelfNCCH(Loader::AppLoader& app_loader);
private: private:
Core::System& system;
/** /**
* Registers an Archive type, instances of which can later be opened using its IdCode. * Registers an Archive type, instances of which can later be opened using its IdCode.
* @param factory File system backend interface to the archive * @param factory File system backend interface to the archive

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/file_backend.h" #include "core/file_sys/file_backend.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
@ -14,8 +15,9 @@
namespace Service::FS { namespace Service::FS {
File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) File::File(Core::System& system, std::unique_ptr<FileSys::FileBackend>&& backend,
: ServiceFramework("", 1), path(path), backend(std::move(backend)) { const FileSys::Path& path)
: ServiceFramework("", 1), path(path), backend(std::move(backend)), system(system) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0x08010100, &File::OpenSubFile, "OpenSubFile"}, {0x08010100, &File::OpenSubFile, "OpenSubFile"},
{0x080200C2, &File::Read, "Read"}, {0x080200C2, &File::Read, "Read"},
@ -195,7 +197,7 @@ void File::OpenLinkFile(Kernel::HLERequestContext& ctx) {
using Kernel::SharedPtr; using Kernel::SharedPtr;
IPC::RequestParser rp(ctx, 0x080C, 0, 0); IPC::RequestParser rp(ctx, 0x080C, 0, 0);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
auto sessions = ServerSession::CreateSessionPair(GetName()); auto sessions = system.Kernel().CreateSessionPair(GetName());
auto server = std::get<SharedPtr<ServerSession>>(sessions); auto server = std::get<SharedPtr<ServerSession>>(sessions);
ClientConnected(server); ClientConnected(server);
@ -243,7 +245,7 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) {
using Kernel::ClientSession; using Kernel::ClientSession;
using Kernel::ServerSession; using Kernel::ServerSession;
using Kernel::SharedPtr; using Kernel::SharedPtr;
auto sessions = ServerSession::CreateSessionPair(GetName()); auto sessions = system.Kernel().CreateSessionPair(GetName());
auto server = std::get<SharedPtr<ServerSession>>(sessions); auto server = std::get<SharedPtr<ServerSession>>(sessions);
ClientConnected(server); ClientConnected(server);
@ -258,7 +260,7 @@ void File::OpenSubFile(Kernel::HLERequestContext& ctx) {
} }
Kernel::SharedPtr<Kernel::ClientSession> File::Connect() { Kernel::SharedPtr<Kernel::ClientSession> File::Connect() {
auto sessions = Kernel::ServerSession::CreateSessionPair(GetName()); auto sessions = system.Kernel().CreateSessionPair(GetName());
auto server = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions); auto server = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);
ClientConnected(server); ClientConnected(server);

View file

@ -8,6 +8,10 @@
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::FS { namespace Service::FS {
struct FileSessionSlot : public Kernel::SessionRequestHandler::SessionDataBase { struct FileSessionSlot : public Kernel::SessionRequestHandler::SessionDataBase {
@ -21,7 +25,8 @@ struct FileSessionSlot : public Kernel::SessionRequestHandler::SessionDataBase {
// Consider splitting ServiceFramework interface. // Consider splitting ServiceFramework interface.
class File final : public ServiceFramework<File, FileSessionSlot> { class File final : public ServiceFramework<File, FileSessionSlot> {
public: public:
File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); File(Core::System& system, std::unique_ptr<FileSys::FileBackend>&& backend,
const FileSys::Path& path);
~File() = default; ~File() = default;
std::string GetName() const { std::string GetName() const {
@ -53,6 +58,8 @@ private:
void GetPriority(Kernel::HLERequestContext& ctx); void GetPriority(Kernel::HLERequestContext& ctx);
void OpenLinkFile(Kernel::HLERequestContext& ctx); void OpenLinkFile(Kernel::HLERequestContext& ctx);
void OpenSubFile(Kernel::HLERequestContext& ctx); void OpenSubFile(Kernel::HLERequestContext& ctx);
Core::System& system;
}; };
} // namespace Service::FS } // namespace Service::FS

View file

@ -286,7 +286,7 @@ void FS_USER::OpenDirectory(Kernel::HLERequestContext& ctx) {
rb.Push(dir_res.Code()); rb.Push(dir_res.Code());
if (dir_res.Succeeded()) { if (dir_res.Succeeded()) {
std::shared_ptr<Directory> directory = *dir_res; std::shared_ptr<Directory> directory = *dir_res;
auto sessions = ServerSession::CreateSessionPair(directory->GetName()); auto sessions = system.Kernel().CreateSessionPair(directory->GetName());
directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); directory->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
rb.PushMoveObjects(std::get<SharedPtr<ClientSession>>(sessions)); rb.PushMoveObjects(std::get<SharedPtr<ClientSession>>(sessions));
} else { } else {
@ -741,7 +741,8 @@ void FS_USER::GetSaveDataSecureValue(Kernel::HLERequestContext& ctx) {
rb.Push<u64>(0); // the secure value rb.Push<u64>(0); // the secure value
} }
FS_USER::FS_USER(ArchiveManager& archives) : ServiceFramework("fs:USER", 30), archives(archives) { FS_USER::FS_USER(Core::System& system)
: ServiceFramework("fs:USER", 30), system(system), archives(system.ArchiveManager()) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0x000100C6, nullptr, "Dummy1"}, {0x000100C6, nullptr, "Dummy1"},
{0x040100C4, nullptr, "Control"}, {0x040100C4, nullptr, "Control"},
@ -860,6 +861,6 @@ FS_USER::FS_USER(ArchiveManager& archives) : ServiceFramework("fs:USER", 30), ar
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
std::make_shared<FS_USER>(system.ArchiveManager())->InstallAsService(service_manager); std::make_shared<FS_USER>(system)->InstallAsService(service_manager);
} }
} // namespace Service::FS } // namespace Service::FS

View file

@ -17,7 +17,7 @@ class ArchiveManager;
class FS_USER final : public ServiceFramework<FS_USER> { class FS_USER final : public ServiceFramework<FS_USER> {
public: public:
explicit FS_USER(ArchiveManager& archives); explicit FS_USER(Core::System& system);
private: private:
void Initialize(Kernel::HLERequestContext& ctx); void Initialize(Kernel::HLERequestContext& ctx);
@ -534,6 +534,7 @@ private:
u32 priority = -1; ///< For SetPriority and GetPriority service functions u32 priority = -1; ///< For SetPriority and GetPriority service functions
Core::System& system;
ArchiveManager& archives; ArchiveManager& archives;
}; };

View file

@ -786,8 +786,8 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 2), system
RegisterHandlers(functions); RegisterHandlers(functions);
using Kernel::MemoryPermission; using Kernel::MemoryPermission;
shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, shared_memory = system.Kernel().CreateSharedMemory(
MemoryPermission::ReadWrite, 0, nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0,
Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); Kernel::MemoryRegion::BASE, "GSP:SharedMemory");
first_initialization = true; first_initialization = true;

View file

@ -359,16 +359,16 @@ std::shared_ptr<Module> Module::Interface::GetModule() const {
Module::Module(Core::System& system) : system(system) { Module::Module(Core::System& system) : system(system) {
using namespace Kernel; using namespace Kernel;
shared_mem = shared_mem = system.Kernel().CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite,
SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, MemoryPermission::Read, 0, MemoryRegion::BASE,
0, MemoryRegion::BASE, "HID:SharedMemory"); "HID:SharedMemory");
// Create event handles // Create event handles
event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); event_pad_or_touch_1 = system.Kernel().CreateEvent(ResetType::OneShot, "HID:EventPadOrTouch1");
event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); event_pad_or_touch_2 = system.Kernel().CreateEvent(ResetType::OneShot, "HID:EventPadOrTouch2");
event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); event_accelerometer = system.Kernel().CreateEvent(ResetType::OneShot, "HID:EventAccelerometer");
event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); event_gyroscope = system.Kernel().CreateEvent(ResetType::OneShot, "HID:EventGyroscope");
event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); event_debug_pad = system.Kernel().CreateEvent(ResetType::OneShot, "HID:EventDebugPad");
// Register update callbacks // Register update callbacks
pad_update_event = pad_update_event =

View file

@ -16,10 +16,10 @@ void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
std::make_shared<IR_U>()->InstallAsService(service_manager); std::make_shared<IR_U>()->InstallAsService(service_manager);
auto ir_user = std::make_shared<IR_USER>(); auto ir_user = std::make_shared<IR_USER>(system);
ir_user->InstallAsService(service_manager); ir_user->InstallAsService(service_manager);
auto ir_rst = std::make_shared<IR_RST>(); auto ir_rst = std::make_shared<IR_RST>(system);
ir_rst->InstallAsService(service_manager); ir_rst->InstallAsService(service_manager);
} }

View file

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
@ -144,14 +145,14 @@ void IR_RST::Shutdown(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_IR, "called"); LOG_DEBUG(Service_IR, "called");
} }
IR_RST::IR_RST() : ServiceFramework("ir:rst", 1) { IR_RST::IR_RST(Core::System& system) : ServiceFramework("ir:rst", 1) {
using namespace Kernel; using namespace Kernel;
// Note: these two kernel objects are even available before Initialize service function is // Note: these two kernel objects are even available before Initialize service function is
// called. // called.
shared_memory = shared_memory = system.Kernel().CreateSharedMemory(nullptr, 0x1000, MemoryPermission::ReadWrite,
SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read, MemoryPermission::Read, 0,
0, MemoryRegion::BASE, "IRRST:SharedMemory"); MemoryRegion::BASE, "IRRST:SharedMemory");
update_event = Event::Create(ResetType::OneShot, "IRRST:UpdateEvent"); update_event = system.Kernel().CreateEvent(ResetType::OneShot, "IRRST:UpdateEvent");
update_callback_id = update_callback_id =
CoreTiming::RegisterEvent("IRRST:UpdateCallBack", [this](u64 userdata, s64 cycles_late) { CoreTiming::RegisterEvent("IRRST:UpdateCallBack", [this](u64 userdata, s64 cycles_late) {

View file

@ -39,7 +39,7 @@ union PadState {
/// Interface to "ir:rst" service /// Interface to "ir:rst" service
class IR_RST final : public ServiceFramework<IR_RST> { class IR_RST final : public ServiceFramework<IR_RST> {
public: public:
IR_RST(); explicit IR_RST(Core::System& system);
~IR_RST(); ~IR_RST();
void ReloadInputDevices(); void ReloadInputDevices();

View file

@ -6,6 +6,7 @@
#include <boost/crc.hpp> #include <boost/crc.hpp>
#include "common/string_util.h" #include "common/string_util.h"
#include "common/swap.h" #include "common/swap.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/shared_memory.h"
@ -380,7 +381,7 @@ void IR_USER::ReleaseReceivedData(Kernel::HLERequestContext& ctx) {
LOG_TRACE(Service_IR, "called, count={}", count); LOG_TRACE(Service_IR, "called, count={}", count);
} }
IR_USER::IR_USER() : ServiceFramework("ir:USER", 1) { IR_USER::IR_USER(Core::System& system) : ServiceFramework("ir:USER", 1) {
const FunctionInfo functions[] = { const FunctionInfo functions[] = {
{0x00010182, nullptr, "InitializeIrNop"}, {0x00010182, nullptr, "InitializeIrNop"},
{0x00020000, &IR_USER::FinalizeIrNop, "FinalizeIrNop"}, {0x00020000, &IR_USER::FinalizeIrNop, "FinalizeIrNop"},
@ -413,9 +414,9 @@ IR_USER::IR_USER() : ServiceFramework("ir:USER", 1) {
using namespace Kernel; using namespace Kernel;
conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); conn_status_event = system.Kernel().CreateEvent(ResetType::OneShot, "IR:ConnectionStatusEvent");
send_event = Event::Create(ResetType::OneShot, "IR:SendEvent"); send_event = system.Kernel().CreateEvent(ResetType::OneShot, "IR:SendEvent");
receive_event = Event::Create(ResetType::OneShot, "IR:ReceiveEvent"); receive_event = system.Kernel().CreateEvent(ResetType::OneShot, "IR:ReceiveEvent");
extra_hid = extra_hid =
std::make_unique<ExtraHID>([this](const std::vector<u8>& data) { PutToReceive(data); }); std::make_unique<ExtraHID>([this](const std::vector<u8>& data) { PutToReceive(data); });

View file

@ -55,7 +55,7 @@ private:
/// Interface to "ir:USER" service /// Interface to "ir:USER" service
class IR_USER final : public ServiceFramework<IR_USER> { class IR_USER final : public ServiceFramework<IR_USER> {
public: public:
IR_USER(); explicit IR_USER(Core::System& system);
~IR_USER(); ~IR_USER();
void ReloadInputDevices(); void ReloadInputDevices();

View file

@ -29,6 +29,11 @@ enum class SampleRate : u8 {
}; };
struct MIC_U::Impl { struct MIC_U::Impl {
explicit Impl(Core::System& system) {
buffer_full_event =
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event");
}
void MapSharedMem(Kernel::HLERequestContext& ctx) { void MapSharedMem(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx, 0x01, 1, 2}; IPC::RequestParser rp{ctx, 0x01, 1, 2};
const u32 size = rp.Pop<u32>(); const u32 size = rp.Pop<u32>();
@ -187,8 +192,7 @@ struct MIC_U::Impl {
} }
u32 client_version = 0; u32 client_version = 0;
Kernel::SharedPtr<Kernel::Event> buffer_full_event = Kernel::SharedPtr<Kernel::Event> buffer_full_event;
Kernel::Event::Create(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event");
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
u8 mic_gain = 0; u8 mic_gain = 0;
bool mic_power = false; bool mic_power = false;
@ -266,7 +270,8 @@ void MIC_U::SetClientVersion(Kernel::HLERequestContext& ctx) {
impl->SetClientVersion(ctx); impl->SetClientVersion(ctx);
} }
MIC_U::MIC_U() : ServiceFramework{"mic:u", 1}, impl{std::make_unique<Impl>()} { MIC_U::MIC_U(Core::System& system)
: ServiceFramework{"mic:u", 1}, impl{std::make_unique<Impl>(system)} {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0x00010042, &MIC_U::MapSharedMem, "MapSharedMem"}, {0x00010042, &MIC_U::MapSharedMem, "MapSharedMem"},
{0x00020000, &MIC_U::UnmapSharedMem, "UnmapSharedMem"}, {0x00020000, &MIC_U::UnmapSharedMem, "UnmapSharedMem"},
@ -293,7 +298,7 @@ MIC_U::~MIC_U() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
std::make_shared<MIC_U>()->InstallAsService(service_manager); std::make_shared<MIC_U>(system)->InstallAsService(service_manager);
} }
} // namespace Service::MIC } // namespace Service::MIC

View file

@ -16,7 +16,7 @@ namespace Service::MIC {
class MIC_U final : public ServiceFramework<MIC_U> { class MIC_U final : public ServiceFramework<MIC_U> {
public: public:
MIC_U(); explicit MIC_U(Core::System& system);
~MIC_U(); ~MIC_U();
private: private:

View file

@ -140,18 +140,18 @@ Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32
Module::Interface::~Interface() = default; Module::Interface::~Interface() = default;
Module::Module() { Module::Module(Core::System& system) {
tag_in_range_event = tag_in_range_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_in_range_event"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
tag_out_of_range_event = tag_out_of_range_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_out_range_event"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NFC::tag_out_range_event");
} }
Module::~Module() = default; Module::~Module() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
auto nfc = std::make_shared<Module>(); auto nfc = std::make_shared<Module>(system);
std::make_shared<NFC_M>(nfc)->InstallAsService(service_manager); std::make_shared<NFC_M>(nfc)->InstallAsService(service_manager);
std::make_shared<NFC_U>(nfc)->InstallAsService(service_manager); std::make_shared<NFC_U>(nfc)->InstallAsService(service_manager);
} }

View file

@ -41,7 +41,7 @@ enum class CommunicationStatus : u8 {
class Module final { class Module final {
public: public:
Module(); explicit Module(Core::System& system);
~Module(); ~Module();
class Interface : public ServiceFramework<Interface> { class Interface : public ServiceFramework<Interface> {

View file

@ -14,7 +14,7 @@ void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
std::make_shared<NIM_AOC>()->InstallAsService(service_manager); std::make_shared<NIM_AOC>()->InstallAsService(service_manager);
std::make_shared<NIM_S>()->InstallAsService(service_manager); std::make_shared<NIM_S>()->InstallAsService(service_manager);
std::make_shared<NIM_U>()->InstallAsService(service_manager); std::make_shared<NIM_U>(system)->InstallAsService(service_manager);
} }
} // namespace Service::NIM } // namespace Service::NIM

View file

@ -2,13 +2,14 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "core/core.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/service/nim/nim_u.h" #include "core/hle/service/nim/nim_u.h"
namespace Service::NIM { namespace Service::NIM {
NIM_U::NIM_U() : ServiceFramework("nim:u", 2) { NIM_U::NIM_U(Core::System& system) : ServiceFramework("nim:u", 2) {
const FunctionInfo functions[] = { const FunctionInfo functions[] = {
{0x00010000, nullptr, "StartSysUpdate"}, {0x00010000, nullptr, "StartSysUpdate"},
{0x00020000, nullptr, "GetUpdateDownloadProgress"}, {0x00020000, nullptr, "GetUpdateDownloadProgress"},
@ -20,7 +21,7 @@ NIM_U::NIM_U() : ServiceFramework("nim:u", 2) {
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
nim_system_update_event = nim_system_update_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "NIM System Update Event"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NIM System Update Event");
} }
NIM_U::~NIM_U() = default; NIM_U::~NIM_U() = default;

View file

@ -6,11 +6,15 @@
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::NIM { namespace Service::NIM {
class NIM_U final : public ServiceFramework<NIM_U> { class NIM_U final : public ServiceFramework<NIM_U> {
public: public:
NIM_U(); explicit NIM_U(Core::System& system);
~NIM_U(); ~NIM_U();
private: private:

View file

@ -839,7 +839,7 @@ void NWM_UDS::Bind(Kernel::HLERequestContext& ctx) {
} }
// Create a new event for this bind node. // Create a new event for this bind node.
auto event = Kernel::Event::Create(Kernel::ResetType::OneShot, auto event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot,
"NWM::BindNodeEvent" + std::to_string(bind_node_id)); "NWM::BindNodeEvent" + std::to_string(bind_node_id));
std::lock_guard<std::mutex> lock(connection_status_mutex); std::lock_guard<std::mutex> lock(connection_status_mutex);
@ -1355,7 +1355,7 @@ static void BeaconBroadcastCallback(u64 userdata, s64 cycles_late) {
beacon_broadcast_event, 0); beacon_broadcast_event, 0);
} }
NWM_UDS::NWM_UDS(Core::System& system) : ServiceFramework("nwm::UDS") { NWM_UDS::NWM_UDS(Core::System& system) : ServiceFramework("nwm::UDS"), system(system) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0x000102C2, nullptr, "Initialize (deprecated)"}, {0x000102C2, nullptr, "Initialize (deprecated)"},
{0x00020000, nullptr, "Scrap"}, {0x00020000, nullptr, "Scrap"},
@ -1388,7 +1388,7 @@ NWM_UDS::NWM_UDS(Core::System& system) : ServiceFramework("nwm::UDS") {
{0x00220402, nullptr, "ScanOnConnection"}, {0x00220402, nullptr, "ScanOnConnection"},
}; };
connection_status_event = connection_status_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "NWM::connection_status_event"); system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NWM::connection_status_event");
RegisterHandlers(functions); RegisterHandlers(functions);

View file

@ -112,6 +112,8 @@ public:
~NWM_UDS(); ~NWM_UDS();
private: private:
Core::System& system;
void UpdateNetworkAttribute(Kernel::HLERequestContext& ctx); void UpdateNetworkAttribute(Kernel::HLERequestContext& ctx);
/** /**

View file

@ -143,11 +143,11 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
port->SetHleHandler(shared_from_this()); port->SetHleHandler(shared_from_this());
} }
void ServiceFrameworkBase::InstallAsNamedPort() { void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelSystem& kernel) {
ASSERT(port == nullptr); ASSERT(port == nullptr);
SharedPtr<ServerPort> server_port; SharedPtr<ServerPort> server_port;
SharedPtr<ClientPort> client_port; SharedPtr<ClientPort> client_port;
std::tie(server_port, client_port) = ServerPort::CreatePortPair(max_sessions, service_name); std::tie(server_port, client_port) = kernel.CreatePortPair(max_sessions, service_name);
server_port->SetHleHandler(shared_from_this()); server_port->SetHleHandler(shared_from_this());
AddNamedPort(service_name, std::move(client_port)); AddNamedPort(service_name, std::move(client_port));
} }
@ -235,8 +235,8 @@ static bool AttemptLLE(const ServiceModuleInfo& service_module) {
} }
/// Initialize ServiceManager /// Initialize ServiceManager
void Init(Core::System& core, std::shared_ptr<SM::ServiceManager>& sm) { void Init(Core::System& core) {
SM::ServiceManager::InstallInterfaces(sm); SM::ServiceManager::InstallInterfaces(core);
for (const auto& service_module : service_module_map) { for (const auto& service_module : service_module_map) {
if (!AttemptLLE(service_module) && service_module.init_function != nullptr) if (!AttemptLLE(service_module) && service_module.init_function != nullptr)

View file

@ -20,6 +20,7 @@ class System;
} }
namespace Kernel { namespace Kernel {
class KernelSystem;
class ClientPort; class ClientPort;
class ServerPort; class ServerPort;
class ServerSession; class ServerSession;
@ -59,7 +60,7 @@ public:
/// Creates a port pair and registers this service with the given ServiceManager. /// Creates a port pair and registers this service with the given ServiceManager.
void InstallAsService(SM::ServiceManager& service_manager); void InstallAsService(SM::ServiceManager& service_manager);
/// Creates a port pair and registers it on the kernel's global port registry. /// Creates a port pair and registers it on the kernel's global port registry.
void InstallAsNamedPort(); void InstallAsNamedPort(Kernel::KernelSystem& kernel);
void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override; void HandleSyncRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session) override;
@ -184,7 +185,7 @@ private:
}; };
/// Initialize ServiceManager /// Initialize ServiceManager
void Init(Core::System& system, std::shared_ptr<SM::ServiceManager>& sm); void Init(Core::System& system);
/// Shutdown ServiceManager /// Shutdown ServiceManager
void Shutdown(); void Shutdown();

View file

@ -4,6 +4,7 @@
#include <tuple> #include <tuple>
#include "common/assert.h" #include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
@ -21,12 +22,14 @@ static ResultCode ValidateServiceName(const std::string& name) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self) { ServiceManager::ServiceManager(Core::System& system) : system(system) {}
ASSERT(self->srv_interface.expired());
auto srv = std::make_shared<SRV>(self); void ServiceManager::InstallInterfaces(Core::System& system) {
srv->InstallAsNamedPort(); ASSERT(system.ServiceManager().srv_interface.expired());
self->srv_interface = srv;
auto srv = std::make_shared<SRV>(system);
srv->InstallAsNamedPort(system.Kernel());
system.ServiceManager().srv_interface = srv;
} }
ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService( ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService(
@ -39,7 +42,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
Kernel::SharedPtr<Kernel::ServerPort> server_port; Kernel::SharedPtr<Kernel::ServerPort> server_port;
Kernel::SharedPtr<Kernel::ClientPort> client_port; Kernel::SharedPtr<Kernel::ClientPort> client_port;
std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, name); std::tie(server_port, client_port) = system.Kernel().CreatePortPair(max_sessions, name);
registered_services.emplace(std::move(name), std::move(client_port)); registered_services.emplace(std::move(name), std::move(client_port));
return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)); return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port));

View file

@ -14,6 +14,10 @@
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Kernel { namespace Kernel {
class ClientSession; class ClientSession;
class SessionRequestHandler; class SessionRequestHandler;
@ -39,7 +43,9 @@ constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorDescription::AlreadyExists, Err
class ServiceManager { class ServiceManager {
public: public:
static void InstallInterfaces(std::shared_ptr<ServiceManager> self); static void InstallInterfaces(Core::System& system);
explicit ServiceManager(Core::System& system);
ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name, ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
unsigned int max_sessions); unsigned int max_sessions);
@ -63,6 +69,7 @@ public:
} }
private: private:
Core::System& system;
std::weak_ptr<SRV> srv_interface; std::weak_ptr<SRV> srv_interface;
/// Map of registered services, retrieved using GetServicePort or ConnectToService. /// Map of registered services, retrieved using GetServicePort or ConnectToService.

View file

@ -5,6 +5,7 @@
#include <tuple> #include <tuple>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc.h" #include "core/hle/ipc.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
@ -62,7 +63,7 @@ void SRV::EnableNotification(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x2, 0, 0); IPC::RequestParser rp(ctx, 0x2, 0, 0);
notification_semaphore = notification_semaphore =
Kernel::Semaphore::Create(0, MAX_PENDING_NOTIFICATIONS, "SRV:Notification").Unwrap(); system.Kernel().CreateSemaphore(0, MAX_PENDING_NOTIFICATIONS, "SRV:Notification").Unwrap();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
@ -103,7 +104,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
Kernel::HLERequestContext& ctx, Kernel::HLERequestContext& ctx,
Kernel::ThreadWakeupReason reason) { Kernel::ThreadWakeupReason reason) {
LOG_ERROR(Service_SRV, "called service={} wakeup", name); LOG_ERROR(Service_SRV, "called service={} wakeup", name);
auto client_port = service_manager->GetServicePort(name); auto client_port = system.ServiceManager().GetServicePort(name);
auto session = client_port.Unwrap()->Connect(); auto session = client_port.Unwrap()->Connect();
if (session.Succeeded()) { if (session.Succeeded()) {
@ -122,7 +123,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
} }
}; };
auto client_port = service_manager->GetServicePort(name); auto client_port = system.ServiceManager().GetServicePort(name);
if (client_port.Failed()) { if (client_port.Failed()) {
if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) { if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) {
LOG_INFO(Service_SRV, "called service={} delayed", name); LOG_INFO(Service_SRV, "called service={} delayed", name);
@ -223,7 +224,7 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) {
std::string name(name_buf.data(), std::min(name_len, name_buf.size())); std::string name(name_buf.data(), std::min(name_len, name_buf.size()));
auto port = service_manager->RegisterService(name, max_sessions); auto port = system.ServiceManager().RegisterService(name, max_sessions);
if (port.Failed()) { if (port.Failed()) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@ -243,8 +244,7 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) {
rb.PushMoveObjects(port.Unwrap()); rb.PushMoveObjects(port.Unwrap());
} }
SRV::SRV(std::shared_ptr<ServiceManager> service_manager) SRV::SRV(Core::System& system) : ServiceFramework("srv:", 4), system(system) {
: ServiceFramework("srv:", 4), service_manager(std::move(service_manager)) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0x00010002, &SRV::RegisterClient, "RegisterClient"}, {0x00010002, &SRV::RegisterClient, "RegisterClient"},
{0x00020000, &SRV::EnableNotification, "EnableNotification"}, {0x00020000, &SRV::EnableNotification, "EnableNotification"},

View file

@ -8,6 +8,10 @@
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Kernel { namespace Kernel {
class HLERequestContext; class HLERequestContext;
class Semaphore; class Semaphore;
@ -18,7 +22,7 @@ namespace Service::SM {
/// Interface to "srv:" service /// Interface to "srv:" service
class SRV final : public ServiceFramework<SRV> { class SRV final : public ServiceFramework<SRV> {
public: public:
explicit SRV(std::shared_ptr<ServiceManager> service_manager); explicit SRV(Core::System& system);
~SRV(); ~SRV();
private: private:
@ -30,7 +34,7 @@ private:
void PublishToSubscriber(Kernel::HLERequestContext& ctx); void PublishToSubscriber(Kernel::HLERequestContext& ctx);
void RegisterService(Kernel::HLERequestContext& ctx); void RegisterService(Kernel::HLERequestContext& ctx);
std::shared_ptr<ServiceManager> service_manager; Core::System& system;
Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore; Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore;
std::unordered_map<std::string, Kernel::SharedPtr<Kernel::Event>> std::unordered_map<std::string, Kernel::SharedPtr<Kernel::Event>>
get_service_handle_delayed_map; get_service_handle_delayed_map;

View file

@ -632,7 +632,7 @@ void Y2R_U::GetPackageParameter(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Y2R, "called"); LOG_DEBUG(Service_Y2R, "called");
} }
Y2R_U::Y2R_U() : ServiceFramework("y2r:u", 1) { Y2R_U::Y2R_U(Core::System& system) : ServiceFramework("y2r:u", 1) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0x00010040, &Y2R_U::SetInputFormat, "SetInputFormat"}, {0x00010040, &Y2R_U::SetInputFormat, "SetInputFormat"},
{0x00020000, &Y2R_U::GetInputFormat, "GetInputFormat"}, {0x00020000, &Y2R_U::GetInputFormat, "GetInputFormat"},
@ -682,14 +682,14 @@ Y2R_U::Y2R_U() : ServiceFramework("y2r:u", 1) {
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
completion_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "Y2R:Completed"); completion_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "Y2R:Completed");
} }
Y2R_U::~Y2R_U() = default; Y2R_U::~Y2R_U() = default;
void InstallInterfaces(Core::System& system) { void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager(); auto& service_manager = system.ServiceManager();
std::make_shared<Y2R_U>()->InstallAsService(service_manager); std::make_shared<Y2R_U>(system)->InstallAsService(service_manager);
} }
} // namespace Service::Y2R } // namespace Service::Y2R

View file

@ -149,7 +149,7 @@ static_assert(sizeof(ConversionParameters) == 12, "ConversionParameters struct h
class Y2R_U final : public ServiceFramework<Y2R_U> { class Y2R_U final : public ServiceFramework<Y2R_U> {
public: public:
Y2R_U(); explicit Y2R_U(Core::System& system);
~Y2R_U() override; ~Y2R_U() override;
private: private:

View file

@ -217,7 +217,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
} }
// Create the CodeSet // Create the CodeSet
SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); SharedPtr<CodeSet> code_set = Core::System::GetInstance().Kernel().CreateCodeSet("", 0);
code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data(); code_set->CodeSegment().offset = loadinfo.seg_ptrs[0] - program_image.data();
code_set->CodeSegment().addr = loadinfo.seg_addrs[0]; code_set->CodeSegment().addr = loadinfo.seg_addrs[0];
@ -267,13 +267,13 @@ ResultStatus AppLoader_THREEDSX::Load(Kernel::SharedPtr<Kernel::Process>& proces
return ResultStatus::Error; return ResultStatus::Error;
codeset->name = filename; codeset->name = filename;
process = Kernel::Process::Create(std::move(codeset)); process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset));
process->svc_access_mask.set(); process->svc_access_mask.set();
process->address_mappings = default_address_mappings; process->address_mappings = default_address_mappings;
// Attach the default resource limit (APPLICATION) to the process // Attach the default resource limit (APPLICATION) to the process
process->resource_limit = process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory(
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); Kernel::ResourceLimitCategory::APPLICATION);
process->Run(48, Kernel::DEFAULT_STACK_SIZE); process->Run(48, Kernel::DEFAULT_STACK_SIZE);

View file

@ -8,6 +8,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/resource_limit.h"
#include "core/loader/elf.h" #include "core/loader/elf.h"
@ -299,7 +300,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
std::vector<u8> program_image(total_image_size); std::vector<u8> program_image(total_image_size);
std::size_t current_image_position = 0; std::size_t current_image_position = 0;
SharedPtr<CodeSet> codeset = CodeSet::Create("", 0); SharedPtr<CodeSet> codeset = Core::System::GetInstance().Kernel().CreateCodeSet("", 0);
for (unsigned int i = 0; i < header->e_phnum; ++i) { for (unsigned int i = 0; i < header->e_phnum; ++i) {
Elf32_Phdr* p = &segments[i]; Elf32_Phdr* p = &segments[i];
@ -395,13 +396,13 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
codeset->name = filename; codeset->name = filename;
process = Kernel::Process::Create(std::move(codeset)); process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset));
process->svc_access_mask.set(); process->svc_access_mask.set();
process->address_mappings = default_address_mappings; process->address_mappings = default_address_mappings;
// Attach the default resource limit (APPLICATION) to the process // Attach the default resource limit (APPLICATION) to the process
process->resource_limit = process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory(
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); Kernel::ResourceLimitCategory::APPLICATION);
process->Run(48, Kernel::DEFAULT_STACK_SIZE); process->Run(48, Kernel::DEFAULT_STACK_SIZE);

View file

@ -75,7 +75,8 @@ ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& proces
std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
(const char*)overlay_ncch->exheader_header.codeset_info.name, 8); (const char*)overlay_ncch->exheader_header.codeset_info.name, 8);
SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, program_id); SharedPtr<CodeSet> codeset =
Core::System::GetInstance().Kernel().CreateCodeSet(process_name, program_id);
codeset->CodeSegment().offset = 0; codeset->CodeSegment().offset = 0;
codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address; codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address;
@ -103,11 +104,12 @@ ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& proces
codeset->entrypoint = codeset->CodeSegment().addr; codeset->entrypoint = codeset->CodeSegment().addr;
codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); codeset->memory = std::make_shared<std::vector<u8>>(std::move(code));
process = Kernel::Process::Create(std::move(codeset)); process = Core::System::GetInstance().Kernel().CreateProcess(std::move(codeset));
// Attach a resource limit to the process based on the resource limit category // Attach a resource limit to the process based on the resource limit category
process->resource_limit = process->resource_limit =
Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>( Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory(
static_cast<Kernel::ResourceLimitCategory>(
overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category)); overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category));
// Set the default CPU core for this process // Set the default CPU core for this process

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/memory_setup.h" #include "core/memory_setup.h"
@ -15,7 +16,10 @@ static Memory::PageTable* page_table = nullptr;
TestEnvironment::TestEnvironment(bool mutable_memory_) TestEnvironment::TestEnvironment(bool mutable_memory_)
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
Kernel::g_current_process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); CoreTiming::Init();
kernel = std::make_unique<Kernel::KernelSystem>(0);
Kernel::g_current_process = kernel->CreateProcess(kernel->CreateCodeSet("", 0));
page_table = &Kernel::g_current_process->vm_manager.page_table; page_table = &Kernel::g_current_process->vm_manager.page_table;
page_table->pointers.fill(nullptr); page_table->pointers.fill(nullptr);
@ -30,6 +34,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
TestEnvironment::~TestEnvironment() { TestEnvironment::~TestEnvironment() {
Memory::UnmapRegion(*page_table, 0x80000000, 0x80000000); Memory::UnmapRegion(*page_table, 0x80000000, 0x80000000);
Memory::UnmapRegion(*page_table, 0x00000000, 0x80000000); Memory::UnmapRegion(*page_table, 0x00000000, 0x80000000);
CoreTiming::Shutdown();
} }
void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) { void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) {

View file

@ -5,8 +5,8 @@
#include <tuple> #include <tuple>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
#include "core/mmio.h" #include "core/mmio.h"
namespace ArmTests { namespace ArmTests {
@ -79,6 +79,8 @@ private:
bool mutable_memory; bool mutable_memory;
std::shared_ptr<TestMemory> test_memory; std::shared_ptr<TestMemory> test_memory;
std::vector<WriteRecord> write_records; std::vector<WriteRecord> write_records;
std::unique_ptr<Kernel::KernelSystem> kernel;
}; };
} // namespace ArmTests } // namespace ArmTests

View file

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
#include "core/core_timing.h"
#include "core/hle/ipc.h" #include "core/hle/ipc.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
@ -14,15 +15,17 @@
namespace Kernel { namespace Kernel {
static SharedPtr<Object> MakeObject() { static SharedPtr<Object> MakeObject(Kernel::KernelSystem& kernel) {
return Event::Create(ResetType::OneShot); return kernel.CreateEvent(ResetType::OneShot);
} }
TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") {
auto session = std::get<SharedPtr<ServerSession>>(ServerSession::CreateSessionPair()); CoreTiming::Init();
Kernel::KernelSystem kernel(0);
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
HLERequestContext context(std::move(session)); HLERequestContext context(std::move(session));
auto process = Process::Create(CodeSet::Create("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
HandleTable handle_table; HandleTable handle_table;
SECTION("works with empty cmdbuf") { SECTION("works with empty cmdbuf") {
@ -52,7 +55,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
} }
SECTION("translates move handles") { SECTION("translates move handles") {
auto a = MakeObject(); auto a = MakeObject(kernel);
Handle a_handle = handle_table.Create(a).Unwrap(); Handle a_handle = handle_table.Create(a).Unwrap();
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 0, 2), IPC::MakeHeader(0, 0, 2),
@ -68,7 +71,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
} }
SECTION("translates copy handles") { SECTION("translates copy handles") {
auto a = MakeObject(); auto a = MakeObject(kernel);
Handle a_handle = handle_table.Create(a).Unwrap(); Handle a_handle = handle_table.Create(a).Unwrap();
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 0, 2), IPC::MakeHeader(0, 0, 2),
@ -84,9 +87,9 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
} }
SECTION("translates multi-handle descriptors") { SECTION("translates multi-handle descriptors") {
auto a = MakeObject(); auto a = MakeObject(kernel);
auto b = MakeObject(); auto b = MakeObject(kernel);
auto c = MakeObject(); auto c = MakeObject(kernel);
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 0, 5), IPC::MoveHandleDesc(2), IPC::MakeHeader(0, 0, 5), IPC::MoveHandleDesc(2),
handle_table.Create(a).Unwrap(), handle_table.Create(b).Unwrap(), handle_table.Create(a).Unwrap(), handle_table.Create(b).Unwrap(),
@ -190,7 +193,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
buffer_mapped->size(), MemoryState::Private); buffer_mapped->size(), MemoryState::Private);
REQUIRE(result.Code() == RESULT_SUCCESS); REQUIRE(result.Code() == RESULT_SUCCESS);
auto a = MakeObject(); auto a = MakeObject(kernel);
const u32_le input[]{ const u32_le input[]{
IPC::MakeHeader(0, 2, 8), IPC::MakeHeader(0, 2, 8),
0x12345678, 0x12345678,
@ -222,13 +225,17 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
REQUIRE(process->vm_manager.UnmapRange(target_address_mapped, buffer_mapped->size()) == REQUIRE(process->vm_manager.UnmapRange(target_address_mapped, buffer_mapped->size()) ==
RESULT_SUCCESS); RESULT_SUCCESS);
} }
CoreTiming::Shutdown();
} }
TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
auto session = std::get<SharedPtr<ServerSession>>(ServerSession::CreateSessionPair()); CoreTiming::Init();
Kernel::KernelSystem kernel(0);
auto session = std::get<SharedPtr<ServerSession>>(kernel.CreateSessionPair());
HLERequestContext context(std::move(session)); HLERequestContext context(std::move(session));
auto process = Process::Create(CodeSet::Create("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
HandleTable handle_table; HandleTable handle_table;
auto* input = context.CommandBuffer(); auto* input = context.CommandBuffer();
u32_le output[IPC::COMMAND_BUFFER_LENGTH]; u32_le output[IPC::COMMAND_BUFFER_LENGTH];
@ -255,8 +262,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
} }
SECTION("translates move/copy handles") { SECTION("translates move/copy handles") {
auto a = MakeObject(); auto a = MakeObject(kernel);
auto b = MakeObject(); auto b = MakeObject(kernel);
input[0] = IPC::MakeHeader(0, 0, 4); input[0] = IPC::MakeHeader(0, 0, 4);
input[1] = IPC::MoveHandleDesc(1); input[1] = IPC::MoveHandleDesc(1);
input[2] = context.AddOutgoingHandle(a); input[2] = context.AddOutgoingHandle(a);
@ -281,9 +288,9 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
} }
SECTION("translates multi-handle descriptors") { SECTION("translates multi-handle descriptors") {
auto a = MakeObject(); auto a = MakeObject(kernel);
auto b = MakeObject(); auto b = MakeObject(kernel);
auto c = MakeObject(); auto c = MakeObject(kernel);
input[0] = IPC::MakeHeader(0, 0, 5); input[0] = IPC::MakeHeader(0, 0, 5);
input[1] = IPC::MoveHandleDesc(2); input[1] = IPC::MoveHandleDesc(2);
input[2] = context.AddOutgoingHandle(a); input[2] = context.AddOutgoingHandle(a);
@ -361,6 +368,8 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) == REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) ==
RESULT_SUCCESS); RESULT_SUCCESS);
} }
CoreTiming::Shutdown();
} }
} // namespace Kernel } // namespace Kernel

View file

@ -3,14 +3,17 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
#include "core/core_timing.h"
#include "core/hle/kernel/memory.h" #include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/hle/shared_page.h" #include "core/hle/shared_page.h"
#include "core/memory.h" #include "core/memory.h"
TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") { TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
CoreTiming::Init();
Kernel::KernelSystem kernel(0);
SECTION("these regions should not be mapped on an empty process") { SECTION("these regions should not be mapped on an empty process") {
auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::HEAP_VADDR) == false); CHECK(Memory::IsValidVirtualAddress(*process, Memory::HEAP_VADDR) == false);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::LINEAR_HEAP_VADDR) == false); CHECK(Memory::IsValidVirtualAddress(*process, Memory::LINEAR_HEAP_VADDR) == false);
@ -21,14 +24,14 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
} }
SECTION("CONFIG_MEMORY_VADDR and SHARED_PAGE_VADDR should be valid after mapping them") { SECTION("CONFIG_MEMORY_VADDR and SHARED_PAGE_VADDR should be valid after mapping them") {
auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
Kernel::MapSharedPages(process->vm_manager); Kernel::MapSharedPages(process->vm_manager);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true); CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true); CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true);
} }
SECTION("special regions should be valid after mapping them") { SECTION("special regions should be valid after mapping them") {
auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
SECTION("VRAM") { SECTION("VRAM") {
Kernel::HandleSpecialMapping(process->vm_manager, Kernel::HandleSpecialMapping(process->vm_manager,
{Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false}); {Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false});
@ -43,9 +46,11 @@ TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
} }
SECTION("Unmapping a VAddr should make it invalid") { SECTION("Unmapping a VAddr should make it invalid") {
auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0)); auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
Kernel::MapSharedPages(process->vm_manager); Kernel::MapSharedPages(process->vm_manager);
process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE); process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false);
} }
CoreTiming::Shutdown();
} }