Merge pull request #4341 from wwylele/kernel-global

Kernel: make a kernel instance and remove object ID counter from global state
master
Weiyi Wang 2018-10-21 18:53:36 +07: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

@ -191,13 +191,13 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) {
rpc_server = std::make_unique<RPC::RPCServer>();
#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>();
archive_manager = std::make_unique<Service::FS::ArchiveManager>();
archive_manager = std::make_unique<Service::FS::ArchiveManager>(*this);
HW::Init();
Kernel::Init(system_mode);
Service::Init(*this, service_manager);
kernel = std::make_unique<Kernel::KernelSystem>(system_mode);
Service::Init(*this);
GDBStub::Init();
ResultStatus result = VideoCore::Init(emu_window);
@ -230,6 +230,14 @@ const Service::FS::ArchiveManager& System::ArchiveManager() const {
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) {
registered_swkbd = std::move(swkbd);
}
@ -248,7 +256,7 @@ void System::Shutdown() {
GDBStub::Shutdown();
VideoCore::Shutdown();
Service::Shutdown();
Kernel::Shutdown();
kernel.reset();
HW::Shutdown();
telemetry_session.reset();
#ifdef ENABLE_SCRIPTING

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

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/erreula.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.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// 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,
"ErrEula Memory");

@ -7,6 +7,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/mii_selector.h"
#include "core/hle/kernel/kernel.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.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// 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,
"MiiSelector Memory");

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/mint.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.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// 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,
"Mint Memory");

@ -8,6 +8,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/applets/swkbd.h"
#include "core/hle/kernel/kernel.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.
heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
// 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,
"SoftwareKeyboard Memory");

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

@ -31,14 +31,6 @@ enum class ArbitrationType : u32 {
class AddressArbiter final : public Object {
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 {
return "Arbiter";
}
@ -57,7 +49,7 @@ public:
s32 value, u64 nanoseconds);
private:
AddressArbiter();
explicit AddressArbiter(KernelSystem& kernel);
~AddressArbiter() override;
/// 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.
std::vector<SharedPtr<Thread>> waiting_threads;
friend class KernelSystem;
};
} // namespace Kernel

@ -13,7 +13,7 @@
namespace Kernel {
ClientPort::ClientPort() = default;
ClientPort::ClientPort(KernelSystem& kernel) : kernel(kernel), Object(kernel) {}
ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
@ -26,7 +26,7 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
active_sessions++;
// 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)
server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));

@ -48,13 +48,16 @@ public:
void ConnectionClosed();
private:
ClientPort();
explicit ClientPort(KernelSystem& kernel);
~ClientPort() override;
KernelSystem& kernel;
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
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
std::string name; ///< Name of client port (optional)
friend class KernelSystem;
};
} // namespace Kernel

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

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

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

@ -12,13 +12,6 @@ namespace Kernel {
class Event final : public WaitObject {
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 {
return "Event";
}
@ -47,13 +40,15 @@ public:
void Clear();
private:
Event();
explicit Event(KernelSystem& kernel);
~Event() override;
ResetType reset_type; ///< Current ResetType
bool signaled; ///< Whether the event has already been signaled
std::string name; ///< Name of event (optional)
friend class KernelSystem;
};
} // namespace Kernel

@ -6,6 +6,7 @@
#include <vector>
#include "common/assert.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
@ -55,7 +56,8 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
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->wait_objects = {event};
event->AddWaitingThread(thread);

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

@ -4,14 +4,185 @@
#pragma once
#include <atomic>
#include <memory>
#include <string>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h"
#include "core/hle/result.h"
namespace Kernel {
/// Initialize the kernel with the specified system mode.
void Init(u32 system_mode);
class AddressArbiter;
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
void Shutdown();
enum class ResetType {
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

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

@ -16,14 +16,6 @@ class Thread;
class Mutex final : public WaitObject {
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 {
return "Mutex";
}
@ -61,8 +53,10 @@ public:
ResultCode Release(Thread* thread);
private:
Mutex();
explicit Mutex(KernelSystem& kernel);
~Mutex() override;
friend class KernelSystem;
};
/**

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

@ -6,13 +6,13 @@
#include <atomic>
#include <string>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel {
class KernelSystem;
using Handle = u32;
enum class HandleType : u32 {
@ -37,14 +37,9 @@ enum {
DEFAULT_STACK_SIZE = 0x4000,
};
enum class ResetType {
OneShot,
Sticky,
Pulse,
};
class Object : NonCopyable {
public:
explicit Object(KernelSystem& kernel);
virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only.
@ -66,15 +61,12 @@ public:
*/
bool IsWaitable() const;
public:
static std::atomic<u32> next_object_id;
private:
friend void intrusive_ptr_add_ref(Object*);
friend void intrusive_ptr_release(Object*);
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
@ -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.
* @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.

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

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

@ -9,19 +9,17 @@
namespace Kernel {
static SharedPtr<ResourceLimit> resource_limits[4];
ResourceLimit::ResourceLimit() {}
ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
ResourceLimit::~ResourceLimit() {}
SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
SharedPtr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));
resource_limit->name = std::move(name);
return resource_limit;
}
SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
SharedPtr<ResourceLimit> ResourceLimitList::GetForCategory(ResourceLimitCategory category) {
switch (category) {
case ResourceLimitCategory::APPLICATION:
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 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_commit = 0x4000000;
resource_limit->max_threads = 0x20;
@ -107,7 +105,7 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = 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_commit = 0x5E00000;
resource_limit->max_threads = 0x1D;
@ -121,7 +119,7 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_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_commit = 0x600000;
resource_limit->max_threads = 0xE;
@ -135,7 +133,7 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = 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_commit = 0x2180000;
resource_limit->max_threads = 0xE1;
@ -149,6 +147,6 @@ void ResourceLimitsInit() {
resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
}
void ResourceLimitsShutdown() {}
ResourceLimitList::~ResourceLimitList() = default;
} // namespace Kernel

@ -4,6 +4,7 @@
#pragma once
#include <array>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
@ -34,14 +35,7 @@ public:
/**
* Creates a resource limit object.
*/
static SharedPtr<ResourceLimit> Create(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);
static SharedPtr<ResourceLimit> Create(KernelSystem& kernel, std::string name = "Unknown");
std::string GetTypeName() const override {
return "ResourceLimit";
@ -113,14 +107,24 @@ public:
s32 current_cpu_time = 0;
private:
ResourceLimit();
explicit ResourceLimit(KernelSystem& kernel);
~ResourceLimit() override;
};
/// Initializes the resource limits
void ResourceLimitsInit();
class ResourceLimitList {
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

@ -10,16 +10,16 @@
namespace Kernel {
Semaphore::Semaphore() {}
Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
Semaphore::~Semaphore() {}
ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
std::string name) {
ResultVal<SharedPtr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count, s32 max_count,
std::string name) {
if (initial_count > max_count)
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,
// and the rest is reserved for the caller thread

@ -15,16 +15,6 @@ namespace Kernel {
class Semaphore final : public WaitObject {
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 {
return "Semaphore";
}
@ -52,8 +42,10 @@ public:
ResultVal<s32> Release(s32 release_count);
private:
Semaphore();
explicit Semaphore(KernelSystem& kernel);
~Semaphore() override;
friend class KernelSystem;
};
} // namespace Kernel

@ -13,7 +13,7 @@
namespace Kernel {
ServerPort::ServerPort() {}
ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {}
ServerPort::~ServerPort() {}
ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
@ -35,11 +35,11 @@ void ServerPort::Acquire(Thread* thread) {
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) {
SharedPtr<ServerPort> server_port(new ServerPort);
SharedPtr<ClientPort> client_port(new ClientPort);
SharedPtr<ServerPort> server_port(new ServerPort(*this));
SharedPtr<ClientPort> client_port(new ClientPort(*this));
server_port->name = name + "_Server";
client_port->name = name + "_Client";

@ -20,16 +20,6 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject {
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 {
return "ServerPort";
}
@ -69,8 +59,10 @@ public:
void Acquire(Thread* thread) override;
private:
ServerPort();
explicit ServerPort(KernelSystem& kernel);
~ServerPort() override;
friend class KernelSystem;
};
} // namespace Kernel

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

@ -48,17 +48,6 @@ public:
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
* instead of the regular IPC machinery. (The regular IPC machinery is currently not
@ -95,16 +84,20 @@ public:
SharedPtr<Thread> currently_handling;
private:
ServerSession();
explicit ServerSession(KernelSystem& kernel);
~ServerSession() override;
/**
* 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.
* @param kernel The kernel instance to create the server session on
* @param name Optional name of the 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

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

@ -12,55 +12,8 @@
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 {
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 {
return "SharedMemory";
}
@ -125,8 +78,10 @@ public:
std::string name;
private:
SharedMemory();
explicit SharedMemory(KernelSystem& kernel);
~SharedMemory() override;
friend class KernelSystem;
};
} // namespace Kernel

@ -615,7 +615,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
/// Create an address arbiter (to allocate access to shared resources)
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)));
LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
return RESULT_SUCCESS;
@ -761,9 +761,9 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
break;
}
CASCADE_RESULT(SharedPtr<Thread> thread,
Thread::Create(name, entry_point, priority, arg, processor_id, stack_top,
g_current_process));
CASCADE_RESULT(SharedPtr<Thread> thread, Core::System::GetInstance().Kernel().CreateThread(
name, entry_point, priority, arg, processor_id,
stack_top, g_current_process));
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
FPSCR_ROUND_TOZERO); // 0x03C00000
@ -828,7 +828,7 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
/// Create a mutex
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));
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
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));
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
static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
SharedPtr<Event> evt = Event::Create(static_cast<ResetType>(reset_type),
fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
SharedPtr<Event> evt = Core::System::GetInstance().Kernel().CreateEvent(
static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
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,
@ -985,8 +986,8 @@ static ResultCode ClearEvent(Handle handle) {
/// Creates a timer
static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type),
fmt ::format("timer-{:08x}", Core::CPU().GetReg(14)));
SharedPtr<Timer> timer = Core::System::GetInstance().Kernel().CreateTimer(
static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", Core::CPU().GetReg(14)));
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,
@ -1104,9 +1105,9 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
if (addr == 0 && g_current_process->flags.shared_device_mem)
region = g_current_process->flags.memory_region;
shared_memory =
SharedMemory::Create(g_current_process, size, static_cast<MemoryPermission>(my_permission),
static_cast<MemoryPermission>(other_permission), addr, region);
shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory(
g_current_process, size, static_cast<MemoryPermission>(my_permission),
static_cast<MemoryPermission>(other_permission), addr, region);
CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory)));
LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr);
@ -1118,7 +1119,7 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam
// TODO(Subv): Implement named ports.
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,
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
@ -1141,7 +1142,7 @@ static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_
}
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);
CASCADE_RESULT(*server_session, g_handle_table.Create(std::move(server)));

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

@ -55,21 +55,6 @@ enum class ThreadWakeupReason {
class Thread final : public WaitObject {
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 {
return name;
}
@ -225,18 +210,22 @@ public:
std::function<WakeupCallback> wakeup_callback;
private:
Thread();
explicit Thread(KernelSystem&);
~Thread() override;
friend class KernelSystem;
};
/**
* 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 priority The priority to give the main thread
* @param owner_process The parent process for 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.

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

@ -12,14 +12,6 @@ namespace Kernel {
class Timer final : public WaitObject {
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 {
return "Timer";
}
@ -68,7 +60,7 @@ public:
void Signal(s64 cycles_late);
private:
Timer();
explicit Timer(KernelSystem& kernel);
~Timer() override;
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 callback_handle;
friend class KernelSystem;
};
/// Initializes the required variables for timers

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

@ -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
// Citra will store contents out to sdmc/nand
const FileSys::Path cia_path = {};
auto file =
std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(media_type), cia_path);
auto file = std::make_shared<Service::FS::File>(
am->system, std::make_unique<CIAFile>(media_type), cia_path);
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
// contents out to sdmc/nand
const FileSys::Path cia_path = {};
auto file = std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(FS::MediaType::NAND),
cia_path);
auto file = std::make_shared<Service::FS::File>(
am->system, std::make_unique<CIAFile>(FS::MediaType::NAND), cia_path);
am->cia_installing = true;
@ -1455,16 +1455,16 @@ void Module::Interface::GetMetaDataFromCia(Kernel::HLERequestContext& ctx) {
rb.PushMappedBuffer(output_buffer);
}
Module::Module() {
Module::Module(Core::System& system) : system(system) {
ScanForAllTitles();
system_updater_mutex = Kernel::Mutex::Create(false, "AM::SystemUpdaterMutex");
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
}
Module::~Module() = default;
void InstallInterfaces(Core::System& system) {
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_NET>(am)->InstallAsService(service_manager);
std::make_shared<AM_SYS>(am)->InstallAsService(service_manager);

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

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

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

@ -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)
: ServiceFramework(name, max_session), boss(std::move(boss)) {}
Module::Module() {
Module::Module(Core::System& system) {
using namespace Kernel;
// 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) {
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_U>(boss)->InstallAsService(service_manager);
}

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

@ -1019,14 +1019,15 @@ void Module::Interface::DriverFinalize(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_CAM, "called");
}
Module::Module() {
Module::Module(Core::System& system) {
using namespace Kernel;
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 =
Event::Create(ResetType::OneShot, "CAM::buffer_error_interrupt_event");
system.Kernel().CreateEvent(ResetType::OneShot, "CAM::buffer_error_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(
"CAM::CompletionEventCallBack",
@ -1061,7 +1062,7 @@ std::shared_ptr<Module> GetModule(Core::System& system) {
void InstallInterfaces(Core::System& system) {
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_S>(cam)->InstallAsService(service_manager);

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

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

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

@ -19,10 +19,10 @@ void CSND_SND::Initialize(Kernel::HLERequestContext& ctx) {
const u32 offset3 = rp.Pop<u32>();
using Kernel::MemoryPermission;
mutex = Kernel::Mutex::Create(false, "CSND:mutex");
shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite,
MemoryPermission::ReadWrite, 0,
Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
mutex = system.Kernel().CreateMutex(false, "CSND:mutex");
shared_memory = system.Kernel().CreateSharedMemory(
nullptr, size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 0,
Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
IPC::RequestBuilder rb = rp.MakeBuilder(1, 3);
rb.Push(RESULT_SUCCESS);
@ -173,7 +173,7 @@ void CSND_SND::Reset(Kernel::HLERequestContext& ctx) {
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[] = {
// clang-format off
{0x00010140, &CSND_SND::Initialize, "Initialize"},
@ -196,7 +196,7 @@ CSND_SND::CSND_SND() : ServiceFramework("csnd:SND", 4) {
void InstallInterfaces(Core::System& system) {
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

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

@ -350,7 +350,7 @@ bool DSP_DSP::HasTooManyEventsRegistered() const {
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[] = {
// clang-format off
{0x00010040, &DSP_DSP::RecvData, "RecvData"},
@ -391,7 +391,8 @@ DSP_DSP::DSP_DSP() : ServiceFramework("dsp::DSP", DefaultMaxSessions) {
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() {
@ -401,7 +402,7 @@ DSP_DSP::~DSP_DSP() {
void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager();
auto dsp = std::make_shared<DSP_DSP>();
auto dsp = std::make_shared<DSP_DSP>(system);
dsp->InstallAsService(service_manager);
Core::DSP().SetServiceToInterrupt(std::move(dsp));
}

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

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

@ -87,7 +87,7 @@ ResultVal<std::shared_ptr<File>> ArchiveManager::OpenFileFromArchive(ArchiveHand
if (backend.Failed())
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));
}
@ -348,7 +348,7 @@ void ArchiveManager::RegisterSelfNCCH(Loader::AppLoader& app_loader) {
factory->Register(app_loader);
}
ArchiveManager::ArchiveManager() {
ArchiveManager::ArchiveManager(Core::System& system) : system(system) {
RegisterArchiveTypes();
}

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

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

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

@ -286,7 +286,7 @@ void FS_USER::OpenDirectory(Kernel::HLERequestContext& ctx) {
rb.Push(dir_res.Code());
if (dir_res.Succeeded()) {
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));
rb.PushMoveObjects(std::get<SharedPtr<ClientSession>>(sessions));
} else {
@ -741,7 +741,8 @@ void FS_USER::GetSaveDataSecureValue(Kernel::HLERequestContext& ctx) {
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[] = {
{0x000100C6, nullptr, "Dummy1"},
{0x040100C4, nullptr, "Control"},
@ -860,6 +861,6 @@ FS_USER::FS_USER(ArchiveManager& archives) : ServiceFramework("fs:USER", 30), ar
void InstallInterfaces(Core::System& system) {
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

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

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

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

@ -16,10 +16,10 @@ void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager();
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);
auto ir_rst = std::make_shared<IR_RST>();
auto ir_rst = std::make_shared<IR_RST>(system);
ir_rst->InstallAsService(service_manager);
}

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

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

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

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

@ -29,6 +29,11 @@ enum class SampleRate : u8 {
};
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) {
IPC::RequestParser rp{ctx, 0x01, 1, 2};
const u32 size = rp.Pop<u32>();
@ -187,8 +192,7 @@ struct MIC_U::Impl {
}
u32 client_version = 0;
Kernel::SharedPtr<Kernel::Event> buffer_full_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event");
Kernel::SharedPtr<Kernel::Event> buffer_full_event;
Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
u8 mic_gain = 0;
bool mic_power = false;
@ -266,7 +270,8 @@ void MIC_U::SetClientVersion(Kernel::HLERequestContext& 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[] = {
{0x00010042, &MIC_U::MapSharedMem, "MapSharedMem"},
{0x00020000, &MIC_U::UnmapSharedMem, "UnmapSharedMem"},
@ -293,7 +298,7 @@ MIC_U::~MIC_U() = default;
void InstallInterfaces(Core::System& system) {
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

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

@ -140,18 +140,18 @@ Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32
Module::Interface::~Interface() = default;
Module::Module() {
Module::Module(Core::System& system) {
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 =
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;
void InstallInterfaces(Core::System& system) {
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_U>(nfc)->InstallAsService(service_manager);
}

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

@ -14,7 +14,7 @@ void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager();
std::make_shared<NIM_AOC>()->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

@ -2,13 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/nim/nim_u.h"
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[] = {
{0x00010000, nullptr, "StartSysUpdate"},
{0x00020000, nullptr, "GetUpdateDownloadProgress"},
@ -20,7 +21,7 @@ NIM_U::NIM_U() : ServiceFramework("nim:u", 2) {
};
RegisterHandlers(functions);
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;

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

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

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

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

@ -20,6 +20,7 @@ class System;
}
namespace Kernel {
class KernelSystem;
class ClientPort;
class ServerPort;
class ServerSession;
@ -59,7 +60,7 @@ public:
/// Creates a port pair and registers this service with the given ServiceManager.
void InstallAsService(SM::ServiceManager& service_manager);
/// 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;
@ -184,7 +185,7 @@ private:
};
/// Initialize ServiceManager
void Init(Core::System& system, std::shared_ptr<SM::ServiceManager>& sm);
void Init(Core::System& system);
/// Shutdown ServiceManager
void Shutdown();

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

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

@ -5,6 +5,7 @@
#include <tuple>
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc.h"
#include "core/hle/ipc_helpers.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);
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);
rb.Push(RESULT_SUCCESS);
@ -103,7 +104,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
Kernel::HLERequestContext& ctx,
Kernel::ThreadWakeupReason reason) {
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();
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 (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) {
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()));
auto port = service_manager->RegisterService(name, max_sessions);
auto port = system.ServiceManager().RegisterService(name, max_sessions);
if (port.Failed()) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@ -243,8 +244,7 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) {
rb.PushMoveObjects(port.Unwrap());
}
SRV::SRV(std::shared_ptr<ServiceManager> service_manager)
: ServiceFramework("srv:", 4), service_manager(std::move(service_manager)) {
SRV::SRV(Core::System& system) : ServiceFramework("srv:", 4), system(system) {
static const FunctionInfo functions[] = {
{0x00010002, &SRV::RegisterClient, "RegisterClient"},
{0x00020000, &SRV::EnableNotification, "EnableNotification"},

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

@ -632,7 +632,7 @@ void Y2R_U::GetPackageParameter(Kernel::HLERequestContext& ctx) {
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[] = {
{0x00010040, &Y2R_U::SetInputFormat, "SetInputFormat"},
{0x00020000, &Y2R_U::GetInputFormat, "GetInputFormat"},
@ -682,14 +682,14 @@ Y2R_U::Y2R_U() : ServiceFramework("y2r:u", 1) {
};
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;
void InstallInterfaces(Core::System& system) {
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

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

@ -217,7 +217,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
}
// 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().addr = loadinfo.seg_addrs[0];
@ -267,13 +267,13 @@ ResultStatus AppLoader_THREEDSX::Load(Kernel::SharedPtr<Kernel::Process>& proces
return ResultStatus::Error;
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->address_mappings = default_address_mappings;
// Attach the default resource limit (APPLICATION) to the process
process->resource_limit =
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory(
Kernel::ResourceLimitCategory::APPLICATION);
process->Run(48, Kernel::DEFAULT_STACK_SIZE);

@ -8,6 +8,7 @@
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.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::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) {
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);
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->address_mappings = default_address_mappings;
// Attach the default resource limit (APPLICATION) to the process
process->resource_limit =
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->resource_limit = Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory(
Kernel::ResourceLimitCategory::APPLICATION);
process->Run(48, Kernel::DEFAULT_STACK_SIZE);

@ -75,7 +75,8 @@ ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& proces
std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
(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().addr = overlay_ncch->exheader_header.codeset_info.text.address;
@ -103,12 +104,13 @@ ResultStatus AppLoader_NCCH::LoadExec(Kernel::SharedPtr<Kernel::Process>& proces
codeset->entrypoint = codeset->CodeSegment().addr;
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
process->resource_limit =
Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>(
overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category));
Core::System::GetInstance().Kernel().ResourceLimit().GetForCategory(
static_cast<Kernel::ResourceLimitCategory>(
overlay_ncch->exheader_header.arm11_system_local_caps.resource_limit_category));
// Set the default CPU core for this process
process->ideal_processor =

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/process.h"
#include "core/memory.h"
#include "core/memory_setup.h"
@ -15,7 +16,10 @@ static Memory::PageTable* page_table = nullptr;
TestEnvironment::TestEnvironment(bool mutable_memory_)
: 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->pointers.fill(nullptr);
@ -30,6 +34,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
TestEnvironment::~TestEnvironment() {
Memory::UnmapRegion(*page_table, 0x80000000, 0x80000000);
Memory::UnmapRegion(*page_table, 0x00000000, 0x80000000);
CoreTiming::Shutdown();
}
void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) {

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

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

@ -3,14 +3,17 @@
// Refer to the license.txt file included.
#include <catch2/catch.hpp>
#include "core/core_timing.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h"
#include "core/hle/shared_page.h"
#include "core/memory.h"
TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
CoreTiming::Init();
Kernel::KernelSystem kernel(0);
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::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") {
auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0));
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
Kernel::MapSharedPages(process->vm_manager);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true);
}
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") {
Kernel::HandleSpecialMapping(process->vm_manager,
{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") {
auto process = Kernel::Process::Create(Kernel::CodeSet::Create("", 0));
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
Kernel::MapSharedPages(process->vm_manager);
process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE);
CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false);
}
CoreTiming::Shutdown();
}