mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	Kernel: replace boost::intrusive_ptr with std::shared_ptr
This commit is contained in:
		
							parent
							
								
									c1de8acfe5
								
							
						
					
					
						commit
						5f11c5f733
					
				
					 96 changed files with 522 additions and 538 deletions
				
			
		| 
						 | 
				
			
			@ -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),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
                ¤t_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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue