diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 5254fa148..fb9cd454a 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -178,7 +178,6 @@ ResultCode AddressArbiter::ArbitrateAddress(std::shared_ptr thread, Arbi // the thread to sleep if (type == ArbitrationType::WaitIfLessThanWithTimeout || type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { - return RESULT_TIMEOUT; } return RESULT_SUCCESS; diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index d12078ce3..b5aebf0b3 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -20,32 +20,31 @@ namespace Kernel { ClientPort::ClientPort(KernelSystem& kernel) : Object(kernel), kernel(kernel) {} ClientPort::~ClientPort() = default; -ResultVal> ClientPort::Connect() { +ResultCode ClientPort::Connect(std::shared_ptr& client_session) { // Note: Threads do not wait for the server endpoint to call // AcceptSession before returning from this call. - if (active_sessions >= max_sessions) { - return ERR_MAX_CONNECTIONS_REACHED; - } + R_UNLESS(active_sessions < max_sessions, ERR_MAX_CONNECTIONS_REACHED); active_sessions++; // Create a new session pair, let the created sessions inherit the parent port's HLE handler. auto [server, client] = kernel.CreateSessionPair(server_port->GetName(), SharedFrom(this)); - if (server_port->hle_handler) + if (server_port->hle_handler) { server_port->hle_handler->ClientConnected(server); - else + } else { server_port->pending_sessions.push_back(server); + } // Wake the threads waiting on the ServerPort server_port->WakeupAllWaitingThreads(); - return client; + client_session = client; + return RESULT_SUCCESS; } void ClientPort::ConnectionClosed() { ASSERT(active_sessions > 0); - --active_sessions; } diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index 8d0f50520..66d022a38 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h @@ -46,7 +46,7 @@ public: * waiting on it to awake. * @returns ClientSession The client endpoint of the created Session pair, or error code. */ - ResultVal> Connect(); + ResultCode Connect(std::shared_ptr& client_session); /** * Signifies that a previously active connection has been closed, diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index a47e6411b..46b21df44 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -47,8 +47,7 @@ ClientSession::~ClientSession() { ResultCode ClientSession::SendSyncRequest(std::shared_ptr thread) { // Keep ServerSession alive until we're done working with it. std::shared_ptr server = SharedFrom(parent->server); - if (server == nullptr) - return ERR_SESSION_CLOSED_BY_REMOTE; + R_UNLESS(server, ERR_SESSION_CLOSED_BY_REMOTE); // Signal the server session that new data is available return server->HandleSyncRequest(std::move(thread)); diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index f1bc7bd12..b78c17d7d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -36,8 +36,9 @@ bool Event::ShouldWait(const Thread* thread) const { void Event::Acquire(Thread* thread) { ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); - if (reset_type == ResetType::OneShot) + if (reset_type == ResetType::OneShot) { signaled = false; + } } void Event::Signal() { @@ -52,8 +53,9 @@ void Event::Clear() { void Event::WakeupAllWaitingThreads() { WaitObject::WakeupAllWaitingThreads(); - if (reset_type == ResetType::Pulse) + if (reset_type == ResetType::Pulse) { signaled = false; + } } } // namespace Kernel diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 8c7b95f26..b38e33432 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -28,45 +28,38 @@ HandleTable::HandleTable(KernelSystem& kernel) : kernel(kernel) { HandleTable::~HandleTable() = default; -ResultVal HandleTable::Create(std::shared_ptr obj) { +ResultCode HandleTable::Create(Handle* out_handle, std::shared_ptr obj) { DEBUG_ASSERT(obj != nullptr); u16 slot = next_free_slot; - if (slot >= generations.size()) { - LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); - return ERR_OUT_OF_HANDLES; - } + R_UNLESS(slot < generations.size(), ERR_OUT_OF_HANDLES); next_free_slot = generations[slot]; u16 generation = next_generation++; // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. // CTR-OS doesn't use generation 0, so skip straight to 1. - if (next_generation >= (1 << 15)) + if (next_generation >= (1 << 15)) { next_generation = 1; + } generations[slot] = generation; objects[slot] = std::move(obj); - Handle handle = generation | (slot << 15); - return handle; + *out_handle = generation | (slot << 15); + return RESULT_SUCCESS; } -ResultVal HandleTable::Duplicate(Handle handle) { +ResultCode HandleTable::Duplicate(Handle* out, Handle handle) { std::shared_ptr object = GetGeneric(handle); - if (object == nullptr) { - LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle); - return ERR_INVALID_HANDLE; - } - return Create(std::move(object)); + R_UNLESS(object, ERR_INVALID_HANDLE); + return Create(out, std::move(object)); } ResultCode HandleTable::Close(Handle handle) { - if (!IsValid(handle)) - return ERR_INVALID_HANDLE; - - u16 slot = GetSlot(handle); + R_UNLESS(IsValid(handle), ERR_INVALID_HANDLE); + const u16 slot = GetSlot(handle); objects[slot] = nullptr; generations[slot] = next_free_slot; @@ -75,9 +68,8 @@ ResultCode HandleTable::Close(Handle handle) { } bool HandleTable::IsValid(Handle handle) const { - std::size_t slot = GetSlot(handle); - u16 generation = GetGeneration(handle); - + const u16 slot = GetSlot(handle); + const u16 generation = GetGeneration(handle); return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; } diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index 728ab5fa3..540971284 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -53,7 +53,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 Create(std::shared_ptr obj); + ResultCode Create(Handle* out_handle, std::shared_ptr obj); /** * Returns a new handle that points to the same object as the passed in handle. @@ -61,7 +61,7 @@ public: * - `ERR_INVALID_HANDLE`: an invalid handle was passed in. * - Any errors returned by `Create()`. */ - ResultVal Duplicate(Handle handle); + ResultCode Duplicate(Handle* out, Handle handle); /** * Closes a handle, removing it from the table and decreasing the object's ref-count. diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 62b993f33..199d45b02 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -239,7 +239,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Handle handle = 0; if (object != nullptr) { // TODO(yuriks): Figure out the proper error handling for if this fails - handle = dst_process.handle_table.Create(object).Unwrap(); + R_ASSERT(dst_process.handle_table.Create(std::addressof(handle), object)); } dst_cmdbuf[i++] = handle; } diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index dade1f520..41e597ed4 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -88,8 +88,8 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy continue; } - auto result = dst_process->handle_table.Create(std::move(object)); - cmd_buf[i++] = result.ValueOr(0); + R_ASSERT(dst_process->handle_table.Create(std::addressof(cmd_buf[i++]), + std::move(object))); } break; } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 478aaba17..a71c67e18 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -192,9 +192,12 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { return; } + VAddr out_addr{}; + auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { - HeapAllocate(segment.addr, segment.size, permissions, memory_state, true); + HeapAllocate(std::addressof(out_addr), segment.addr, segment.size, permissions, + memory_state, true); kernel.memory.WriteBlock(*this, segment.addr, codeset->memory.data() + segment.offset, segment.size); }; @@ -205,8 +208,8 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { MapSegment(codeset->DataSegment(), VMAPermission::ReadWrite, MemoryState::Private); // Allocate and map stack - HeapAllocate(Memory::HEAP_VADDR_END - stack_size, stack_size, VMAPermission::ReadWrite, - MemoryState::Locked, true); + HeapAllocate(std::addressof(out_addr), Memory::HEAP_VADDR_END - stack_size, stack_size, + VMAPermission::ReadWrite, MemoryState::Locked, true); // Map special address mappings kernel.MapSharedPages(vm_manager); @@ -246,8 +249,8 @@ VAddr Process::GetLinearHeapLimit() const { return GetLinearHeapBase() + memory_region->size; } -ResultVal Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms, - MemoryState memory_state, bool skip_range_check) { +ResultCode Process::HeapAllocate(VAddr* out_addr, VAddr target, u32 size, VMAPermission perms, + MemoryState memory_state, bool skip_range_check) { LOG_DEBUG(Kernel, "Allocate heap target={:08X}, size={:08X}", target, size); if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { @@ -290,7 +293,8 @@ ResultVal Process::HeapAllocate(VAddr target, u32 size, VMAPermission per memory_used += size; resource_limit->Reserve(ResourceLimitType::Commit, size); - return target; + *out_addr = target; + return RESULT_SUCCESS; } ResultCode Process::HeapFree(VAddr target, u32 size) { @@ -301,9 +305,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { return ERR_INVALID_ADDRESS; } - if (size == 0) { - return RESULT_SUCCESS; - } + R_SUCCEED_IF(size == 0); // Free heaps block by block CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(target, size)); @@ -322,7 +324,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { return RESULT_SUCCESS; } -ResultVal Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { +ResultCode Process::LinearAllocate(VAddr* out_addr, VAddr target, u32 size, VMAPermission perms) { LOG_DEBUG(Kernel, "Allocate linear heap target={:08X}, size={:08X}", target, size); u32 physical_offset; if (target == 0) { @@ -366,7 +368,8 @@ ResultVal Process::LinearAllocate(VAddr target, u32 size, VMAPermission p resource_limit->Reserve(ResourceLimitType::Commit, size); LOG_DEBUG(Kernel, "Allocated at target={:08X}", target); - return target; + *out_addr = target; + return RESULT_SUCCESS; } ResultCode Process::LinearFree(VAddr target, u32 size) { @@ -377,15 +380,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { return ERR_INVALID_ADDRESS; } - if (size == 0) { - return RESULT_SUCCESS; - } - - ResultCode result = vm_manager.UnmapRange(target, size); - if (result.IsError()) { - LOG_ERROR(Kernel, "Trying to free already freed memory"); - return result; - } + R_SUCCEED_IF(size == 0); + R_TRY(vm_manager.UnmapRange(target, size)); u32 physical_offset = target - GetLinearHeapAreaAddress(); // relative to FCRAM memory_region->Free(physical_offset, size); diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index a7d493f19..1a911f139 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -231,12 +231,12 @@ public: VAddr GetLinearHeapBase() const; VAddr GetLinearHeapLimit() const; - ResultVal HeapAllocate(VAddr target, u32 size, VMAPermission perms, - MemoryState memory_state = MemoryState::Private, - bool skip_range_check = false); + ResultCode HeapAllocate(VAddr* out_addr, VAddr target, u32 size, VMAPermission perms, + MemoryState memory_state = MemoryState::Private, + bool skip_range_check = false); ResultCode HeapFree(VAddr target, u32 size); - ResultVal LinearAllocate(VAddr target, u32 size, VMAPermission perms); + ResultCode LinearAllocate(VAddr* out_addr, VAddr target, u32 size, VMAPermission perms); ResultCode LinearFree(VAddr target, u32 size); ResultVal AllocateThreadLocalStorage(); diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 5e2412fe6..f023fe599 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -26,9 +26,7 @@ ResultVal> KernelSystem::CreateSemaphore(s32 initial_ s32 max_count, std::string name) { - if (initial_count > max_count) { - return ERR_INVALID_COMBINATION_KERNEL; - } + R_UNLESS(initial_count <= max_count, ERR_INVALID_COMBINATION_KERNEL); // When the semaphore is created, some slots are reserved for other threads, // and the rest is reserved for the caller thread @@ -44,21 +42,20 @@ bool Semaphore::ShouldWait(const Thread* thread) const { } void Semaphore::Acquire(Thread* thread) { - if (available_count <= 0) + if (available_count <= 0) { return; + } --available_count; } -ResultVal Semaphore::Release(s32 release_count) { - if (max_count - available_count < release_count) - return ERR_OUT_OF_RANGE_KERNEL; +ResultCode Semaphore::Release(s32* count, s32 release_count) { + R_UNLESS(max_count >= release_count + available_count, ERR_OUT_OF_RANGE_KERNEL); - s32 previous_count = available_count; + *count = available_count; available_count += release_count; - WakeupAllWaitingThreads(); - return previous_count; + return RESULT_SUCCESS; } } // namespace Kernel diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 2fa3b720b..abd864e16 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -47,7 +47,7 @@ public: * @param release_count The number of slots to release * @return The number of free slots the semaphore had before this call */ - ResultVal Release(s32 release_count); + ResultCode Release(s32* count, s32 release_count); private: friend class boost::serialization::access; diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index 721a029d8..57d411dea 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -24,14 +24,12 @@ namespace Kernel { ServerPort::ServerPort(KernelSystem& kernel) : WaitObject(kernel) {} ServerPort::~ServerPort() {} -ResultVal> ServerPort::Accept() { - if (pending_sessions.empty()) { - return ERR_NO_PENDING_SESSIONS; - } +ResultCode ServerPort::Accept(std::shared_ptr& session) { + R_UNLESS(!pending_sessions.empty(), ERR_NO_PENDING_SESSIONS); - auto session = std::move(pending_sessions.back()); + session = std::move(pending_sessions.back()); pending_sessions.pop_back(); - return session; + return RESULT_SUCCESS; } bool ServerPort::ShouldWait(const Thread* thread) const { diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index 00eb10100..f246527fa 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h @@ -41,7 +41,7 @@ public: * Accepts a pending incoming connection on this port. If there are no pending sessions, will * return ERR_NO_PENDING_SESSIONS. */ - ResultVal> Accept(); + ResultCode Accept(std::shared_ptr& session); /** * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a9a1a618f..6921b704d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -460,14 +460,11 @@ ResultCode SVC::ControlMemory(u32* out_addr, u32 addr0, u32 addr1, u32 size, u32 "size=0x{:X}, permissions=0x{:08X}", operation, addr0, addr1, size, permissions); - if ((addr0 & Memory::CITRA_PAGE_MASK) != 0 || (addr1 & Memory::CITRA_PAGE_MASK) != 0) { - return ERR_MISALIGNED_ADDRESS; - } - if ((size & Memory::CITRA_PAGE_MASK) != 0) { - return ERR_MISALIGNED_SIZE; - } + R_UNLESS((addr0 & Memory::CITRA_PAGE_MASK) == 0, ERR_MISALIGNED_ADDRESS); + R_UNLESS((addr1 & Memory::CITRA_PAGE_MASK) == 0, ERR_MISALIGNED_ADDRESS); + R_UNLESS((size & Memory::CITRA_PAGE_MASK) == 0, ERR_MISALIGNED_SIZE); - u32 region = operation & MEMOP_REGION_MASK; + const u32 region = operation & MEMOP_REGION_MASK; operation &= ~MEMOP_REGION_MASK; if (region != 0) { @@ -487,53 +484,37 @@ ResultCode SVC::ControlMemory(u32* out_addr, u32 addr0, u32 addr1, u32 size, u32 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a // SharedMemory pointing to it? if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { - ResultCode result = process.HeapFree(addr0, size); - if (result.IsError()) - return result; + R_TRY(process.HeapFree(addr0, size)); } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { - ResultCode result = process.LinearFree(addr0, size); - if (result.IsError()) - return result; + R_TRY(process.LinearFree(addr0, size)); } else { return ERR_INVALID_ADDRESS; } *out_addr = addr0; break; } - case MEMOP_COMMIT: { if (operation & MEMOP_LINEAR) { - CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); + return process.LinearAllocate(out_addr, addr0, size, vma_permissions); } else { - CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); + return process.HeapAllocate(out_addr, addr0, size, vma_permissions); } break; } - case MEMOP_MAP: { - CASCADE_CODE(process.Map(addr0, addr1, size, vma_permissions)); - break; + return process.Map(addr0, addr1, size, vma_permissions); } - case MEMOP_UNMAP: { - CASCADE_CODE(process.Unmap(addr0, addr1, size, vma_permissions)); - break; + return process.Unmap(addr0, addr1, size, vma_permissions); } - case MEMOP_PROTECT: { - ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); - if (result.IsError()) - return result; - break; + return process.vm_manager.ReprotectRange(addr0, size, vma_permissions); } - default: LOG_ERROR(Kernel_SVC, "unknown operation=0x{:08X}", operation); return ERR_INVALID_COMBINATION; } - process.vm_manager.LogLayout(Common::Log::Level::Trace); - return RESULT_SUCCESS; } @@ -544,9 +525,7 @@ void SVC::ExitProcess() { ResultCode SVC::TerminateProcess(Handle handle) { std::shared_ptr process = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (process == nullptr) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(process, ERR_INVALID_HANDLE); kernel.TerminateProcess(process); return RESULT_SUCCESS; @@ -561,8 +540,7 @@ ResultCode SVC::MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 oth std::shared_ptr shared_memory = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (shared_memory == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(shared_memory, ERR_INVALID_HANDLE); MemoryPermission permissions_type = static_cast(permissions); switch (permissions_type) { @@ -591,50 +569,39 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) { std::shared_ptr current_process = kernel.GetCurrentProcess(); std::shared_ptr shared_memory = current_process->handle_table.Get(handle); - if (shared_memory == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(shared_memory, ERR_INVALID_HANDLE); return shared_memory->Unmap(*current_process, addr); } /// Connect to an OS service given the port name, returns the handle to the port to out ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address)) { - return ERR_NOT_FOUND; - } + R_UNLESS(memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address), + ERR_NOT_FOUND); static constexpr std::size_t PortNameMaxLength = 11; // Read 1 char beyond the max allowed port name to detect names that are too long. std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1); - if (port_name.size() > PortNameMaxLength) { - return ERR_PORT_NAME_TOO_LONG; - } + R_UNLESS(port_name.size() <= PortNameMaxLength, ERR_PORT_NAME_TOO_LONG); LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); auto it = kernel.named_ports.find(port_name); - if (it == kernel.named_ports.end()) { - LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); - return ERR_NOT_FOUND; - } + R_UNLESS(it != kernel.named_ports.end(), ERR_NOT_FOUND); auto client_port = it->second; - std::shared_ptr client_session; - CASCADE_RESULT(client_session, client_port->Connect()); + R_TRY(client_port->Connect(client_session)); // Return the client session - CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(client_session)); - return RESULT_SUCCESS; + return kernel.GetCurrentProcess()->handle_table.Create(out_handle, client_session); } /// Makes a blocking IPC call to an OS service. ResultCode SVC::SendSyncRequest(Handle handle) { std::shared_ptr session = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (session == nullptr) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(session, ERR_INVALID_HANDLE); LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); @@ -655,42 +622,32 @@ ResultCode SVC::OpenProcess(Handle* out_handle, u32 process_id) { // Result 0xd9001818 (process not found?) return ResultCode(24, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); } - auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(process); - if (!result_handle) { - return result_handle.Code(); - } - *out_handle = result_handle.Unwrap(); - return RESULT_SUCCESS; + return kernel.GetCurrentProcess()->handle_table.Create(out_handle, process); } ResultCode SVC::OpenThread(Handle* out_handle, Handle process_handle, u32 thread_id) { + // Result 0xd9001819 (thread not found?) + constexpr static ResultCode ResultThreadNotFound( + 25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + if (process_handle == 0) { LOG_ERROR(Kernel_SVC, "Uninplemented svcOpenThread process_handle=0"); - // Result 0xd9001819 (thread not found?) - return ResultCode(25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return ResultThreadNotFound; } std::shared_ptr process = kernel.GetCurrentProcess()->handle_table.Get(process_handle); - if (!process) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(process, ERR_INVALID_HANDLE); for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) { const auto thread_list = kernel.GetThreadManager(core_id).GetThreadList(); for (auto& thread : thread_list) { if (thread->owner_process.lock() == process && thread.get()->thread_id == thread_id) { - auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(thread); - if (!result_handle) { - return result_handle.Code(); - } - *out_handle = result_handle.Unwrap(); - return RESULT_SUCCESS; + return kernel.GetCurrentProcess()->handle_table.Create(out_handle, thread); } } } - // Result 0xd9001819 (thread not found?) - return ResultCode(25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return ResultThreadNotFound; } /// Close a handle @@ -773,17 +730,13 @@ private: ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) { auto object = kernel.GetCurrentProcess()->handle_table.Get(handle); Thread* thread = kernel.GetCurrentThreadManager().GetCurrentThread(); - - if (object == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(object, ERR_INVALID_HANDLE); LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({}:{}), nanoseconds={}", handle, object->GetTypeName(), object->GetName(), nano_seconds); if (object->ShouldWait(thread)) { - - if (nano_seconds == 0) - return RESULT_TIMEOUT; + R_UNLESS(nano_seconds != 0, RESULT_TIMEOUT); thread->wait_objects = {object}; object->AddWaitingThread(SharedFrom(thread)); @@ -803,7 +756,6 @@ ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) { } object->Acquire(thread); - return RESULT_SUCCESS; } @@ -811,19 +763,15 @@ ResultCode SVC::WaitSynchronization1(Handle handle, s64 nano_seconds) { ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle_count, bool wait_all, s64 nano_seconds) { Thread* thread = kernel.GetCurrentThreadManager().GetCurrentThread(); - - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) { - return ERR_INVALID_POINTER; - } + R_UNLESS(memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address), + ERR_INVALID_POINTER); // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If // this happens, the running application will crash. ASSERT_MSG(out != nullptr, "invalid output pointer specified!"); // Check if 'handle_count' is invalid - if (handle_count < 0) { - return ERR_OUT_OF_RANGE; - } + R_UNLESS(handle_count >= 0, ERR_OUT_OF_RANGE); using ObjectPtr = std::shared_ptr; std::vector objects(handle_count); @@ -831,8 +779,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle for (int i = 0; i < handle_count; ++i) { Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); auto object = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (object == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(object, ERR_INVALID_HANDLE); objects[i] = object; } @@ -853,8 +800,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle // If a timeout value of 0 was provided, just return the Timeout error code instead of // suspending the thread. - if (nano_seconds == 0) - return RESULT_TIMEOUT; + R_UNLESS(nano_seconds != 0, RESULT_TIMEOUT); // Put the thread to sleep thread->status = ThreadStatus::WaitSynchAll; @@ -896,8 +842,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle // If a timeout value of 0 was provided, just return the Timeout error code instead of // suspending the thread. - if (nano_seconds == 0) - return RESULT_TIMEOUT; + R_UNLESS(nano_seconds != 0, RESULT_TIMEOUT); // Put the thread to sleep thread->status = ThreadStatus::WaitSynchAny; @@ -931,9 +876,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::MemorySystem& memory, std::shared_ptr server_session, std::shared_ptr thread) { - if (server_session->parent->client == nullptr) { - return ERR_SESSION_CLOSED_BY_REMOTE; - } + R_UNLESS(server_session->parent->client, ERR_SESSION_CLOSED_BY_REMOTE); VAddr target_address = thread->GetCommandBufferAddress(); VAddr source_address = server_session->currently_handling->GetCommandBufferAddress(); @@ -960,14 +903,11 @@ static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::Memory /// In a single operation, sends a IPC reply and waits for a new request. ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, Handle reply_target) { - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) { - return ERR_INVALID_POINTER; - } + R_UNLESS(memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address), + ERR_INVALID_POINTER); // Check if 'handle_count' is invalid - if (handle_count < 0) { - return ERR_OUT_OF_RANGE; - } + R_UNLESS(handle_count >= 0, ERR_OUT_OF_RANGE); using ObjectPtr = std::shared_ptr; std::vector objects(handle_count); @@ -977,8 +917,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co for (int i = 0; i < handle_count; ++i) { Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); auto object = current_process->handle_table.Get(handle); - if (object == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(object, ERR_INVALID_HANDLE); objects[i] = object; } @@ -989,8 +928,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co IPC::Header header{cmd_buff_header}; if (reply_target != 0 && header.command_id != 0xFFFF) { auto session = current_process->handle_table.Get(reply_target); - if (session == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(session, ERR_INVALID_HANDLE); auto request_thread = std::move(session->currently_handling); @@ -1021,12 +959,10 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co if (handle_count == 0) { *index = 0; + R_SUCCEED_IF(reply_target != 0 && header.command_id != 0xFFFF); // The kernel uses this value as a placeholder for the real error, and returns it when we // pass no handles and do not perform any reply. - if (reply_target == 0 || header.command_id == 0xFFFF) - return ResultCode(0xE7E3FFFF); - - return RESULT_SUCCESS; + return ResultCode(0xE7E3FFFF); } // Find the first object that is acquirable in the provided list of objects @@ -1040,8 +976,7 @@ ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_co object->Acquire(thread); *index = static_cast(std::distance(objects.begin(), itr)); - if (object->GetHandleType() != HandleType::ServerSession) - return RESULT_SUCCESS; + R_SUCCEED_IF(object->GetHandleType() != HandleType::ServerSession); auto server_session = static_cast(object); return ReceiveIPCRequest(kernel, memory, SharedFrom(server_session), SharedFrom(thread)); @@ -1084,9 +1019,7 @@ ResultCode SVC::CreateAddressArbiter(Handle* out_handle) { // Create address arbiter. const auto arbiter = kernel.CreateAddressArbiter(); arbiter->resource_limit = resource_limit; - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(arbiter))); - LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle); - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(arbiter)); } /// Arbitrate address @@ -1096,8 +1029,7 @@ ResultCode SVC::ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value std::shared_ptr arbiter = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (arbiter == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(arbiter, ERR_INVALID_HANDLE); auto res = arbiter->ArbitrateAddress(SharedFrom(kernel.GetCurrentThreadManager().GetCurrentThread()), @@ -1105,7 +1037,6 @@ ResultCode SVC::ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value // TODO(Subv): Identify in which specific cases this call should cause a reschedule. system.PrepareReschedule(); - return res; } @@ -1159,12 +1090,9 @@ ResultCode SVC::GetResourceLimit(Handle* resource_limit, Handle process_handle) std::shared_ptr current_process = kernel.GetCurrentProcess(); std::shared_ptr process = current_process->handle_table.Get(process_handle); - if (process == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(process, ERR_INVALID_HANDLE); - CASCADE_RESULT(*resource_limit, current_process->handle_table.Create(process->resource_limit)); - - return RESULT_SUCCESS; + return current_process->handle_table.Create(resource_limit, process->resource_limit); } /// Get resource limit current values @@ -1175,9 +1103,7 @@ ResultCode SVC::GetResourceLimitCurrentValues(VAddr values, Handle resource_limi const auto resource_limit = kernel.GetCurrentProcess()->handle_table.Get(resource_limit_handle); - if (!resource_limit) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(resource_limit, ERR_INVALID_HANDLE); for (u32 i = 0; i < name_count; ++i) { const u32 name = memory.Read32(names + i * sizeof(u32)); @@ -1196,15 +1122,11 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_ const auto resource_limit = kernel.GetCurrentProcess()->handle_table.Get(resource_limit_handle); - if (!resource_limit) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(resource_limit, ERR_INVALID_HANDLE); for (u32 i = 0; i < name_count; ++i) { const auto name = static_cast(memory.Read32(names + i * sizeof(u32))); - if (name >= ResourceLimitType::Max) { - return ERR_INVALID_ENUM_VALUE; - } + R_UNLESS(name < ResourceLimitType::Max, ERR_INVALID_ENUM_VALUE); const s64 value = resource_limit->GetLimitValue(name); memory.Write64(values + i * sizeof(u64), value); } @@ -1219,20 +1141,16 @@ ResultCode SVC::SetResourceLimitLimitValues(Handle res_limit, VAddr names, VAddr const auto resource_limit = kernel.GetCurrentProcess()->handle_table.Get(res_limit); - if (!resource_limit) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(resource_limit, ERR_INVALID_HANDLE); for (u32 i = 0; i < name_count; ++i) { const auto name = static_cast(memory.Read32(names + i * sizeof(u32))); - if (name >= ResourceLimitType::Max) { - return ERR_INVALID_ENUM_VALUE; - } + R_UNLESS(name < ResourceLimitType::Max, ERR_INVALID_ENUM_VALUE); + const s64 value = memory.Read64(resource_list + i * sizeof(u64)); const s32 value_high = value >> 32; - if (value_high < 0) { - return ERR_OUT_OF_RANGE_KERNEL; - } + R_UNLESS(value_high >= 0, ERR_OUT_OF_RANGE_KERNEL); + if (name == ResourceLimitType::Commit && value_high != 0) { auto& config_mem = kernel.GetConfigMemHandler().GetConfigMem(); config_mem.app_mem_alloc = value_high; @@ -1246,18 +1164,13 @@ ResultCode SVC::SetResourceLimitLimitValues(Handle res_limit, VAddr names, VAddr /// Creates a new thread ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr stack_top, u32 priority, s32 processor_id) { - std::string name = fmt::format("thread-{:08X}", entry_point); - - if (priority > ThreadPrioLowest) { - return ERR_OUT_OF_RANGE; - } + R_UNLESS(priority <= ThreadPrioLowest, ERR_OUT_OF_RANGE); const auto current_process = kernel.GetCurrentProcess(); const auto& resource_limit = current_process->resource_limit; const u32 max_priority = resource_limit->GetLimitValue(ResourceLimitType::Priority); - if (max_priority > priority && !current_process->no_thread_restrictions) { - return ERR_NOT_AUTHORIZED; - } + R_UNLESS(max_priority <= priority || current_process->no_thread_restrictions, + ERR_NOT_AUTHORIZED); if (processor_id == ThreadProcessorIdDefault) { // Set the target CPU to the one specified in the process' exheader. @@ -1294,6 +1207,7 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr } // Create thread. + const std::string name = fmt::format("thread-{:08X}", entry_point); CASCADE_RESULT(std::shared_ptr thread, kernel.CreateThread(name, entry_point, priority, arg, processor_id, stack_top, current_process)); @@ -1301,16 +1215,14 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(thread))); - system.PrepareReschedule(); LOG_TRACE(Kernel_SVC, "called entrypoint=0x{:08X} ({}), arg=0x{:08X}, stacktop=0x{:08X}, " - "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", - entry_point, name, arg, stack_top, priority, processor_id, *out_handle); + "threadpriority=0x{:08X}, processorid=0x{:08X}", + entry_point, name, arg, stack_top, priority, processor_id); - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(thread)); } /// Called when a thread exits @@ -1325,8 +1237,7 @@ void SVC::ExitThread() { ResultCode SVC::GetThreadPriority(u32* priority, Handle handle) { const std::shared_ptr thread = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (thread == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(thread, ERR_INVALID_HANDLE); *priority = thread->GetPriority(); return RESULT_SUCCESS; @@ -1334,22 +1245,16 @@ ResultCode SVC::GetThreadPriority(u32* priority, Handle handle) { /// Sets the priority for the specified thread ResultCode SVC::SetThreadPriority(Handle handle, u32 priority) { - if (priority > ThreadPrioLowest) { - return ERR_OUT_OF_RANGE; - } + R_UNLESS(priority <= ThreadPrioLowest, ERR_OUT_OF_RANGE); const auto thread = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (!thread) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(thread, ERR_INVALID_HANDLE); // Note: The kernel uses the current process's resource limit instead of // the one from the thread owner's resource limit. const auto& resource_limit = kernel.GetCurrentProcess()->resource_limit; const u32 max_priority = resource_limit->GetLimitValue(ResourceLimitType::Priority); - if (max_priority > priority) { - return ERR_NOT_AUTHORIZED; - } + R_UNLESS(max_priority <= priority, ERR_NOT_AUTHORIZED); thread->SetPriority(priority); thread->UpdatePriority(); @@ -1377,12 +1282,7 @@ ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) { const auto mutex = kernel.CreateMutex(initial_locked != 0); mutex->name = fmt::format("mutex-{:08x}", system.GetRunningCore().GetReg(14)); mutex->resource_limit = resource_limit; - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(mutex))); - - LOG_TRACE(Kernel_SVC, "called initial_locked={} : created handle=0x{:08X}", - initial_locked ? "true" : "false", *out_handle); - - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(mutex)); } /// Release a mutex @@ -1390,8 +1290,7 @@ ResultCode SVC::ReleaseMutex(Handle handle) { LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle); std::shared_ptr mutex = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (mutex == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(mutex, ERR_INVALID_HANDLE); return mutex->Release(kernel.GetCurrentThreadManager().GetCurrentThread()); } @@ -1402,8 +1301,7 @@ ResultCode SVC::GetProcessId(u32* process_id, Handle process_handle) { const std::shared_ptr process = kernel.GetCurrentProcess()->handle_table.Get(process_handle); - if (process == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(process, ERR_INVALID_HANDLE); *process_id = process->process_id; return RESULT_SUCCESS; @@ -1415,8 +1313,7 @@ ResultCode SVC::GetProcessIdOfThread(u32* process_id, Handle thread_handle) { const std::shared_ptr thread = kernel.GetCurrentProcess()->handle_table.Get(thread_handle); - if (thread == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(thread, ERR_INVALID_HANDLE); const std::shared_ptr process = thread->owner_process.lock(); ASSERT_MSG(process != nullptr, "Invalid parent process for thread={:#010X}", thread_handle); @@ -1431,8 +1328,7 @@ ResultCode SVC::GetThreadId(u32* thread_id, Handle handle) { const std::shared_ptr thread = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (thread == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(thread, ERR_INVALID_HANDLE); *thread_id = thread->GetThreadId(); return RESULT_SUCCESS; @@ -1453,11 +1349,7 @@ ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_c kernel.CreateSemaphore(initial_count, max_count)); semaphore->name = fmt::format("semaphore-{:08x}", system.GetRunningCore().GetReg(14)); semaphore->resource_limit = resource_limit; - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(semaphore))); - - LOG_TRACE(Kernel_SVC, "called initial_count={}, max_count={}, created handle=0x{:08X}", - initial_count, max_count, *out_handle); - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(semaphore)); } /// Releases a certain number of slots in a semaphore @@ -1466,18 +1358,14 @@ ResultCode SVC::ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { std::shared_ptr semaphore = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (semaphore == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(semaphore, ERR_INVALID_HANDLE); - CASCADE_RESULT(*count, semaphore->Release(release_count)); - - return RESULT_SUCCESS; + return semaphore->Release(count, release_count); } /// Sets the kernel state ResultCode SVC::KernelSetState(u32 kernel_state, u32 varg1, u32 varg2) { switch (static_cast(kernel_state)) { - // This triggers a hardware reboot on real console, since this doesn't make sense // on emulator, we shutdown instead. case KernelState::KERNEL_STATE_REBOOT: @@ -1495,13 +1383,10 @@ ResultCode SVC::QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, Handle process_handle, u32 addr) { std::shared_ptr process = kernel.GetCurrentProcess()->handle_table.Get(process_handle); - if (process == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(process, ERR_INVALID_HANDLE); auto vma = process->vm_manager.FindVMA(addr); - - if (vma == process->vm_manager.vma_map.end()) - return ERR_INVALID_ADDRESS; + R_UNLESS(vma != process->vm_manager.vma_map.end(), ERR_INVALID_ADDRESS); auto permissions = vma->second.permissions; auto state = vma->second.meminfo_state; @@ -1549,18 +1434,12 @@ ResultCode SVC::CreateEvent(Handle* out_handle, u32 reset_type) { const auto name = fmt::format("event-{:08x}", system.GetRunningCore().GetReg(14)); const auto event = kernel.CreateEvent(static_cast(reset_type), name); event->resource_limit = resource_limit; - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(event))); - - LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, - *out_handle); - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(event)); } /// Duplicates a kernel handle ResultCode SVC::DuplicateHandle(Handle* out, Handle handle) { - CASCADE_RESULT(*out, kernel.GetCurrentProcess()->handle_table.Duplicate(handle)); - LOG_TRACE(Kernel_SVC, "duplicated 0x{:08X} to 0x{:08X}", handle, *out); - return RESULT_SUCCESS; + return kernel.GetCurrentProcess()->handle_table.Duplicate(out, handle); } /// Signals an event @@ -1568,11 +1447,9 @@ ResultCode SVC::SignalEvent(Handle handle) { LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle); std::shared_ptr evt = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (evt == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(evt, ERR_INVALID_HANDLE); evt->Signal(); - return RESULT_SUCCESS; } @@ -1581,8 +1458,7 @@ ResultCode SVC::ClearEvent(Handle handle) { LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle); std::shared_ptr evt = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (evt == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(evt, ERR_INVALID_HANDLE); evt->Clear(); return RESULT_SUCCESS; @@ -1602,11 +1478,7 @@ ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) { const auto name = fmt::format("timer-{:08x}", system.GetRunningCore().GetReg(14)); const auto timer = kernel.CreateTimer(static_cast(reset_type), name); timer->resource_limit = resource_limit; - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(timer))); - - LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type, - *out_handle); - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(timer)); } /// Clears a timer @@ -1614,8 +1486,7 @@ ResultCode SVC::ClearTimer(Handle handle) { LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); std::shared_ptr timer = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (timer == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(timer, ERR_INVALID_HANDLE); timer->Clear(); return RESULT_SUCCESS; @@ -1625,13 +1496,10 @@ ResultCode SVC::ClearTimer(Handle handle) { ResultCode SVC::SetTimer(Handle handle, s64 initial, s64 interval) { LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); - if (initial < 0 || interval < 0) { - return ERR_OUT_OF_RANGE_KERNEL; - } + R_UNLESS(initial >= 0 && interval >= 0, ERR_OUT_OF_RANGE_KERNEL); std::shared_ptr timer = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (timer == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(timer, ERR_INVALID_HANDLE); timer->Set(initial, interval); @@ -1643,11 +1511,9 @@ ResultCode SVC::CancelTimer(Handle handle) { LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle); std::shared_ptr timer = kernel.GetCurrentProcess()->handle_table.Get(handle); - if (timer == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(timer, ERR_INVALID_HANDLE); timer->Cancel(); - return RESULT_SUCCESS; } @@ -1659,8 +1525,9 @@ void SVC::SleepThread(s64 nanoseconds) { // Don't attempt to yield execution if there are no available threads to run, // this way we avoid a useless reschedule to the idle thread. - if (nanoseconds == 0 && !thread_manager.HaveReadyThreads()) + if (nanoseconds == 0 && !thread_manager.HaveReadyThreads()) { return; + } // Sleep current thread and check for next thread to schedule thread_manager.WaitCurrentThread_Sleep(); @@ -1683,10 +1550,8 @@ s64 SVC::GetSystemTick() { // Returns information of the specified handle ResultCode SVC::GetHandleInfo(s64* out, Handle handle, u32 type) { - std::shared_ptr KObject = kernel.GetCurrentProcess()->handle_table.GetGeneric(handle); - if (!KObject) { - return ERR_INVALID_HANDLE; - } + std::shared_ptr object = kernel.GetCurrentProcess()->handle_table.GetGeneric(handle); + R_UNLESS(object, ERR_INVALID_HANDLE); // Not initialized in real kernel, but we don't want to leak memory. s64 value = 0; @@ -1694,14 +1559,14 @@ ResultCode SVC::GetHandleInfo(s64* out, Handle handle, u32 type) { switch (static_cast(type)) { case HandleInfoType::KPROCESS_ELAPSED_TICKS: - process = DynamicObjectCast(KObject); + process = DynamicObjectCast(object); if (process) { value = process->creation_time_ticks; } break; case HandleInfoType::REFERENCE_COUNT: // This is the closest approximation we can get without a full KObject impl. - value = KObject.use_count() - 1; + value = object.use_count() - 1; break; // These values are stubbed in real kernel, they do nothing. @@ -1718,8 +1583,7 @@ ResultCode SVC::GetHandleInfo(s64* out, Handle handle, u32 type) { /// Creates a memory block at the specified address with the specified permissions and size ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, u32 other_permission) { - if (size % Memory::CITRA_PAGE_SIZE != 0) - return ERR_MISALIGNED_SIZE; + R_UNLESS(size % Memory::CITRA_PAGE_SIZE == 0, ERR_MISALIGNED_SIZE); std::shared_ptr shared_memory = nullptr; @@ -1737,9 +1601,10 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my } }; - if (!VerifyPermissions(static_cast(my_permission)) || - !VerifyPermissions(static_cast(other_permission))) - return ERR_INVALID_COMBINATION; + R_UNLESS(VerifyPermissions(static_cast(my_permission)), + ERR_INVALID_COMBINATION); + R_UNLESS(VerifyPermissions(static_cast(other_permission)), + ERR_INVALID_COMBINATION); // TODO(Subv): Processes with memory type APPLICATION are not allowed // to create memory blocks with addr = 0, any attempts to do so @@ -1770,64 +1635,56 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my kernel.CreateSharedMemory( current_process, size, static_cast(my_permission), static_cast(other_permission), addr, region)); - CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(shared_memory))); - - LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr); - return RESULT_SUCCESS; + return current_process->handle_table.Create(out_handle, std::move(shared_memory)); } ResultCode SVC::CreatePort(Handle* server_port, Handle* client_port, VAddr name_address, u32 max_sessions) { // TODO(Subv): Implement named ports. ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented"); + LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions); std::shared_ptr current_process = kernel.GetCurrentProcess(); auto [server, client] = kernel.CreatePortPair(max_sessions); - CASCADE_RESULT(*client_port, current_process->handle_table.Create(std::move(client))); + R_TRY(current_process->handle_table.Create(client_port, std::move(client))); // 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(server))); - - LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions); - return RESULT_SUCCESS; + return current_process->handle_table.Create(server_port, std::move(server)); } ResultCode SVC::CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) { std::shared_ptr current_process = kernel.GetCurrentProcess(); std::shared_ptr client_port = current_process->handle_table.Get(client_port_handle); - if (client_port == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(client_port, ERR_INVALID_HANDLE); - CASCADE_RESULT(auto session, client_port->Connect()); - CASCADE_RESULT(*out_client_session, current_process->handle_table.Create(std::move(session))); - return RESULT_SUCCESS; + std::shared_ptr session; + R_TRY(client_port->Connect(session)); + + return current_process->handle_table.Create(out_client_session, std::move(session)); } ResultCode SVC::CreateSession(Handle* server_session, Handle* client_session) { auto [server, client] = kernel.CreateSessionPair(); + LOG_TRACE(Kernel_SVC, "called"); std::shared_ptr current_process = kernel.GetCurrentProcess(); + R_TRY(current_process->handle_table.Create(server_session, std::move(server))); - CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server))); - - CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client))); - - LOG_TRACE(Kernel_SVC, "called"); - return RESULT_SUCCESS; + return current_process->handle_table.Create(client_session, std::move(client)); } ResultCode SVC::AcceptSession(Handle* out_server_session, Handle server_port_handle) { std::shared_ptr current_process = kernel.GetCurrentProcess(); std::shared_ptr server_port = current_process->handle_table.Get(server_port_handle); - if (server_port == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(server_port, ERR_INVALID_HANDLE); - CASCADE_RESULT(auto session, server_port->Accept()); - CASCADE_RESULT(*out_server_session, current_process->handle_table.Create(std::move(session))); - return RESULT_SUCCESS; + std::shared_ptr session; + R_TRY(server_port->Accept(session)); + + return current_process->handle_table.Create(out_server_session, std::move(session)); } static void CopyStringPart(char* out, const char* in, size_t offset, size_t max_length) { @@ -1943,8 +1800,7 @@ ResultCode SVC::GetProcessInfo(s64* out, Handle process_handle, u32 type) { std::shared_ptr process = kernel.GetCurrentProcess()->handle_table.Get(process_handle); - if (process == nullptr) - return ERR_INVALID_HANDLE; + R_UNLESS(process, ERR_INVALID_HANDLE); switch (static_cast(type)) { case ProcessInfoType::PRIVATE_AND_SHARED_USED_MEMORY: @@ -1979,7 +1835,7 @@ ResultCode SVC::GetProcessInfo(s64* out, Handle process_handle, u32 type) { // Here start the custom ones, taken from Luma3DS for 3GX support case ProcessInfoType::LUMA_CUSTOM_PROCESS_NAME: // Get process name - strncpy(reinterpret_cast(out), process->codeset->GetName().c_str(), 8); + std::strncpy(reinterpret_cast(out), process->codeset->GetName().c_str(), 8); break; case ProcessInfoType::LUMA_CUSTOM_PROCESS_TITLE_ID: // Get process TID @@ -2017,9 +1873,7 @@ ResultCode SVC::GetThreadInfo(s64* out, Handle thread_handle, u32 type) { std::shared_ptr thread = kernel.GetCurrentProcess()->handle_table.Get(thread_handle); - if (thread == nullptr) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(thread, ERR_INVALID_HANDLE); switch (type) { case 0x10000: @@ -2035,9 +1889,8 @@ ResultCode SVC::GetThreadInfo(s64* out, Handle thread_handle, u32 type) { ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array, s32 out_process_array_count) { - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), out_process_array)) { - return ERR_INVALID_POINTER; - } + R_UNLESS(memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), out_process_array), + ERR_INVALID_POINTER); s32 written = 0; for (const auto& process : kernel.GetProcessList()) { @@ -2080,9 +1933,7 @@ ResultCode SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address, std::shared_ptr src_process = kernel.GetCurrentProcess()->handle_table.Get(src_process_handle); - if (dst_process == nullptr || src_process == nullptr) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(dst_process && src_process, ERR_INVALID_HANDLE); if (size & 0xFFF) { size = (size & ~0xFFF) + Memory::CITRA_PAGE_SIZE; @@ -2090,16 +1941,13 @@ ResultCode SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address, // Only linear memory supported auto vma = src_process->vm_manager.FindVMA(src_address); - if (vma == src_process->vm_manager.vma_map.end() || - vma->second.type != VMAType::BackingMemory || - vma->second.meminfo_state != MemoryState::Continuous) { - return ERR_INVALID_ADDRESS; - } + R_UNLESS(vma != src_process->vm_manager.vma_map.end() && + vma->second.type == VMAType::BackingMemory && + vma->second.meminfo_state == MemoryState::Continuous, + ERR_INVALID_ADDRESS); - u32 offset = src_address - vma->second.base; - if (offset + size > vma->second.size) { - return ERR_INVALID_ADDRESS; - } + const u32 offset = src_address - vma->second.base; + R_UNLESS(offset + size <= vma->second.size, ERR_INVALID_ADDRESS); auto vma_res = dst_process->vm_manager.MapBackingMemory( dst_address, @@ -2110,18 +1958,15 @@ ResultCode SVC::MapProcessMemoryEx(Handle dst_process_handle, u32 dst_address, if (!vma_res.Succeeded()) { return ERR_INVALID_ADDRESS_STATE; } - dst_process->vm_manager.Reprotect(vma_res.Unwrap(), Kernel::VMAPermission::ReadWriteExecute); + dst_process->vm_manager.Reprotect(vma_res.Unwrap(), Kernel::VMAPermission::ReadWriteExecute); return RESULT_SUCCESS; } ResultCode SVC::UnmapProcessMemoryEx(Handle process, u32 dst_address, u32 size) { std::shared_ptr dst_process = kernel.GetCurrentProcess()->handle_table.Get(process); - - if (dst_process == nullptr) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(dst_process, ERR_INVALID_HANDLE); if (size & 0xFFF) { size = (size & ~0xFFF) + Memory::CITRA_PAGE_SIZE; @@ -2129,11 +1974,10 @@ ResultCode SVC::UnmapProcessMemoryEx(Handle process, u32 dst_address, u32 size) // Only linear memory supported auto vma = dst_process->vm_manager.FindVMA(dst_address); - if (vma == dst_process->vm_manager.vma_map.end() || - vma->second.type != VMAType::BackingMemory || - vma->second.meminfo_state != MemoryState::Continuous) { - return ERR_INVALID_ADDRESS; - } + R_UNLESS(vma != dst_process->vm_manager.vma_map.end() && + vma->second.type == VMAType::BackingMemory && + vma->second.meminfo_state == MemoryState::Continuous, + ERR_INVALID_ADDRESS); dst_process->vm_manager.UnmapRange(dst_address, size); return RESULT_SUCCESS; @@ -2142,10 +1986,7 @@ ResultCode SVC::UnmapProcessMemoryEx(Handle process, u32 dst_address, u32 size) ResultCode SVC::ControlProcess(Handle process_handle, u32 process_OP, u32 varg2, u32 varg3) { std::shared_ptr process = kernel.GetCurrentProcess()->handle_table.Get(process_handle); - - if (process == nullptr) { - return ERR_INVALID_HANDLE; - } + R_UNLESS(process, ERR_INVALID_HANDLE); switch (static_cast(process_OP)) { case ControlProcessOP::PROCESSOP_SET_MMU_TO_RWX: { @@ -2158,9 +1999,7 @@ ResultCode SVC::ControlProcess(Handle process_handle, u32 process_OP, u32 varg2, } case ControlProcessOP::PROCESSOP_GET_ON_MEMORY_CHANGE_EVENT: { auto plgldr = Service::PLGLDR::GetService(system); - if (!plgldr) { - return ERR_NOT_FOUND; - } + R_UNLESS(plgldr, ERR_NOT_FOUND); ResultVal out = plgldr->GetMemoryChangedHandle(kernel); if (out.Failed()) { diff --git a/src/core/hle/result.h b/src/core/hle/result.h index a1adaeeaa..82bac490e 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -408,3 +408,29 @@ private: auto CONCAT2(check_result_L, __LINE__) = source; \ if (CONCAT2(check_result_L, __LINE__).IsError()) \ return CONCAT2(check_result_L, __LINE__); + +#define R_SUCCEEDED(res) (static_cast(res).IsSuccess()) +#define R_FAILED(res) (static_cast(res).IsError()) + +/// Evaluates a boolean expression, and returns a result unless that expression is true. +#define R_UNLESS(expr, res) \ + { \ + if (!(expr)) { \ + return (res); \ + } \ + } + +/// Evaluates an expression that returns a result, and returns the result if it would fail. +#define R_TRY(res_expr) \ + { \ + const auto _tmp_r_try_rc = (res_expr); \ + if (R_FAILED(_tmp_r_try_rc)) { \ + return (_tmp_r_try_rc); \ + } \ + } + +/// Evaluates a boolean expression, and succeeds if that expression is true. +#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), RESULT_SUCCESS) + +/// Evaluates a boolean expression, and asserts if that expression is false. +#define R_ASSERT(expr) ASSERT(R_SUCCEEDED(expr)) diff --git a/src/core/hle/service/plgldr/plgldr.cpp b/src/core/hle/service/plgldr/plgldr.cpp index dd8fe7b6f..22827f6b8 100644 --- a/src/core/hle/service/plgldr/plgldr.cpp +++ b/src/core/hle/service/plgldr/plgldr.cpp @@ -130,21 +130,22 @@ void PLG_LDR::OnProcessExit(Kernel::Process& process, Kernel::KernelSystem& kern } ResultVal PLG_LDR::GetMemoryChangedHandle(Kernel::KernelSystem& kernel) { - if (plgldr_context.memory_changed_handle) + if (plgldr_context.memory_changed_handle) { return plgldr_context.memory_changed_handle; + } std::shared_ptr evt = kernel.CreateEvent( Kernel::ResetType::OneShot, fmt::format("event-{:08x}", Core::System::GetInstance().GetRunningCore().GetReg(14))); - CASCADE_RESULT(plgldr_context.memory_changed_handle, - kernel.GetCurrentProcess()->handle_table.Create(std::move(evt))); - + R_TRY(kernel.GetCurrentProcess()->handle_table.Create( + std::addressof(plgldr_context.memory_changed_handle), std::move(evt))); return plgldr_context.memory_changed_handle; } void PLG_LDR::OnMemoryChanged(Kernel::Process& process, Kernel::KernelSystem& kernel) { - if (!plgldr_context.plugin_loaded || !plgldr_context.memory_changed_handle) + if (!plgldr_context.plugin_loaded || !plgldr_context.memory_changed_handle) { return; + } std::shared_ptr evt = kernel.GetCurrentProcess()->handle_table.Get( diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 1e4c071f2..daa3bef4b 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -130,7 +130,8 @@ ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_ses ServiceFrameworkBase::~ServiceFrameworkBase() = default; void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) { - auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap(); + std::shared_ptr port; + R_ASSERT(service_manager.RegisterService(port, service_name, max_sessions)); port->SetHleHandler(shared_from_this()); } diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 25ca1d248..a60b4b07e 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -13,12 +13,8 @@ namespace Service::SM { static ResultCode ValidateServiceName(const std::string& name) { - if (name.size() <= 0 || name.size() > 8) { - return ERR_INVALID_NAME_SIZE; - } - if (name.find('\0') != std::string::npos) { - return ERR_NAME_CONTAINS_NUL; - } + R_UNLESS(name.size() > 0 && name.size() <= 8, ERR_INVALID_NAME_SIZE); + R_UNLESS(name.find('\0') == std::string::npos, ERR_NAME_CONTAINS_NUL); return RESULT_SUCCESS; } @@ -32,38 +28,35 @@ void ServiceManager::InstallInterfaces(Core::System& system) { system.ServiceManager().srv_interface = srv; } -ResultVal> ServiceManager::RegisterService( - std::string name, unsigned int max_sessions) { - - CASCADE_CODE(ValidateServiceName(name)); - - if (registered_services.find(name) != registered_services.end()) - return ERR_ALREADY_REGISTERED; - - auto [server_port, client_port] = system.Kernel().CreatePortPair(max_sessions, name); +ResultCode ServiceManager::RegisterService(std::shared_ptr& server_port, + std::string name, u32 max_sessions) { + R_TRY(ValidateServiceName(name)); + R_UNLESS(registered_services.find(name) == registered_services.end(), ERR_ALREADY_REGISTERED); + std::shared_ptr client_port; + std::tie(server_port, client_port) = system.Kernel().CreatePortPair(max_sessions, name); registered_services_inverse.emplace(client_port->GetObjectId(), name); registered_services.emplace(std::move(name), std::move(client_port)); - return server_port; + + return RESULT_SUCCESS; } -ResultVal> ServiceManager::GetServicePort( - const std::string& name) { +ResultCode ServiceManager::GetServicePort(std::shared_ptr& out_port, + const std::string& name) { + R_TRY(ValidateServiceName(name)); - CASCADE_CODE(ValidateServiceName(name)); auto it = registered_services.find(name); - if (it == registered_services.end()) { - return ERR_SERVICE_NOT_REGISTERED; - } + R_UNLESS(it != registered_services.end(), ERR_SERVICE_NOT_REGISTERED); - return it->second; + out_port = it->second; + return RESULT_SUCCESS; } -ResultVal> ServiceManager::ConnectToService( - const std::string& name) { - - CASCADE_RESULT(auto client_port, GetServicePort(name)); - return client_port->Connect(); +ResultCode ServiceManager::ConnectToService(std::shared_ptr& session, + const std::string& name) { + std::shared_ptr client_port; + R_TRY(GetServicePort(client_port, name)); + return client_port->Connect(session); } std::string ServiceManager::GetServiceNameByPortId(u32 port) const { diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 659e14afb..9ea32065f 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -51,10 +51,12 @@ public: explicit ServiceManager(Core::System& system); - ResultVal> RegisterService(std::string name, - unsigned int max_sessions); - ResultVal> GetServicePort(const std::string& name); - ResultVal> ConnectToService(const std::string& name); + ResultCode RegisterService(std::shared_ptr& out_port, std::string name, + u32 max_sessions); + ResultCode GetServicePort(std::shared_ptr& out_port, + const std::string& name); + ResultCode ConnectToService(std::shared_ptr& out_session, + const std::string& name); // For IPC Recorder std::string GetServiceNameByPortId(u32 port) const; diff --git a/src/core/hle/service/sm/srv.cpp b/src/core/hle/service/sm/srv.cpp index 1960bb7e4..61c4cd456 100644 --- a/src/core/hle/service/sm/srv.cpp +++ b/src/core/hle/service/sm/srv.cpp @@ -94,22 +94,23 @@ public: void WakeUp(std::shared_ptr thread, Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { LOG_ERROR(Service_SRV, "called service={} wakeup", name); - auto client_port = system.ServiceManager().GetServicePort(name); + std::shared_ptr client_port; + R_ASSERT(system.ServiceManager().GetServicePort(client_port, name)); - auto session = client_port.Unwrap()->Connect(); - if (session.Succeeded()) { - LOG_DEBUG(Service_SRV, "called service={} -> session={}", name, - (*session)->GetObjectId()); + std::shared_ptr session; + auto result = client_port->Connect(session); + if (result.IsSuccess()) { + LOG_DEBUG(Service_SRV, "called service={} -> session={}", name, session->GetObjectId()); IPC::RequestBuilder rb(ctx, 0x5, 1, 2); - rb.Push(session.Code()); - rb.PushMoveObjects(std::move(session).Unwrap()); - } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED) { + rb.Push(result); + rb.PushMoveObjects(std::move(session)); + } else if (result == Kernel::ERR_MAX_CONNECTIONS_REACHED) { LOG_ERROR(Service_SRV, "called service={} -> ERR_MAX_CONNECTIONS_REACHED", name); UNREACHABLE(); } else { - LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, session.Code().raw); + LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, result.raw); IPC::RequestBuilder rb(ctx, 0x5, 1, 0); - rb.Push(session.Code()); + rb.Push(result); } } @@ -158,9 +159,10 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { auto get_handle = std::make_shared(system, name); - auto client_port = system.ServiceManager().GetServicePort(name); - if (client_port.Failed()) { - if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) { + std::shared_ptr client_port; + auto result = system.ServiceManager().GetServicePort(client_port, name); + if (result.IsError()) { + if (wait_until_available && result == ERR_SERVICE_NOT_REGISTERED) { LOG_INFO(Service_SRV, "called service={} delayed", name); std::shared_ptr get_service_handle_event = ctx.SleepClientThread("GetServiceHandle", std::chrono::nanoseconds(-1), get_handle); @@ -168,27 +170,27 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { return; } else { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(client_port.Code()); - LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, - client_port.Code().raw); + rb.Push(result); + LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, result.raw); return; } } - auto session = client_port.Unwrap()->Connect(); - if (session.Succeeded()) { - LOG_DEBUG(Service_SRV, "called service={} -> session={}", name, (*session)->GetObjectId()); + std::shared_ptr session; + result = client_port->Connect(session); + if (result.IsSuccess()) { + LOG_DEBUG(Service_SRV, "called service={} -> session={}", name, session->GetObjectId()); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - rb.Push(session.Code()); - rb.PushMoveObjects(std::move(session).Unwrap()); - } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && wait_until_available) { + rb.Push(result); + rb.PushMoveObjects(std::move(session)); + } else if (result == Kernel::ERR_MAX_CONNECTIONS_REACHED && wait_until_available) { LOG_WARNING(Service_SRV, "called service={} -> ERR_MAX_CONNECTIONS_REACHED", name); // TODO(Subv): Put the caller guest thread to sleep until this port becomes available again. UNIMPLEMENTED_MSG("Unimplemented wait until port {} is available.", name); } else { - LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, session.Code().raw); + LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, result.raw); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(session.Code()); + rb.Push(result); } } @@ -266,12 +268,13 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { std::string name(name_buf.data(), std::min(name_len, name_buf.size())); - auto port = system.ServiceManager().RegisterService(name, max_sessions); + std::shared_ptr port; + auto result = system.ServiceManager().RegisterService(port, name, max_sessions); - if (port.Failed()) { + if (result.IsError()) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(port.Code()); - LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, port.Code().raw); + rb.Push(result); + LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, result.raw); return; } @@ -283,7 +286,7 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); rb.Push(RESULT_SUCCESS); - rb.PushMoveObjects(port.Unwrap()); + rb.PushMoveObjects(std::move(port)); } SRV::SRV(Core::System& system) : ServiceFramework("srv:", 64), system(system) { diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp index e301fe306..e41754361 100644 --- a/src/tests/core/hle/kernel/hle_ipc.cpp +++ b/src/tests/core/hle/kernel/hle_ipc.cpp @@ -59,7 +59,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel SECTION("translates move handles") { auto a = MakeObject(kernel); - Handle a_handle = process->handle_table.Create(a).Unwrap(); + Handle a_handle; + process->handle_table.Create(std::addressof(a_handle), a); const u32_le input[]{ IPC::MakeHeader(0, 0, 2), IPC::MoveHandleDesc(1), @@ -75,7 +76,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel SECTION("translates copy handles") { auto a = MakeObject(kernel); - Handle a_handle = process->handle_table.Create(a).Unwrap(); + Handle a_handle; + process->handle_table.Create(std::addressof(a_handle), a); const u32_le input[]{ IPC::MakeHeader(0, 0, 2), IPC::CopyHandleDesc(1), @@ -93,13 +95,17 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel auto a = MakeObject(kernel); auto b = MakeObject(kernel); auto c = MakeObject(kernel); + Handle a_handle, b_handle, c_handle; + process->handle_table.Create(std::addressof(a_handle), a); + process->handle_table.Create(std::addressof(b_handle), b); + process->handle_table.Create(std::addressof(c_handle), c); const u32_le input[]{ IPC::MakeHeader(0, 0, 5), IPC::MoveHandleDesc(2), - process->handle_table.Create(a).Unwrap(), - process->handle_table.Create(b).Unwrap(), + a_handle, + b_handle, IPC::MoveHandleDesc(1), - process->handle_table.Create(c).Unwrap(), + c_handle, }; context.PopulateFromIncomingCommandBuffer(input, process); @@ -209,12 +215,14 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel REQUIRE(result.Code() == RESULT_SUCCESS); auto a = MakeObject(kernel); + Handle a_handle; + process->handle_table.Create(std::addressof(a_handle), a); const u32_le input[]{ IPC::MakeHeader(0, 2, 8), 0x12345678, 0xABCDEF00, IPC::MoveHandleDesc(1), - process->handle_table.Create(a).Unwrap(), + a_handle, IPC::CallingPidDesc(), 0, IPC::StaticBufferDesc(buffer_static.GetSize(), 0),