Kernel: replace boost::intrusive_ptr with std::shared_ptr

This commit is contained in:
Weiyi Wang 2019-03-23 16:04:19 -04:00
parent c1de8acfe5
commit 5f11c5f733
96 changed files with 522 additions and 538 deletions

View file

@ -16,7 +16,7 @@
namespace Kernel {
void AddressArbiter::WaitThread(SharedPtr<Thread> thread, VAddr wait_address) {
void AddressArbiter::WaitThread(std::shared_ptr<Thread> thread, VAddr wait_address) {
thread->wait_address = wait_address;
thread->status = ThreadStatus::WaitArb;
waiting_threads.emplace_back(std::move(thread));
@ -38,7 +38,7 @@ void AddressArbiter::ResumeAllThreads(VAddr address) {
waiting_threads.erase(itr, waiting_threads.end());
}
SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
std::shared_ptr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
// Determine which threads are waiting on this address, those should be considered for wakeup.
auto matches_start = std::stable_partition(
waiting_threads.begin(), waiting_threads.end(), [address](const auto& thread) {
@ -68,19 +68,19 @@ SharedPtr<Thread> AddressArbiter::ResumeHighestPriorityThread(VAddr address) {
AddressArbiter::AddressArbiter(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
AddressArbiter::~AddressArbiter() {}
SharedPtr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter(*this));
std::shared_ptr<AddressArbiter> KernelSystem::CreateAddressArbiter(std::string name) {
auto address_arbiter{std::make_shared<AddressArbiter>(*this)};
address_arbiter->name = std::move(name);
return address_arbiter;
}
ResultCode AddressArbiter::ArbitrateAddress(SharedPtr<Thread> thread, ArbitrationType type,
ResultCode AddressArbiter::ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type,
VAddr address, s32 value, u64 nanoseconds) {
auto timeout_callback = [this](ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object) {
auto timeout_callback = [this](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object) {
ASSERT(reason == ThreadWakeupReason::Timeout);
// Remove the newly-awakened thread from the Arbiter's waiting list.
waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread),

View file

@ -31,6 +31,9 @@ enum class ArbitrationType : u32 {
class AddressArbiter final : public Object {
public:
explicit AddressArbiter(KernelSystem& kernel);
~AddressArbiter() override;
std::string GetTypeName() const override {
return "Arbiter";
}
@ -45,29 +48,24 @@ public:
std::string name; ///< Name of address arbiter object (optional)
ResultCode ArbitrateAddress(SharedPtr<Thread> thread, ArbitrationType type, VAddr address,
ResultCode ArbitrateAddress(std::shared_ptr<Thread> thread, ArbitrationType type, VAddr address,
s32 value, u64 nanoseconds);
private:
explicit AddressArbiter(KernelSystem& kernel);
~AddressArbiter() override;
KernelSystem& kernel;
/// Puts the thread to wait on the specified arbitration address under this address arbiter.
void WaitThread(SharedPtr<Thread> thread, VAddr wait_address);
void WaitThread(std::shared_ptr<Thread> thread, VAddr wait_address);
/// Resume all threads found to be waiting on the address under this address arbiter
void ResumeAllThreads(VAddr address);
/// Resume one thread found to be waiting on the address under this address arbiter and return
/// the resumed thread.
SharedPtr<Thread> ResumeHighestPriorityThread(VAddr address);
std::shared_ptr<Thread> ResumeHighestPriorityThread(VAddr address);
/// Threads waiting for the address arbiter to be signaled.
std::vector<SharedPtr<Thread>> waiting_threads;
friend class KernelSystem;
std::vector<std::shared_ptr<Thread>> waiting_threads;
};
} // namespace Kernel

View file

@ -16,7 +16,7 @@ namespace Kernel {
ClientPort::ClientPort(KernelSystem& kernel) : kernel(kernel), Object(kernel) {}
ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
// Note: Threads do not wait for the server endpoint to call
// AcceptSession before returning from this call.
@ -26,17 +26,18 @@ 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 = kernel.CreateSessionPair(server_port->GetName(), this);
auto sessions = kernel.CreateSessionPair(server_port->GetName(), SharedFrom(this));
if (server_port->hle_handler)
server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
server_port->hle_handler->ClientConnected(
std::get<std::shared_ptr<ServerSession>>(sessions));
else
server_port->pending_sessions.push_back(std::get<SharedPtr<ServerSession>>(sessions));
server_port->pending_sessions.push_back(std::get<std::shared_ptr<ServerSession>>(sessions));
// Wake the threads waiting on the ServerPort
server_port->WakeupAllWaitingThreads();
return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
return MakeResult(std::get<std::shared_ptr<ClientSession>>(sessions));
}
void ClientPort::ConnectionClosed() {

View file

@ -16,6 +16,9 @@ class ClientSession;
class ClientPort final : public Object {
public:
explicit ClientPort(KernelSystem& kernel);
~ClientPort() override;
friend class ServerPort;
std::string GetTypeName() const override {
return "ClientPort";
@ -29,7 +32,7 @@ public:
return HANDLE_TYPE;
}
SharedPtr<ServerPort> GetServerPort() const {
std::shared_ptr<ServerPort> GetServerPort() const {
return server_port;
}
@ -39,7 +42,7 @@ public:
* waiting on it to awake.
* @returns ClientSession The client endpoint of the created Session pair, or error code.
*/
ResultVal<SharedPtr<ClientSession>> Connect();
ResultVal<std::shared_ptr<ClientSession>> Connect();
/**
* Signifies that a previously active connection has been closed,
@ -48,11 +51,8 @@ public:
void ConnectionClosed();
private:
explicit ClientPort(KernelSystem& kernel);
~ClientPort() override;
KernelSystem& kernel;
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
std::shared_ptr<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)

View file

@ -20,7 +20,7 @@ ClientSession::~ClientSession() {
// Local references to ServerSession and SessionRequestHandler are necessary to guarantee they
// will be kept alive until after ClientDisconnected() returns.
SharedPtr<ServerSession> server = parent->server;
std::shared_ptr<ServerSession> server = SharedFrom(parent->server);
if (server) {
std::shared_ptr<SessionRequestHandler> hle_handler = server->hle_handler;
if (hle_handler)
@ -42,9 +42,9 @@ ClientSession::~ClientSession() {
}
}
ResultCode ClientSession::SendSyncRequest(SharedPtr<Thread> thread) {
ResultCode ClientSession::SendSyncRequest(std::shared_ptr<Thread> thread) {
// Keep ServerSession alive until we're done working with it.
SharedPtr<ServerSession> server = parent->server;
std::shared_ptr<ServerSession> server = SharedFrom(parent->server);
if (server == nullptr)
return ERR_SESSION_CLOSED_BY_REMOTE;

View file

@ -17,6 +17,9 @@ class Thread;
class ClientSession final : public Object {
public:
explicit ClientSession(KernelSystem& kernel);
~ClientSession() override;
friend class KernelSystem;
std::string GetTypeName() const override {
@ -37,16 +40,12 @@ public:
* @param thread Thread that initiated the request.
* @return ResultCode of the operation.
*/
ResultCode SendSyncRequest(SharedPtr<Thread> thread);
ResultCode SendSyncRequest(std::shared_ptr<Thread> thread);
std::string name; ///< Name of client port (optional)
/// The parent session, which links to the server endpoint.
std::shared_ptr<Session> parent;
private:
explicit ClientSession(KernelSystem& kernel);
~ClientSession() override;
};
} // namespace Kernel

View file

@ -15,8 +15,8 @@ namespace Kernel {
Event::Event(KernelSystem& kernel) : WaitObject(kernel) {}
Event::~Event() {}
SharedPtr<Event> KernelSystem::CreateEvent(ResetType reset_type, std::string name) {
SharedPtr<Event> evt(new Event(*this));
std::shared_ptr<Event> KernelSystem::CreateEvent(ResetType reset_type, std::string name) {
auto evt{std::make_shared<Event>(*this)};
evt->signaled = false;
evt->reset_type = reset_type;

View file

@ -12,6 +12,9 @@ namespace Kernel {
class Event final : public WaitObject {
public:
explicit Event(KernelSystem& kernel);
~Event() override;
std::string GetTypeName() const override {
return "Event";
}
@ -40,9 +43,6 @@ public:
void Clear();
private:
explicit Event(KernelSystem& kernel);
~Event() override;
ResetType reset_type; ///< Current ResetType
bool signaled; ///< Whether the event has already been signaled

View file

@ -28,7 +28,7 @@ HandleTable::HandleTable(KernelSystem& kernel) : kernel(kernel) {
HandleTable::~HandleTable() = default;
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
ResultVal<Handle> HandleTable::Create(std::shared_ptr<Object> obj) {
DEBUG_ASSERT(obj != nullptr);
u16 slot = next_free_slot;
@ -53,7 +53,7 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
}
ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
SharedPtr<Object> object = GetGeneric(handle);
std::shared_ptr<Object> object = GetGeneric(handle);
if (object == nullptr) {
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
return ERR_INVALID_HANDLE;
@ -81,9 +81,9 @@ bool HandleTable::IsValid(Handle handle) const {
return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
}
SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
std::shared_ptr<Object> HandleTable::GetGeneric(Handle handle) const {
if (handle == CurrentThread) {
return kernel.GetThreadManager().GetCurrentThread();
return SharedFrom(kernel.GetThreadManager().GetCurrentThread());
} else if (handle == CurrentProcess) {
return kernel.GetCurrentProcess();
}

View file

@ -50,7 +50,7 @@ public:
* @return The created Handle or one of the following errors:
* - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
*/
ResultVal<Handle> Create(SharedPtr<Object> obj);
ResultVal<Handle> Create(std::shared_ptr<Object> obj);
/**
* Returns a new handle that points to the same object as the passed in handle.
@ -74,7 +74,7 @@ public:
* Looks up a handle.
* @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
*/
SharedPtr<Object> GetGeneric(Handle handle) const;
std::shared_ptr<Object> GetGeneric(Handle handle) const;
/**
* Looks up a handle while verifying its type.
@ -82,7 +82,7 @@ public:
* type differs from the requested one.
*/
template <class T>
SharedPtr<T> Get(Handle handle) const {
std::shared_ptr<T> Get(Handle handle) const {
return DynamicObjectCast<T>(GetGeneric(handle));
}
@ -97,7 +97,7 @@ private:
static const std::size_t MAX_COUNT = 4096;
/// Stores the Object referenced by the handle or null if the slot is empty.
std::array<SharedPtr<Object>, MAX_COUNT> objects;
std::array<std::shared_ptr<Object>, MAX_COUNT> objects;
/**
* The value of `next_generation` when the handle was created, used to check for validity. For

View file

@ -15,16 +15,16 @@
namespace Kernel {
SessionRequestHandler::SessionInfo::SessionInfo(SharedPtr<ServerSession> session,
SessionRequestHandler::SessionInfo::SessionInfo(std::shared_ptr<ServerSession> session,
std::unique_ptr<SessionDataBase> data)
: session(std::move(session)), data(std::move(data)) {}
void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) {
void SessionRequestHandler::ClientConnected(std::shared_ptr<ServerSession> server_session) {
server_session->SetHleHandler(shared_from_this());
connected_sessions.emplace_back(std::move(server_session), MakeSessionData());
}
void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_session) {
void SessionRequestHandler::ClientDisconnected(std::shared_ptr<ServerSession> server_session) {
server_session->SetHleHandler(nullptr);
connected_sessions.erase(
std::remove_if(connected_sessions.begin(), connected_sessions.end(),
@ -32,14 +32,14 @@ void SessionRequestHandler::ClientDisconnected(SharedPtr<ServerSession> server_s
connected_sessions.end());
}
SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
const std::string& reason,
std::chrono::nanoseconds timeout,
WakeupCallback&& callback) {
std::shared_ptr<Event> HLERequestContext::SleepClientThread(std::shared_ptr<Thread> thread,
const std::string& reason,
std::chrono::nanoseconds timeout,
WakeupCallback&& callback) {
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
thread->wakeup_callback = [context = *this, callback](ThreadWakeupReason reason,
SharedPtr<Thread> thread,
SharedPtr<WaitObject> object) mutable {
thread->wakeup_callback = [context = *this,
callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object) mutable {
ASSERT(thread->status == ThreadStatus::WaitHleEvent);
callback(thread, context, reason);
@ -68,19 +68,19 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
return event;
}
HLERequestContext::HLERequestContext(KernelSystem& kernel, SharedPtr<ServerSession> session)
HLERequestContext::HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session)
: kernel(kernel), session(std::move(session)) {
cmd_buf[0] = 0;
}
HLERequestContext::~HLERequestContext() = default;
SharedPtr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const {
std::shared_ptr<Object> HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const {
ASSERT(id_from_cmdbuf < request_handles.size());
return request_handles[id_from_cmdbuf];
}
u32 HLERequestContext::AddOutgoingHandle(SharedPtr<Object> object) {
u32 HLERequestContext::AddOutgoingHandle(std::shared_ptr<Object> object) {
request_handles.push_back(std::move(object));
return static_cast<u32>(request_handles.size() - 1);
}
@ -119,7 +119,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
ASSERT(i + num_handles <= command_size); // TODO(yuriks): Return error
for (u32 j = 0; j < num_handles; ++j) {
Handle handle = src_cmdbuf[i];
SharedPtr<Object> object = nullptr;
std::shared_ptr<Object> object = nullptr;
if (handle != 0) {
object = src_process.handle_table.GetGeneric(handle);
ASSERT(object != nullptr); // TODO(yuriks): Return error
@ -185,7 +185,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
u32 num_handles = IPC::HandleNumberFromDesc(descriptor);
ASSERT(i + num_handles <= command_size);
for (u32 j = 0; j < num_handles; ++j) {
SharedPtr<Object> object = GetIncomingHandle(cmd_buf[i]);
std::shared_ptr<Object> object = GetIncomingHandle(cmd_buf[i]);
Handle handle = 0;
if (object != nullptr) {
// TODO(yuriks): Figure out the proper error handling for if this fails

View file

@ -55,14 +55,14 @@ public:
* associated ServerSession alive for the duration of the connection.
* @param server_session Owning pointer to the ServerSession associated with the connection.
*/
virtual void ClientConnected(SharedPtr<ServerSession> server_session);
virtual void ClientConnected(std::shared_ptr<ServerSession> server_session);
/**
* Signals that a client has just disconnected from this HLE handler and releases the
* associated ServerSession.
* @param server_session ServerSession associated with the connection.
*/
virtual void ClientDisconnected(SharedPtr<ServerSession> server_session);
virtual void ClientDisconnected(std::shared_ptr<ServerSession> server_session);
/// Empty placeholder structure for services with no per-session data. The session data classes
/// in each service must inherit from this.
@ -76,7 +76,7 @@ protected:
/// Returns the session data associated with the server session.
template <typename T>
T* GetSessionData(SharedPtr<ServerSession> session) {
T* GetSessionData(std::shared_ptr<ServerSession> session) {
static_assert(std::is_base_of<SessionDataBase, T>(),
"T is not a subclass of SessionDataBase");
auto itr = std::find_if(connected_sessions.begin(), connected_sessions.end(),
@ -86,9 +86,9 @@ protected:
}
struct SessionInfo {
SessionInfo(SharedPtr<ServerSession> session, std::unique_ptr<SessionDataBase> data);
SessionInfo(std::shared_ptr<ServerSession> session, std::unique_ptr<SessionDataBase> data);
SharedPtr<ServerSession> session;
std::shared_ptr<ServerSession> session;
std::unique_ptr<SessionDataBase> data;
};
/// List of sessions that are connected to this handler. A ServerSession whose server endpoint
@ -158,7 +158,7 @@ private:
*/
class HLERequestContext {
public:
HLERequestContext(KernelSystem& kernel, SharedPtr<ServerSession> session);
HLERequestContext(KernelSystem& kernel, std::shared_ptr<ServerSession> session);
~HLERequestContext();
/// Returns a pointer to the IPC command buffer for this request.
@ -170,12 +170,12 @@ public:
* Returns the session through which this request was made. This can be used as a map key to
* access per-client data on services.
*/
SharedPtr<ServerSession> Session() const {
std::shared_ptr<ServerSession> Session() const {
return session;
}
using WakeupCallback = std::function<void(SharedPtr<Thread> thread, HLERequestContext& context,
ThreadWakeupReason reason)>;
using WakeupCallback = std::function<void(
std::shared_ptr<Thread> thread, HLERequestContext& context, ThreadWakeupReason reason)>;
/**
* Puts the specified guest thread to sleep until the returned event is signaled or until the
@ -189,20 +189,22 @@ public:
* was called.
* @returns Event that when signaled will resume the thread and call the callback function.
*/
SharedPtr<Event> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason,
std::chrono::nanoseconds timeout, WakeupCallback&& callback);
std::shared_ptr<Event> SleepClientThread(std::shared_ptr<Thread> thread,
const std::string& reason,
std::chrono::nanoseconds timeout,
WakeupCallback&& callback);
/**
* Resolves a object id from the request command buffer into a pointer to an object. See the
* "HLE handle protocol" section in the class documentation for more details.
*/
SharedPtr<Object> GetIncomingHandle(u32 id_from_cmdbuf) const;
std::shared_ptr<Object> GetIncomingHandle(u32 id_from_cmdbuf) const;
/**
* Adds an outgoing object to the response, returning the id which should be used to reference
* it. See the "HLE handle protocol" section in the class documentation for more details.
*/
u32 AddOutgoingHandle(SharedPtr<Object> object);
u32 AddOutgoingHandle(std::shared_ptr<Object> object);
/**
* Discards all Objects from the context, invalidating all ids. This may be called after reading
@ -237,9 +239,9 @@ public:
private:
KernelSystem& kernel;
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
SharedPtr<ServerSession> session;
std::shared_ptr<ServerSession> session;
// TODO(yuriks): Check common usage of this and optimize size accordingly
boost::container::small_vector<SharedPtr<Object>, 8> request_handles;
boost::container::small_vector<std::shared_ptr<Object>, 8> request_handles;
// The static buffers will be created when the IPC request is translated.
std::array<std::vector<u8>, IPC::MAX_STATIC_BUFFERS> static_buffers;
// The mapped buffers will be created when the IPC request is translated

View file

@ -16,8 +16,8 @@
namespace Kernel {
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread> src_thread,
SharedPtr<Thread> dst_thread, VAddr src_address,
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<Thread> src_thread,
std::shared_ptr<Thread> dst_thread, VAddr src_address,
VAddr dst_address,
std::vector<MappedBufferContext>& mapped_buffer_context,
bool reply) {
@ -55,14 +55,14 @@ ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread
for (u32 j = 0; j < num_handles; ++j) {
Handle handle = cmd_buf[i];
SharedPtr<Object> object = nullptr;
std::shared_ptr<Object> object = nullptr;
// Perform pseudo-handle detection here because by the time this function is called,
// the current thread and process are no longer the ones which created this IPC
// request, but the ones that are handling it.
if (handle == CurrentThread) {
object = src_thread;
} else if (handle == CurrentProcess) {
object = src_process;
object = SharedFrom(src_process);
} else if (handle != 0) {
object = src_process->handle_table.GetGeneric(handle);
if (descriptor == IPC::DescriptorType::MoveHandle) {

View file

@ -27,8 +27,8 @@ struct MappedBufferContext {
};
/// Performs IPC command buffer translation from one process to another.
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, SharedPtr<Thread> src_thread,
SharedPtr<Thread> dst_thread, VAddr src_address,
ResultCode TranslateCommandBuffer(Memory::MemorySystem& memory, std::shared_ptr<Thread> src_thread,
std::shared_ptr<Thread> dst_thread, VAddr src_address,
VAddr dst_address,
std::vector<MappedBufferContext>& mapped_buffer_context,
bool reply);

View file

@ -42,11 +42,11 @@ u32 KernelSystem::GenerateObjectID() {
return next_object_id++;
}
SharedPtr<Process> KernelSystem::GetCurrentProcess() const {
std::shared_ptr<Process> KernelSystem::GetCurrentProcess() const {
return current_process;
}
void KernelSystem::SetCurrentProcess(SharedPtr<Process> process) {
void KernelSystem::SetCurrentProcess(std::shared_ptr<Process> process) {
current_process = std::move(process);
}
@ -74,7 +74,7 @@ const SharedPage::Handler& KernelSystem::GetSharedPageHandler() const {
return *shared_page_handler;
}
void KernelSystem::AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
void KernelSystem::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
named_ports.emplace(std::move(name), std::move(port));
}

View file

@ -78,9 +78,6 @@ enum class MemoryRegion : u16 {
BASE = 3,
};
template <typename T>
using SharedPtr = boost::intrusive_ptr<T>;
class KernelSystem {
public:
explicit KernelSystem(Memory::MemorySystem& memory, Core::Timing& timing,
@ -93,14 +90,14 @@ public:
* @param name Optional name used for debugging.
* @returns The created AddressArbiter.
*/
SharedPtr<AddressArbiter> CreateAddressArbiter(std::string name = "Unknown");
std::shared_ptr<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");
std::shared_ptr<Event> CreateEvent(ResetType reset_type, std::string name = "Unknown");
/**
* Creates a mutex.
@ -108,11 +105,11 @@ public:
* @param name Optional name of mutex
* @return Pointer to new Mutex object
*/
SharedPtr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown");
std::shared_ptr<Mutex> CreateMutex(bool initial_locked, std::string name = "Unknown");
SharedPtr<CodeSet> CreateCodeSet(std::string name, u64 program_id);
std::shared_ptr<CodeSet> CreateCodeSet(std::string name, u64 program_id);
SharedPtr<Process> CreateProcess(SharedPtr<CodeSet> code_set);
std::shared_ptr<Process> CreateProcess(std::shared_ptr<CodeSet> code_set);
/**
* Creates and returns a new thread. The new thread is immediately scheduled
@ -125,9 +122,9 @@ public:
* @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,
Process& owner_process);
ResultVal<std::shared_ptr<Thread>> CreateThread(std::string name, VAddr entry_point,
u32 priority, u32 arg, s32 processor_id,
VAddr stack_top, Process& owner_process);
/**
* Creates a semaphore.
@ -136,8 +133,8 @@ public:
* @param name Optional name of semaphore
* @return The created semaphore
*/
ResultVal<SharedPtr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count,
std::string name = "Unknown");
ResultVal<std::shared_ptr<Semaphore>> CreateSemaphore(s32 initial_count, s32 max_count,
std::string name = "Unknown");
/**
* Creates a timer
@ -145,7 +142,7 @@ public:
* @param name Optional name of timer
* @return The created Timer
*/
SharedPtr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
std::shared_ptr<Timer> CreateTimer(ResetType reset_type, std::string name = "Unknown");
/**
* Creates a pair of ServerPort and an associated ClientPort.
@ -154,7 +151,7 @@ public:
* @param name Optional name of the ports
* @return The created port tuple
*/
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
std::tuple<std::shared_ptr<ServerPort>, std::shared_ptr<ClientPort>> CreatePortPair(
u32 max_sessions, std::string name = "UnknownPort");
/**
@ -163,8 +160,8 @@ public:
* @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);
std::tuple<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>> CreateSessionPair(
const std::string& name = "Unknown", std::shared_ptr<ClientPort> client_port = nullptr);
ResourceLimitList& ResourceLimit();
const ResourceLimitList& ResourceLimit() const;
@ -181,12 +178,10 @@ public:
* linear heap.
* @param name Optional object name, used for debugging purposes.
*/
ResultVal<SharedPtr<SharedMemory>> CreateSharedMemory(Process* owner_process, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
VAddr address = 0,
MemoryRegion region = MemoryRegion::BASE,
std::string name = "Unknown");
ResultVal<std::shared_ptr<SharedMemory>> CreateSharedMemory(
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.
@ -197,18 +192,18 @@ public:
* block.
* @param name Optional object name, used for debugging purposes.
*/
SharedPtr<SharedMemory> CreateSharedMemoryForApplet(u32 offset, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
std::shared_ptr<SharedMemory> CreateSharedMemoryForApplet(u32 offset, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
std::string name = "Unknown Applet");
u32 GenerateObjectID();
/// Retrieves a process from the current list of processes.
SharedPtr<Process> GetProcessById(u32 process_id) const;
std::shared_ptr<Process> GetProcessById(u32 process_id) const;
SharedPtr<Process> GetCurrentProcess() const;
void SetCurrentProcess(SharedPtr<Process> process);
std::shared_ptr<Process> GetCurrentProcess() const;
void SetCurrentProcess(std::shared_ptr<Process> process);
ThreadManager& GetThreadManager();
const ThreadManager& GetThreadManager() const;
@ -228,14 +223,14 @@ public:
std::array<MemoryRegionInfo, 3> memory_regions;
/// Adds a port to the named port table
void AddNamedPort(std::string name, SharedPtr<ClientPort> port);
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
void PrepareReschedule() {
prepare_reschedule_callback();
}
/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort
std::unordered_map<std::string, SharedPtr<ClientPort>> named_ports;
std::unordered_map<std::string, std::shared_ptr<ClientPort>> named_ports;
Memory::MemorySystem& memory;
@ -263,9 +258,9 @@ private:
u32 next_process_id = 10;
// Lists all processes that exist in the current session.
std::vector<SharedPtr<Process>> process_list;
std::vector<std::shared_ptr<Process>> process_list;
SharedPtr<Process> current_process;
std::shared_ptr<Process> current_process;
std::unique_ptr<ThreadManager> thread_manager;

View file

@ -27,8 +27,8 @@ void ReleaseThreadMutexes(Thread* thread) {
Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {}
Mutex::~Mutex() {}
SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
SharedPtr<Mutex> mutex(new Mutex(*this));
std::shared_ptr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name) {
auto mutex{std::make_shared<Mutex>(*this)};
mutex->lock_count = 0;
mutex->name = std::move(name);
@ -42,7 +42,7 @@ SharedPtr<Mutex> KernelSystem::CreateMutex(bool initial_locked, std::string name
}
bool Mutex::ShouldWait(Thread* thread) const {
return lock_count > 0 && thread != holding_thread;
return lock_count > 0 && thread != holding_thread.get();
}
void Mutex::Acquire(Thread* thread) {
@ -51,8 +51,8 @@ void Mutex::Acquire(Thread* thread) {
// Actually "acquire" the mutex only if we don't already have it
if (lock_count == 0) {
priority = thread->current_priority;
thread->held_mutexes.insert(this);
holding_thread = thread;
thread->held_mutexes.insert(SharedFrom(this));
holding_thread = SharedFrom(thread);
thread->UpdatePriority();
kernel.PrepareReschedule();
}
@ -62,7 +62,7 @@ void Mutex::Acquire(Thread* thread) {
ResultCode Mutex::Release(Thread* thread) {
// We can only release the mutex if it's held by the calling thread.
if (thread != holding_thread) {
if (thread != holding_thread.get()) {
if (holding_thread) {
LOG_ERROR(
Kernel,
@ -83,7 +83,7 @@ ResultCode Mutex::Release(Thread* thread) {
// Yield to the next thread only if we've fully released the mutex
if (lock_count == 0) {
holding_thread->held_mutexes.erase(this);
holding_thread->held_mutexes.erase(SharedFrom(this));
holding_thread->UpdatePriority();
holding_thread = nullptr;
WakeupAllWaitingThreads();
@ -93,15 +93,15 @@ ResultCode Mutex::Release(Thread* thread) {
return RESULT_SUCCESS;
}
void Mutex::AddWaitingThread(SharedPtr<Thread> thread) {
void Mutex::AddWaitingThread(std::shared_ptr<Thread> thread) {
WaitObject::AddWaitingThread(thread);
thread->pending_mutexes.insert(this);
thread->pending_mutexes.insert(SharedFrom(this));
UpdatePriority();
}
void Mutex::RemoveWaitingThread(Thread* thread) {
WaitObject::RemoveWaitingThread(thread);
thread->pending_mutexes.erase(this);
thread->pending_mutexes.erase(SharedFrom(this));
UpdatePriority();
}

View file

@ -16,6 +16,9 @@ class Thread;
class Mutex final : public WaitObject {
public:
explicit Mutex(KernelSystem& kernel);
~Mutex() override;
std::string GetTypeName() const override {
return "Mutex";
}
@ -28,10 +31,10 @@ public:
return HANDLE_TYPE;
}
int lock_count; ///< Number of times the mutex has been acquired
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
int lock_count; ///< Number of times the mutex has been acquired
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
std::shared_ptr<Thread> holding_thread; ///< Thread that has acquired the mutex
/**
* Elevate the mutex priority to the best priority
@ -42,7 +45,7 @@ public:
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
void AddWaitingThread(SharedPtr<Thread> thread) override;
void AddWaitingThread(std::shared_ptr<Thread> thread) override;
void RemoveWaitingThread(Thread* thread) override;
/**
@ -53,10 +56,6 @@ public:
ResultCode Release(Thread* thread);
private:
explicit Mutex(KernelSystem& kernel);
~Mutex() override;
friend class KernelSystem;
KernelSystem& kernel;
};

View file

@ -5,6 +5,7 @@
#pragma once
#include <atomic>
#include <memory>
#include <string>
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
@ -37,7 +38,7 @@ enum {
DEFAULT_STACK_SIZE = 0x4000,
};
class Object : NonCopyable {
class Object : NonCopyable, public std::enable_shared_from_this<Object> {
public:
explicit Object(KernelSystem& kernel);
virtual ~Object();
@ -62,22 +63,15 @@ public:
bool IsWaitable() const;
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;
};
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
inline void intrusive_ptr_add_ref(Object* object) {
object->ref_count.fetch_add(1, std::memory_order_relaxed);
}
template <typename T>
std::shared_ptr<T> SharedFrom(T* raw) {
if (raw == nullptr)
return nullptr;
inline void intrusive_ptr_release(Object* object) {
if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete object;
}
return std::static_pointer_cast<T>(raw->shared_from_this());
}
/**
@ -85,9 +79,9 @@ inline void intrusive_ptr_release(Object* object) {
* @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
*/
template <typename T>
inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
inline std::shared_ptr<T> DynamicObjectCast(std::shared_ptr<Object> object) {
if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
return boost::static_pointer_cast<T>(object);
return std::static_pointer_cast<T>(object);
}
return nullptr;
}

View file

@ -17,8 +17,8 @@
namespace Kernel {
SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
SharedPtr<CodeSet> codeset(new CodeSet(*this));
std::shared_ptr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
auto codeset{std::make_shared<CodeSet>(*this)};
codeset->name = std::move(name);
codeset->program_id = program_id;
@ -29,8 +29,8 @@ SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id)
CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {}
CodeSet::~CodeSet() {}
SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) {
SharedPtr<Process> process(new Process(*this));
std::shared_ptr<Process> KernelSystem::CreateProcess(std::shared_ptr<CodeSet> code_set) {
auto process{std::make_shared<Process>(*this)};
process->codeset = std::move(code_set);
process->flags.raw = 0;
@ -142,7 +142,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
status = ProcessStatus::Running;
vm_manager.LogLayout(Log::Level::Debug);
Kernel::SetupMainThread(kernel, codeset->entrypoint, main_thread_priority, this);
Kernel::SetupMainThread(kernel, codeset->entrypoint, main_thread_priority, SharedFrom(this));
}
VAddr Process::GetLinearHeapAreaAddress() const {
@ -416,10 +416,10 @@ Kernel::Process::~Process() {
kernel.memory.UnregisterPageTable(&vm_manager.page_table);
}
SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {
std::shared_ptr<Process> KernelSystem::GetProcessById(u32 process_id) const {
auto itr = std::find_if(
process_list.begin(), process_list.end(),
[&](const SharedPtr<Process>& process) { return process->process_id == process_id; });
[&](const std::shared_ptr<Process>& process) { return process->process_id == process_id; });
if (itr == process_list.end())
return nullptr;

View file

@ -52,6 +52,9 @@ struct MemoryRegionInfo;
class CodeSet final : public Object {
public:
explicit CodeSet(KernelSystem& kernel);
~CodeSet() override;
struct Segment {
std::size_t offset = 0;
VAddr addr = 0;
@ -103,16 +106,13 @@ public:
std::string name;
/// Title ID corresponding to the process
u64 program_id;
private:
explicit CodeSet(KernelSystem& kernel);
~CodeSet() override;
friend class KernelSystem;
};
class Process final : public Object {
public:
explicit Process(Kernel::KernelSystem& kernel);
~Process() override;
std::string GetTypeName() const override {
return "Process";
}
@ -127,9 +127,9 @@ public:
HandleTable handle_table;
SharedPtr<CodeSet> codeset;
std::shared_ptr<CodeSet> codeset;
/// Resource limit descriptor for this process
SharedPtr<ResourceLimit> resource_limit;
std::shared_ptr<ResourceLimit> resource_limit;
/// The process may only call SVCs which have the corresponding bit set.
std::bitset<0x80> svc_access_mask;
@ -194,10 +194,6 @@ public:
bool privileged = false);
private:
explicit Process(Kernel::KernelSystem& kernel);
~Process() override;
friend class KernelSystem;
KernelSystem& kernel;
};
} // namespace Kernel

View file

@ -12,14 +12,14 @@ namespace Kernel {
ResourceLimit::ResourceLimit(KernelSystem& kernel) : Object(kernel) {}
ResourceLimit::~ResourceLimit() {}
SharedPtr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));
std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelSystem& kernel, std::string name) {
auto resource_limit{std::make_shared<ResourceLimit>(kernel)};
resource_limit->name = std::move(name);
return resource_limit;
}
SharedPtr<ResourceLimit> ResourceLimitList::GetForCategory(ResourceLimitCategory category) {
std::shared_ptr<ResourceLimit> ResourceLimitList::GetForCategory(ResourceLimitCategory category) {
switch (category) {
case ResourceLimitCategory::APPLICATION:
case ResourceLimitCategory::SYS_APPLET:
@ -91,7 +91,7 @@ u32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
ResourceLimitList::ResourceLimitList(KernelSystem& kernel) {
// Create the four resource limits that the system uses
// Create the APPLICATION resource limit
SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
std::shared_ptr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
resource_limit->max_priority = 0x18;
resource_limit->max_commit = 0x4000000;
resource_limit->max_threads = 0x20;

View file

@ -32,10 +32,14 @@ enum ResourceTypes {
class ResourceLimit final : public Object {
public:
explicit ResourceLimit(KernelSystem& kernel);
~ResourceLimit() override;
/**
* Creates a resource limit object.
*/
static SharedPtr<ResourceLimit> Create(KernelSystem& kernel, std::string name = "Unknown");
static std::shared_ptr<ResourceLimit> Create(KernelSystem& kernel,
std::string name = "Unknown");
std::string GetTypeName() const override {
return "ResourceLimit";
@ -105,10 +109,6 @@ public:
/// Current CPU time that the processes in this category are utilizing
s32 current_cpu_time = 0;
private:
explicit ResourceLimit(KernelSystem& kernel);
~ResourceLimit() override;
};
class ResourceLimitList {
@ -121,10 +121,10 @@ public:
* @param category The resource limit category
* @returns The resource limit associated with the category
*/
SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
std::shared_ptr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
private:
std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
std::array<std::shared_ptr<ResourceLimit>, 4> resource_limits;
};
} // namespace Kernel

View file

@ -13,13 +13,14 @@ namespace Kernel {
Semaphore::Semaphore(KernelSystem& kernel) : WaitObject(kernel) {}
Semaphore::~Semaphore() {}
ResultVal<SharedPtr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count, s32 max_count,
std::string name) {
ResultVal<std::shared_ptr<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(*this));
auto semaphore{std::make_shared<Semaphore>(*this)};
// When the semaphore is created, some slots are reserved for other threads,
// and the rest is reserved for the caller thread
@ -27,7 +28,7 @@ ResultVal<SharedPtr<Semaphore>> KernelSystem::CreateSemaphore(s32 initial_count,
semaphore->available_count = initial_count;
semaphore->name = std::move(name);
return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
return MakeResult<std::shared_ptr<Semaphore>>(std::move(semaphore));
}
bool Semaphore::ShouldWait(Thread* thread) const {

View file

@ -15,6 +15,9 @@ namespace Kernel {
class Semaphore final : public WaitObject {
public:
explicit Semaphore(KernelSystem& kernel);
~Semaphore() override;
std::string GetTypeName() const override {
return "Semaphore";
}
@ -40,12 +43,6 @@ public:
* @return The number of free slots the semaphore had before this call
*/
ResultVal<s32> Release(s32 release_count);
private:
explicit Semaphore(KernelSystem& kernel);
~Semaphore() override;
friend class KernelSystem;
};
} // namespace Kernel

View file

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

View file

@ -20,6 +20,9 @@ class SessionRequestHandler;
class ServerPort final : public WaitObject {
public:
explicit ServerPort(KernelSystem& kernel);
~ServerPort() override;
std::string GetTypeName() const override {
return "ServerPort";
}
@ -36,7 +39,7 @@ public:
* Accepts a pending incoming connection on this port. If there are no pending sessions, will
* return ERR_NO_PENDING_SESSIONS.
*/
ResultVal<SharedPtr<ServerSession>> Accept();
ResultVal<std::shared_ptr<ServerSession>> Accept();
/**
* Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
@ -49,7 +52,7 @@ public:
std::string name; ///< Name of port (optional)
/// ServerSessions waiting to be accepted by the port
std::vector<SharedPtr<ServerSession>> pending_sessions;
std::vector<std::shared_ptr<ServerSession>> pending_sessions;
/// This session's HLE request handler template (optional)
/// ServerSessions created from this port inherit a reference to this handler.
@ -57,12 +60,6 @@ public:
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
private:
explicit ServerPort(KernelSystem& kernel);
~ServerPort() override;
friend class KernelSystem;
};
} // namespace Kernel

View file

@ -28,8 +28,9 @@ ServerSession::~ServerSession() {
parent->server = nullptr;
}
ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelSystem& kernel, std::string name) {
SharedPtr<ServerSession> server_session(new ServerSession(kernel));
ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelSystem& kernel,
std::string name) {
auto server_session{std::make_shared<ServerSession>(kernel)};
server_session->name = std::move(name);
server_session->parent = nullptr;
@ -59,7 +60,7 @@ void ServerSession::Acquire(Thread* thread) {
pending_requesting_threads.pop_back();
}
ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread) {
// The ServerSession received a sync request, this means that there's new data available
// from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
// similar.
@ -71,7 +72,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
kernel.memory.ReadBlock(*current_process, thread->GetCommandBufferAddress(), cmd_buf.data(),
cmd_buf.size() * sizeof(u32));
Kernel::HLERequestContext context(kernel, this);
Kernel::HLERequestContext context(kernel, SharedFrom(this));
context.PopulateFromIncomingCommandBuffer(cmd_buf.data(), *current_process);
hle_handler->HandleSyncRequest(context);
@ -119,10 +120,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
return RESULT_SUCCESS;
}
std::tuple<SharedPtr<ServerSession>, SharedPtr<ClientSession>> KernelSystem::CreateSessionPair(
const std::string& name, SharedPtr<ClientPort> port) {
std::tuple<std::shared_ptr<ServerSession>, std::shared_ptr<ClientSession>>
KernelSystem::CreateSessionPair(const std::string& name, std::shared_ptr<ClientPort> port) {
auto server_session = ServerSession::Create(*this, name + "_Server").Unwrap();
SharedPtr<ClientSession> client_session(new ClientSession(*this));
auto client_session{std::make_shared<ClientSession>(*this)};
client_session->name = name + "_Client";
std::shared_ptr<Session> parent(new Session);

View file

@ -37,6 +37,9 @@ class Thread;
*/
class ServerSession final : public WaitObject {
public:
~ServerSession() override;
explicit ServerSession(KernelSystem& kernel);
std::string GetName() const override {
return name;
}
@ -63,7 +66,7 @@ public:
* @param thread Thread that initiated the request.
* @returns ResultCode from the operation.
*/
ResultCode HandleSyncRequest(SharedPtr<Thread> thread);
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread);
bool ShouldWait(Thread* thread) const override;
@ -77,20 +80,17 @@ public:
/// List of threads that are pending a response after a sync request. This list is processed in
/// a LIFO manner, thus, the last request will be dispatched first.
/// TODO(Subv): Verify if this is indeed processed in LIFO using a hardware test.
std::vector<SharedPtr<Thread>> pending_requesting_threads;
std::vector<std::shared_ptr<Thread>> pending_requesting_threads;
/// Thread whose request is currently being handled. A request is considered "handled" when a
/// response is sent via svcReplyAndReceive.
/// TODO(Subv): Find a better name for this.
SharedPtr<Thread> currently_handling;
std::shared_ptr<Thread> currently_handling;
/// A temporary list holding mapped buffer info from IPC request, used for during IPC reply
std::vector<MappedBufferContext> mapped_buffer_context;
private:
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.
@ -98,8 +98,8 @@ private:
* @param name Optional name of the server session.
* @return The created server session
*/
static ResultVal<SharedPtr<ServerSession>> Create(KernelSystem& kernel,
std::string name = "Unknown");
static ResultVal<std::shared_ptr<ServerSession>> Create(KernelSystem& kernel,
std::string name = "Unknown");
friend class KernelSystem;
KernelSystem& kernel;

View file

@ -20,8 +20,8 @@ class ServerSession;
*/
class Session final {
public:
ClientSession* client = nullptr; ///< The client endpoint of the session.
ServerSession* server = nullptr; ///< The server endpoint of the session.
SharedPtr<ClientPort> port; ///< The port that this session is associated with (optional).
ClientSession* client = nullptr; ///< The client endpoint of the session.
ServerSession* server = nullptr; ///< The server endpoint of the session.
std::shared_ptr<ClientPort> port; ///< The port that this session is associated with (optional).
};
} // namespace Kernel

View file

@ -24,10 +24,10 @@ SharedMemory::~SharedMemory() {
}
}
ResultVal<SharedPtr<SharedMemory>> KernelSystem::CreateSharedMemory(
ResultVal<std::shared_ptr<SharedMemory>> KernelSystem::CreateSharedMemory(
Process* owner_process, u32 size, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory(*this));
auto shared_memory{std::make_shared<SharedMemory>(*this)};
shared_memory->owner_process = owner_process;
shared_memory->name = std::move(name);
@ -69,10 +69,10 @@ ResultVal<SharedPtr<SharedMemory>> KernelSystem::CreateSharedMemory(
return MakeResult(shared_memory);
}
SharedPtr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
std::shared_ptr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet(
u32 offset, u32 size, MemoryPermission permissions, MemoryPermission other_permissions,
std::string name) {
SharedPtr<SharedMemory> shared_memory(new SharedMemory(*this));
auto shared_memory{std::make_shared<SharedMemory>(*this)};
// Allocate memory in heap
MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::SYSTEM);

View file

@ -15,6 +15,9 @@ namespace Kernel {
class SharedMemory final : public Object {
public:
explicit SharedMemory(KernelSystem& kernel);
~SharedMemory() override;
std::string GetTypeName() const override {
return "SharedMemory";
}
@ -79,9 +82,6 @@ public:
const u8* GetPointer(u32 offset = 0) const;
private:
explicit SharedMemory(KernelSystem& kernel);
~SharedMemory() override;
/// Offset in FCRAM of the shared memory block in the linear heap if no address was specified
/// during creation.
PAddr linear_heap_phys_offset = 0;

View file

@ -271,7 +271,7 @@ ResultCode SVC::ControlMemory(u32* out_addr, u32 addr0, u32 addr1, u32 size, u32
}
void SVC::ExitProcess() {
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->process_id);
ASSERT_MSG(current_process->status == ProcessStatus::Running, "Process has already exited");
@ -281,10 +281,10 @@ void SVC::ExitProcess() {
// Stop all the process threads that are currently waiting for objects.
auto& thread_list = kernel.GetThreadManager().GetThreadList();
for (auto& thread : thread_list) {
if (thread->owner_process != current_process)
if (thread->owner_process != current_process.get())
continue;
if (thread == kernel.GetThreadManager().GetCurrentThread())
if (thread.get() == kernel.GetThreadManager().GetCurrentThread())
continue;
// TODO(Subv): When are the other running/ready threads terminated?
@ -308,7 +308,7 @@ ResultCode SVC::MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 oth
"otherpermission={}",
handle, addr, permissions, other_permissions);
SharedPtr<SharedMemory> shared_memory =
std::shared_ptr<SharedMemory> shared_memory =
kernel.GetCurrentProcess()->handle_table.Get<SharedMemory>(handle);
if (shared_memory == nullptr)
return ERR_INVALID_HANDLE;
@ -337,8 +337,9 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) {
// TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
SharedPtr<SharedMemory> shared_memory = current_process->handle_table.Get<SharedMemory>(handle);
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<SharedMemory> shared_memory =
current_process->handle_table.Get<SharedMemory>(handle);
if (shared_memory == nullptr)
return ERR_INVALID_HANDLE;
@ -366,7 +367,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
auto client_port = it->second;
SharedPtr<ClientSession> client_session;
std::shared_ptr<ClientSession> client_session;
CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session
@ -376,7 +377,7 @@ ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
/// Makes a blocking IPC call to an OS service.
ResultCode SVC::SendSyncRequest(Handle handle) {
SharedPtr<ClientSession> session =
std::shared_ptr<ClientSession> session =
kernel.GetCurrentProcess()->handle_table.Get<ClientSession>(handle);
if (session == nullptr) {
return ERR_INVALID_HANDLE;
@ -386,7 +387,7 @@ ResultCode SVC::SendSyncRequest(Handle handle) {
system.PrepareReschedule();
return session->SendSyncRequest(kernel.GetThreadManager().GetCurrentThread());
return session->SendSyncRequest(SharedFrom(kernel.GetThreadManager().GetCurrentThread()));
}
/// Close a handle
@ -412,14 +413,14 @@ ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) {
return RESULT_TIMEOUT;
thread->wait_objects = {object};
object->AddWaitingThread(thread);
object->AddWaitingThread(SharedFrom(thread));
thread->status = ThreadStatus::WaitSynchAny;
// Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object) {
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object) {
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
if (reason == ThreadWakeupReason::Timeout) {
@ -463,7 +464,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
if (handle_count < 0)
return ERR_OUT_OF_RANGE;
using ObjectPtr = SharedPtr<WaitObject>;
using ObjectPtr = std::shared_ptr<WaitObject>;
std::vector<ObjectPtr> objects(handle_count);
for (int i = 0; i < handle_count; ++i) {
@ -499,7 +500,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
// Add the thread to each of the objects' waiting threads.
for (auto& object : objects) {
object->AddWaitingThread(thread);
object->AddWaitingThread(SharedFrom(thread));
}
thread->wait_objects = std::move(objects);
@ -507,8 +508,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
// Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object) {
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object) {
ASSERT(thread->status == ThreadStatus::WaitSynchAll);
if (reason == ThreadWakeupReason::Timeout) {
@ -556,7 +557,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
// Add the thread to each of the objects' waiting threads.
for (std::size_t i = 0; i < objects.size(); ++i) {
WaitObject* object = objects[i].get();
object->AddWaitingThread(thread);
object->AddWaitingThread(SharedFrom(thread));
}
thread->wait_objects = std::move(objects);
@ -567,8 +568,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
// Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = [](ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object) {
thread->wakeup_callback = [](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object) {
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
if (reason == ThreadWakeupReason::Timeout) {
@ -593,8 +594,8 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
}
static ResultCode ReceiveIPCRequest(Memory::MemorySystem& memory,
SharedPtr<ServerSession> server_session,
SharedPtr<Thread> thread) {
std::shared_ptr<ServerSession> server_session,
std::shared_ptr<Thread> thread) {
if (server_session->parent->client == nullptr) {
return ERR_SESSION_CLOSED_BY_REMOTE;
}
@ -631,10 +632,10 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
if (handle_count < 0)
return ERR_OUT_OF_RANGE;
using ObjectPtr = SharedPtr<WaitObject>;
using ObjectPtr = std::shared_ptr<WaitObject>;
std::vector<ObjectPtr> objects(handle_count);
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
for (int i = 0; i < handle_count; ++i) {
Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
@ -670,8 +671,8 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
VAddr target_address = request_thread->GetCommandBufferAddress();
ResultCode translation_result =
TranslateCommandBuffer(memory, thread, request_thread, source_address, target_address,
session->mapped_buffer_context, true);
TranslateCommandBuffer(memory, SharedFrom(thread), request_thread, source_address,
target_address, session->mapped_buffer_context, true);
// Note: The real kernel seems to always panic if the Server->Client buffer translation
// fails for whatever reason.
@ -706,7 +707,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
return RESULT_SUCCESS;
auto server_session = static_cast<ServerSession*>(object);
return ReceiveIPCRequest(memory, server_session, thread);
return ReceiveIPCRequest(memory, SharedFrom(server_session), SharedFrom(thread));
}
// No objects were ready to be acquired, prepare to suspend the thread.
@ -717,14 +718,14 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
// Add the thread to each of the objects' waiting threads.
for (std::size_t i = 0; i < objects.size(); ++i) {
WaitObject* object = objects[i].get();
object->AddWaitingThread(thread);
object->AddWaitingThread(SharedFrom(thread));
}
thread->wait_objects = std::move(objects);
thread->wakeup_callback = [& memory = this->memory](ThreadWakeupReason reason,
SharedPtr<Thread> thread,
SharedPtr<WaitObject> object) {
std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object) {
ASSERT(thread->status == ThreadStatus::WaitSynchAny);
ASSERT(reason == ThreadWakeupReason::Signal);
@ -750,7 +751,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co
/// Create an address arbiter (to allocate access to shared resources)
ResultCode SVC::CreateAddressArbiter(Handle* out_handle) {
SharedPtr<AddressArbiter> arbiter = kernel.CreateAddressArbiter();
std::shared_ptr<AddressArbiter> arbiter = kernel.CreateAddressArbiter();
CASCADE_RESULT(*out_handle,
kernel.GetCurrentProcess()->handle_table.Create(std::move(arbiter)));
LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
@ -762,13 +763,13 @@ ResultCode SVC::ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}",
handle, address, type, value);
SharedPtr<AddressArbiter> arbiter =
std::shared_ptr<AddressArbiter> arbiter =
kernel.GetCurrentProcess()->handle_table.Get<AddressArbiter>(handle);
if (arbiter == nullptr)
return ERR_INVALID_HANDLE;
auto res =
arbiter->ArbitrateAddress(kernel.GetThreadManager().GetCurrentThread(),
arbiter->ArbitrateAddress(SharedFrom(kernel.GetThreadManager().GetCurrentThread()),
static_cast<ArbitrationType>(type), address, value, nanoseconds);
// TODO(Subv): Identify in which specific cases this call should cause a reschedule.
@ -812,8 +813,8 @@ void SVC::OutputDebugString(VAddr address, s32 len) {
ResultCode SVC::GetResourceLimit(Handle* resource_limit, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
SharedPtr<Process> process = current_process->handle_table.Get<Process>(process_handle);
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> process = current_process->handle_table.Get<Process>(process_handle);
if (process == nullptr)
return ERR_INVALID_HANDLE;
@ -828,7 +829,7 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}",
resource_limit_handle, names, name_count);
SharedPtr<ResourceLimit> resource_limit =
std::shared_ptr<ResourceLimit> resource_limit =
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(resource_limit_handle);
if (resource_limit == nullptr)
return ERR_INVALID_HANDLE;
@ -848,7 +849,7 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}",
resource_limit_handle, names, name_count);
SharedPtr<ResourceLimit> resource_limit =
std::shared_ptr<ResourceLimit> resource_limit =
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(resource_limit_handle);
if (resource_limit == nullptr)
return ERR_INVALID_HANDLE;
@ -871,9 +872,9 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr
return ERR_OUT_OF_RANGE;
}
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
SharedPtr<ResourceLimit>& resource_limit = current_process->resource_limit;
std::shared_ptr<ResourceLimit>& resource_limit = current_process->resource_limit;
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
return ERR_NOT_AUTHORIZED;
}
@ -901,7 +902,7 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr
break;
}
CASCADE_RESULT(SharedPtr<Thread> thread,
CASCADE_RESULT(std::shared_ptr<Thread> thread,
kernel.CreateThread(name, entry_point, priority, arg, processor_id, stack_top,
*current_process));
@ -930,7 +931,8 @@ void SVC::ExitThread() {
/// Gets the priority for the specified thread
ResultCode SVC::GetThreadPriority(u32* priority, Handle handle) {
const SharedPtr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
const std::shared_ptr<Thread> thread =
kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
if (thread == nullptr)
return ERR_INVALID_HANDLE;
@ -944,13 +946,13 @@ ResultCode SVC::SetThreadPriority(Handle handle, u32 priority) {
return ERR_OUT_OF_RANGE;
}
SharedPtr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
std::shared_ptr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
if (thread == nullptr)
return ERR_INVALID_HANDLE;
// Note: The kernel uses the current process's resource limit instead of
// the one from the thread owner's resource limit.
SharedPtr<ResourceLimit>& resource_limit = kernel.GetCurrentProcess()->resource_limit;
std::shared_ptr<ResourceLimit>& resource_limit = kernel.GetCurrentProcess()->resource_limit;
if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
return ERR_NOT_AUTHORIZED;
}
@ -968,7 +970,7 @@ ResultCode SVC::SetThreadPriority(Handle handle, u32 priority) {
/// Create a mutex
ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) {
SharedPtr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0);
std::shared_ptr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0);
mutex->name = fmt::format("mutex-{:08x}", system.CPU().GetReg(14));
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(mutex)));
@ -982,7 +984,7 @@ ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) {
ResultCode SVC::ReleaseMutex(Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
SharedPtr<Mutex> mutex = kernel.GetCurrentProcess()->handle_table.Get<Mutex>(handle);
std::shared_ptr<Mutex> mutex = kernel.GetCurrentProcess()->handle_table.Get<Mutex>(handle);
if (mutex == nullptr)
return ERR_INVALID_HANDLE;
@ -993,7 +995,7 @@ ResultCode SVC::ReleaseMutex(Handle handle) {
ResultCode SVC::GetProcessId(u32* process_id, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
const SharedPtr<Process> process =
const std::shared_ptr<Process> process =
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
if (process == nullptr)
return ERR_INVALID_HANDLE;
@ -1006,12 +1008,12 @@ ResultCode SVC::GetProcessId(u32* process_id, Handle process_handle) {
ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
const SharedPtr<Thread> thread =
const std::shared_ptr<Thread> thread =
kernel.GetCurrentProcess()->handle_table.Get<Thread>(thread_handle);
if (thread == nullptr)
return ERR_INVALID_HANDLE;
const SharedPtr<Process> process = thread->owner_process;
const std::shared_ptr<Process> process = SharedFrom(thread->owner_process);
ASSERT_MSG(process != nullptr, "Invalid parent process for thread={:#010X}", thread_handle);
@ -1023,7 +1025,8 @@ ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
ResultCode SVC::GetThreadId(u32* thread_id, Handle handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle);
const SharedPtr<Thread> thread = kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
const std::shared_ptr<Thread> thread =
kernel.GetCurrentProcess()->handle_table.Get<Thread>(handle);
if (thread == nullptr)
return ERR_INVALID_HANDLE;
@ -1033,7 +1036,7 @@ ResultCode SVC::GetThreadId(u32* thread_id, Handle handle) {
/// Creates a semaphore
ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
CASCADE_RESULT(SharedPtr<Semaphore> semaphore,
CASCADE_RESULT(std::shared_ptr<Semaphore> semaphore,
kernel.CreateSemaphore(initial_count, max_count));
semaphore->name = fmt::format("semaphore-{:08x}", system.CPU().GetReg(14));
CASCADE_RESULT(*out_handle,
@ -1048,7 +1051,7 @@ ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_c
ResultCode SVC::ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle);
SharedPtr<Semaphore> semaphore =
std::shared_ptr<Semaphore> semaphore =
kernel.GetCurrentProcess()->handle_table.Get<Semaphore>(handle);
if (semaphore == nullptr)
return ERR_INVALID_HANDLE;
@ -1061,7 +1064,7 @@ ResultCode SVC::ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
/// Query process memory
ResultCode SVC::QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
Handle process_handle, u32 addr) {
SharedPtr<Process> process =
std::shared_ptr<Process> process =
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
if (process == nullptr)
return ERR_INVALID_HANDLE;
@ -1105,8 +1108,8 @@ ResultCode SVC::QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32 ad
/// Create an event
ResultCode SVC::CreateEvent(Handle* out_handle, u32 reset_type) {
SharedPtr<Event> evt = kernel.CreateEvent(static_cast<ResetType>(reset_type),
fmt::format("event-{:08x}", system.CPU().GetReg(14)));
std::shared_ptr<Event> evt = kernel.CreateEvent(
static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", system.CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt)));
LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
@ -1125,7 +1128,7 @@ ResultCode SVC::DuplicateHandle(Handle* out, Handle handle) {
ResultCode SVC::SignalEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
SharedPtr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
std::shared_ptr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
if (evt == nullptr)
return ERR_INVALID_HANDLE;
@ -1138,7 +1141,7 @@ ResultCode SVC::SignalEvent(Handle handle) {
ResultCode SVC::ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
SharedPtr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
std::shared_ptr<Event> evt = kernel.GetCurrentProcess()->handle_table.Get<Event>(handle);
if (evt == nullptr)
return ERR_INVALID_HANDLE;
@ -1148,7 +1151,7 @@ ResultCode SVC::ClearEvent(Handle handle) {
/// Creates a timer
ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) {
SharedPtr<Timer> timer = kernel.CreateTimer(
std::shared_ptr<Timer> timer = kernel.CreateTimer(
static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", system.CPU().GetReg(14)));
CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(timer)));
@ -1161,7 +1164,7 @@ ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) {
ResultCode SVC::ClearTimer(Handle handle) {
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
SharedPtr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
std::shared_ptr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
if (timer == nullptr)
return ERR_INVALID_HANDLE;
@ -1177,7 +1180,7 @@ ResultCode SVC::SetTimer(Handle handle, s64 initial, s64 interval) {
return ERR_OUT_OF_RANGE_KERNEL;
}
SharedPtr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
std::shared_ptr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
if (timer == nullptr)
return ERR_INVALID_HANDLE;
@ -1190,7 +1193,7 @@ ResultCode SVC::SetTimer(Handle handle, s64 initial, s64 interval) {
ResultCode SVC::CancelTimer(Handle handle) {
LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
SharedPtr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
std::shared_ptr<Timer> timer = kernel.GetCurrentProcess()->handle_table.Get<Timer>(handle);
if (timer == nullptr)
return ERR_INVALID_HANDLE;
@ -1234,7 +1237,7 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my
if (size % Memory::PAGE_SIZE != 0)
return ERR_MISALIGNED_SIZE;
SharedPtr<SharedMemory> shared_memory = nullptr;
std::shared_ptr<SharedMemory> shared_memory = nullptr;
auto VerifyPermissions = [](MemoryPermission permission) {
// SharedMemory blocks can not be created with Execute permissions
@ -1262,7 +1265,7 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my
return ERR_INVALID_ADDRESS;
}
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
// When trying to create a memory block with address = 0,
// if the process has the Shared Device Memory flag in the exheader,
@ -1287,23 +1290,23 @@ ResultCode SVC::CreatePort(Handle* server_port, Handle* client_port, VAddr name_
// TODO(Subv): Implement named ports.
ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
auto ports = kernel.CreatePortPair(max_sessions);
CASCADE_RESULT(*client_port, current_process->handle_table.Create(
std::move(std::get<SharedPtr<ClientPort>>(ports))));
std::move(std::get<std::shared_ptr<ClientPort>>(ports))));
// Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
// created.
CASCADE_RESULT(*server_port, current_process->handle_table.Create(
std::move(std::get<SharedPtr<ServerPort>>(ports))));
std::move(std::get<std::shared_ptr<ServerPort>>(ports))));
LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions);
return RESULT_SUCCESS;
}
ResultCode SVC::CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) {
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
SharedPtr<ClientPort> client_port =
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<ClientPort> client_port =
current_process->handle_table.Get<ClientPort>(client_port_handle);
if (client_port == nullptr)
return ERR_INVALID_HANDLE;
@ -1316,12 +1319,12 @@ ResultCode SVC::CreateSessionToPort(Handle* out_client_session, Handle client_po
ResultCode SVC::CreateSession(Handle* server_session, Handle* client_session) {
auto sessions = kernel.CreateSessionPair();
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
auto& server = std::get<SharedPtr<ServerSession>>(sessions);
auto& server = std::get<std::shared_ptr<ServerSession>>(sessions);
CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server)));
auto& client = std::get<SharedPtr<ClientSession>>(sessions);
auto& client = std::get<std::shared_ptr<ClientSession>>(sessions);
CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client)));
LOG_TRACE(Kernel_SVC, "called");
@ -1329,8 +1332,8 @@ ResultCode SVC::CreateSession(Handle* server_session, Handle* client_session) {
}
ResultCode SVC::AcceptSession(Handle* out_server_session, Handle server_port_handle) {
SharedPtr<Process> current_process = kernel.GetCurrentProcess();
SharedPtr<ServerPort> server_port =
std::shared_ptr<Process> current_process = kernel.GetCurrentProcess();
std::shared_ptr<ServerPort> server_port =
current_process->handle_table.Get<ServerPort>(server_port_handle);
if (server_port == nullptr)
return ERR_INVALID_HANDLE;
@ -1386,7 +1389,7 @@ ResultCode SVC::GetSystemInfo(s64* out, u32 type, s32 param) {
ResultCode SVC::GetProcessInfo(s64* out, Handle process_handle, u32 type) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type);
SharedPtr<Process> process =
std::shared_ptr<Process> process =
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
if (process == nullptr)
return ERR_INVALID_HANDLE;

View file

@ -105,13 +105,13 @@ void ThreadManager::SwitchContext(Thread* new_thread) {
auto previous_process = kernel.GetCurrentProcess();
current_thread = new_thread;
current_thread = SharedFrom(new_thread);
ready_queue.remove(new_thread->current_priority, new_thread);
new_thread->status = ThreadStatus::Running;
if (previous_process != current_thread->owner_process) {
kernel.SetCurrentProcess(current_thread->owner_process);
if (previous_process.get() != current_thread->owner_process) {
kernel.SetCurrentProcess(SharedFrom(current_thread->owner_process));
kernel.memory.SetCurrentPageTable(
&current_thread->owner_process->vm_manager.page_table);
}
@ -152,12 +152,13 @@ void ThreadManager::WaitCurrentThread_Sleep() {
void ThreadManager::ExitCurrentThread() {
Thread* thread = GetCurrentThread();
thread->Stop();
thread_list.erase(std::remove(thread_list.begin(), thread_list.end(), thread),
thread_list.erase(std::remove_if(thread_list.begin(), thread_list.end(),
[thread](const auto& p) { return p.get() == thread; }),
thread_list.end());
}
void ThreadManager::ThreadWakeupCallback(u64 thread_id, s64 cycles_late) {
SharedPtr<Thread> thread = wakeup_callback_table.at(thread_id);
std::shared_ptr<Thread> thread = SharedFrom(wakeup_callback_table.at(thread_id));
if (thread == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", thread_id);
return;
@ -286,9 +287,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>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
u32 priority, u32 arg, s32 processor_id,
VAddr stack_top, Process& owner_process) {
ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
u32 priority, u32 arg,
s32 processor_id, VAddr stack_top,
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);
@ -309,7 +311,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
}
SharedPtr<Thread> thread(new Thread(*this));
auto thread{std::make_shared<Thread>(*this)};
thread_manager->thread_list.push_back(thread);
thread_manager->ready_queue.prepare(priority);
@ -372,7 +374,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
thread_manager->ready_queue.push_back(thread->current_priority, thread.get());
thread->status = ThreadStatus::Ready;
return MakeResult<SharedPtr<Thread>>(std::move(thread));
return MakeResult<std::shared_ptr<Thread>>(std::move(thread));
}
void Thread::SetPriority(u32 priority) {
@ -405,14 +407,14 @@ void Thread::BoostPriority(u32 priority) {
current_priority = priority;
}
SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
SharedPtr<Process> owner_process) {
std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
std::shared_ptr<Process> owner_process) {
// Initialize new "main" thread
auto thread_res =
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();
std::shared_ptr<Thread> thread = std::move(thread_res).Unwrap();
thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO |
FPSCR_IXC); // 0x03C00010
@ -450,7 +452,8 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
s32 Thread::GetWaitObjectIndex(WaitObject* object) const {
ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything");
auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object);
auto match = std::find_if(wait_objects.rbegin(), wait_objects.rend(),
[object](const auto& p) { return p.get() == object; });
return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1);
}
@ -473,7 +476,7 @@ ThreadManager::~ThreadManager() {
}
}
const std::vector<SharedPtr<Thread>>& ThreadManager::GetThreadList() {
const std::vector<std::shared_ptr<Thread>>& ThreadManager::GetThreadList() {
return thread_list;
}

View file

@ -99,7 +99,7 @@ public:
/**
* Get a const reference to the thread list for debug use
*/
const std::vector<SharedPtr<Thread>>& GetThreadList();
const std::vector<std::shared_ptr<Thread>>& GetThreadList();
void SetCPU(ARM_Interface& cpu) {
this->cpu = &cpu;
@ -133,7 +133,7 @@ private:
ARM_Interface* cpu;
u32 next_thread_id = 1;
SharedPtr<Thread> current_thread;
std::shared_ptr<Thread> current_thread;
Common::ThreadQueueList<Thread*, ThreadPrioLowest + 1> ready_queue;
std::unordered_map<u64, Thread*> wakeup_callback_table;
@ -141,7 +141,7 @@ private:
Core::TimingEventType* ThreadWakeupEventType = nullptr;
// Lists all threadsthat aren't deleted.
std::vector<SharedPtr<Thread>> thread_list;
std::vector<std::shared_ptr<Thread>> thread_list;
friend class Thread;
friend class KernelSystem;
@ -149,6 +149,9 @@ private:
class Thread final : public WaitObject {
public:
explicit Thread(KernelSystem&);
~Thread() override;
std::string GetName() const override {
return name;
}
@ -278,35 +281,30 @@ public:
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
/// Mutexes currently held by this thread, which will be released when it exits.
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
boost::container::flat_set<std::shared_ptr<Mutex>> held_mutexes;
/// Mutexes that this thread is currently waiting for.
boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
boost::container::flat_set<std::shared_ptr<Mutex>> pending_mutexes;
Process* owner_process; ///< Process that owns this thread
/// Objects that the thread is waiting on, in the same order as they were
// passed to WaitSynchronization1/N.
std::vector<SharedPtr<WaitObject>> wait_objects;
std::vector<std::shared_ptr<WaitObject>> wait_objects;
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
std::string name;
using WakeupCallback = void(ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object);
using WakeupCallback = void(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
std::shared_ptr<WaitObject> object);
// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
// was waiting via WaitSynchronizationN then the object will be the last object that became
// available. In case of a timeout, the object will be nullptr.
std::function<WakeupCallback> wakeup_callback;
private:
explicit Thread(KernelSystem&);
~Thread() override;
ThreadManager& thread_manager;
friend class KernelSystem;
};
/**
@ -317,7 +315,7 @@ private:
* @param owner_process The parent process for the main thread
* @return A shared pointer to the main thread
*/
SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
SharedPtr<Process> owner_process);
std::shared_ptr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 priority,
std::shared_ptr<Process> owner_process);
} // namespace Kernel

View file

@ -21,8 +21,8 @@ Timer::~Timer() {
timer_manager.timer_callback_table.erase(callback_id);
}
SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
SharedPtr<Timer> timer(new Timer(*this));
std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
auto timer{std::make_shared<Timer>(*this)};
timer->reset_type = reset_type;
timer->signaled = false;
@ -94,7 +94,7 @@ void Timer::Signal(s64 cycles_late) {
/// The timer callback event, called when a timer is fired
void TimerManager::TimerCallback(u64 callback_id, s64 cycles_late) {
SharedPtr<Timer> timer = timer_callback_table.at(callback_id);
std::shared_ptr<Timer> timer = SharedFrom(timer_callback_table.at(callback_id));
if (timer == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016x}", callback_id);

View file

@ -37,6 +37,9 @@ private:
class Timer final : public WaitObject {
public:
explicit Timer(KernelSystem& kernel);
~Timer() override;
std::string GetTypeName() const override {
return "Timer";
}
@ -85,9 +88,6 @@ public:
void Signal(s64 cycles_late);
private:
explicit Timer(KernelSystem& kernel);
~Timer() override;
ResetType reset_type; ///< The ResetType of this timer
u64 initial_delay; ///< The delay until the timer fires for the first time

View file

@ -16,14 +16,15 @@
namespace Kernel {
void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
void WaitObject::AddWaitingThread(std::shared_ptr<Thread> thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr == waiting_threads.end())
waiting_threads.push_back(std::move(thread));
}
void WaitObject::RemoveWaitingThread(Thread* thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
auto itr = std::find_if(waiting_threads.begin(), waiting_threads.end(),
[thread](const auto& p) { return p.get() == thread; });
// If a thread passed multiple handles to the same object,
// the kernel might attempt to remove the thread from the object's
// waiting threads list multiple times.
@ -31,7 +32,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
waiting_threads.erase(itr);
}
SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
std::shared_ptr<Thread> WaitObject::GetHighestPriorityReadyThread() {
Thread* candidate = nullptr;
u32 candidate_priority = ThreadPrioLowest + 1;
@ -53,7 +54,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
bool ready_to_run = true;
if (thread->status == ThreadStatus::WaitSynchAll) {
ready_to_run = std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
[&thread](const SharedPtr<WaitObject>& object) {
[&thread](const std::shared_ptr<WaitObject>& object) {
return object->ShouldWait(thread.get());
});
}
@ -64,7 +65,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
}
}
return candidate;
return SharedFrom(candidate);
}
void WaitObject::WakeupAllWaitingThreads() {
@ -79,7 +80,7 @@ void WaitObject::WakeupAllWaitingThreads() {
// Invoke the wakeup callback before clearing the wait objects
if (thread->wakeup_callback)
thread->wakeup_callback(ThreadWakeupReason::Signal, thread, this);
thread->wakeup_callback(ThreadWakeupReason::Signal, thread, SharedFrom(this));
for (auto& object : thread->wait_objects)
object->RemoveWaitingThread(thread.get());
@ -92,7 +93,7 @@ void WaitObject::WakeupAllWaitingThreads() {
hle_notifier();
}
const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
const std::vector<std::shared_ptr<Thread>>& WaitObject::GetWaitingThreads() const {
return waiting_threads;
}

View file

@ -33,7 +33,7 @@ public:
* Add a thread to wait on this object
* @param thread Pointer to thread to add
*/
virtual void AddWaitingThread(SharedPtr<Thread> thread);
virtual void AddWaitingThread(std::shared_ptr<Thread> thread);
/**
* Removes a thread from waiting on this object (e.g. if it was resumed already)
@ -48,17 +48,17 @@ public:
virtual void WakeupAllWaitingThreads();
/// Obtains the highest priority thread that is ready to run from this object's waiting list.
SharedPtr<Thread> GetHighestPriorityReadyThread();
std::shared_ptr<Thread> GetHighestPriorityReadyThread();
/// Get a const reference to the waiting threads list for debug use
const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
const std::vector<std::shared_ptr<Thread>>& GetWaitingThreads() const;
/// Sets a callback which is called when the object becomes available
void SetHLENotifier(std::function<void()> callback);
private:
/// Threads waiting for this object to become available
std::vector<SharedPtr<Thread>> waiting_threads;
std::vector<std::shared_ptr<Thread>> waiting_threads;
/// Function to call when this object becomes available
std::function<void()> hle_notifier;
@ -66,9 +66,9 @@ private:
// Specialization of DynamicObjectCast for WaitObjects
template <>
inline SharedPtr<WaitObject> DynamicObjectCast<WaitObject>(SharedPtr<Object> object) {
inline std::shared_ptr<WaitObject> DynamicObjectCast<WaitObject>(std::shared_ptr<Object> object) {
if (object != nullptr && object->IsWaitable()) {
return boost::static_pointer_cast<WaitObject>(object);
return std::static_pointer_cast<WaitObject>(object);
}
return nullptr;
}