From 9a345de2bd73c280de16442f78a313c1b6bee84c Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 01:20:49 -0200 Subject: [PATCH 01/14] Kernel: Remove useless/duplicated comments; mark functions static --- src/core/hle/kernel/address_arbiter.cpp | 5 +---- src/core/hle/kernel/address_arbiter.h | 3 --- src/core/hle/kernel/event.cpp | 2 +- src/core/hle/kernel/mutex.cpp | 18 ++++-------------- src/core/hle/kernel/shared_memory.cpp | 10 +--------- src/core/hle/kernel/timer.cpp | 2 +- 6 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 9e855b0bf..2a66f8dd5 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -28,7 +28,6 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////// -/// Arbitrate an address ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) { AddressArbiter* object = Kernel::g_handle_table.Get(handle).get(); @@ -92,8 +91,7 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3 return RESULT_SUCCESS; } -/// Create an address arbiter -AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { +static AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { AddressArbiter* address_arbiter = new AddressArbiter; // TOOD(yuriks): Fix error reporting handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE); @@ -101,7 +99,6 @@ AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { return address_arbiter; } -/// Create an address arbiter Handle CreateAddressArbiter(const std::string& name) { Handle handle; CreateAddressArbiter(handle, name); diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 3ffd465a2..81084bdc8 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -18,7 +18,6 @@ namespace Kernel { -/// Address arbitration types enum class ArbitrationType : u32 { Signal, WaitIfLessThan, @@ -27,10 +26,8 @@ enum class ArbitrationType : u32 { DecrementAndWaitIfLessThanWithTimeout, }; -/// Arbitrate an address ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds); -/// Create an address arbiter Handle CreateAddressArbiter(const std::string& name = "Unknown"); } // namespace FileSys diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index a48125965..74df47a05 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -69,7 +69,7 @@ ResultCode ClearEvent(Handle handle) { * @param name Optional name of event * @return Newly created Event object */ -Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { +static Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { Event* evt = new Event; // TOOD(yuriks): Fix error reporting diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index cd05a1397..c94c2acc9 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -40,7 +40,7 @@ static MutexMap g_mutex_held_locks; * @param mutex Mutex that is to be acquired * @param thread Thread that will acquire the mutex */ -void MutexAcquireLock(Mutex* mutex, Thread* thread) { +static void MutexAcquireLock(Mutex* mutex, Thread* thread) { g_mutex_held_locks.insert(std::make_pair(thread, mutex)); mutex->holding_thread = thread; } @@ -49,7 +49,7 @@ void MutexAcquireLock(Mutex* mutex, Thread* thread) { * Resumes a thread waiting for the specified mutex * @param mutex The mutex that some thread is waiting on */ -void ResumeWaitingThread(Mutex* mutex) { +static void ResumeWaitingThread(Mutex* mutex) { // Find the next waiting thread for the mutex... auto next_thread = mutex->WakeupNextThread(); if (next_thread != nullptr) { @@ -73,7 +73,7 @@ void ReleaseThreadMutexes(Thread* thread) { g_mutex_held_locks.erase(thread); } -bool ReleaseMutex(Mutex* mutex) { +static bool ReleaseMutex(Mutex* mutex) { if (mutex->locked) { auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); @@ -89,10 +89,6 @@ bool ReleaseMutex(Mutex* mutex) { return true; } -/** - * Releases a mutex - * @param handle Handle to mutex to release - */ ResultCode ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_handle_table.Get(handle).get(); if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); @@ -113,7 +109,7 @@ ResultCode ReleaseMutex(Handle handle) { * @param name Optional name of mutex * @return Pointer to new Mutex object */ -Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { +static Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { Mutex* mutex = new Mutex; // TODO(yuriks): Fix error reporting handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE); @@ -129,12 +125,6 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) return mutex; } -/** - * Creates a mutex - * @param initial_locked Specifies if the mutex should be locked initially - * @param name Optional name of mutex - * @return Handle to newly created object - */ Handle CreateMutex(bool initial_locked, const std::string& name) { Handle handle; Mutex* mutex = CreateMutex(handle, initial_locked, name); diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 5368e4728..fa8fc6f92 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -30,7 +30,7 @@ public: * @param name Name of shared memory object * @return Pointer to newly created shared memory object */ -SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { +static SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { SharedMemory* shared_memory = new SharedMemory; // TOOD(yuriks): Fix error reporting handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE); @@ -44,14 +44,6 @@ Handle CreateSharedMemory(const std::string& name) { return handle; } -/** - * Maps a shared memory block to an address in system memory - * @param handle Shared memory block handle - * @param address Address in system memory to map shared memory block to - * @param permissions Memory block map permissions (specified by SVC field) - * @param other_permissions Memory block map other permissions (specified by SVC field) - * @return Result of operation, 0 on success, otherwise error code - */ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, MemoryPermission other_permissions) { diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index ec0b2c323..aee5dc599 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -45,7 +45,7 @@ public: * @param name Optional name of timer * @return Newly created Timer object */ -Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) { +static Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) { Timer* timer = new Timer; handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE); From b5ee4f9df9ad302355eb48f59e0a11723b639ada Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 01:56:28 -0200 Subject: [PATCH 02/14] Move VAddr/PAddr typedefs to kernel.h --- src/core/hle/kernel/kernel.h | 5 +++++ src/core/mem_map.h | 11 ++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3828efbea..08a5db3b7 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -16,6 +16,11 @@ typedef u32 Handle; typedef s32 Result; +// TODO: It would be nice to eventually replace these with strong types that prevent accidental +// conversion between each other. +typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space. +typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space. + const Handle INVALID_HANDLE = 0; namespace Kernel { diff --git a/src/core/mem_map.h b/src/core/mem_map.h index fad40ae0c..8f4f21fec 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h @@ -7,12 +7,9 @@ #include "common/common.h" #include "common/common_types.h" -namespace Memory { +#include "core/hle/kernel/kernel.h" -// TODO: It would be nice to eventually replace these with strong types that prevent accidental -// conversion between each other. -typedef u32 VAddr; ///< Represents a pointer in the ARM11 virtual address space. -typedef u32 PAddr; ///< Represents a pointer in the physical address space. +namespace Memory { //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -190,7 +187,3 @@ VAddr PhysicalToVirtualAddress(PAddr addr); PAddr VirtualToPhysicalAddress(VAddr addr); } // namespace - -// These are used often, so re-export then on the root namespace -using Memory::VAddr; -using Memory::PAddr; From afc416c6079f2db2c6cfae704de4c312907b3bb7 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 03:42:18 -0200 Subject: [PATCH 03/14] Additions to ResultVal to make it more convenient to use. --- src/core/hle/result.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 82dcf5bba..ad06d00aa 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -9,8 +9,9 @@ #include #include -#include "common/common_types.h" #include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" // All the constants in this file come from http://3dbrew.org/wiki/Error_codes @@ -364,6 +365,17 @@ public: return !empty() ? *GetPointer() : std::move(value); } + /// Asserts that the result succeeded and returns a reference to it. + T& Unwrap() { + // TODO(yuriks): Should be a release assert + _assert_msg_(Common, Succeeded(), "Tried to Unwrap empty ResultVal"); + return **this; + } + + T&& MoveFrom() { + return std::move(Unwrap()); + } + private: typedef typename std::aligned_storage::value>::type StorageType; @@ -400,3 +412,15 @@ template ResultVal MakeResult(Args&&... args) { return ResultVal::WithCode(RESULT_SUCCESS, std::forward(args)...); } + +/** + * Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps + * the contained value and assigns it to `target`, which can be either an l-value expression or a + * variable declaration. If it fails the return code is returned from the current function. Thus it + * can be used to cascade errors out, achieving something akin to exception handling. + */ +#define CASCADE_RESULT(target, source) \ + auto CONCAT2(check_result_L, __LINE__) = source; \ + if (CONCAT2(check_result_L, __LINE__).Failed()) \ + return CONCAT2(check_result_L, __LINE__).Code(); \ + target = std::move(*CONCAT2(check_result_L, __LINE__)) From fc11aff9559da4725037c21f7a4732f5f009d975 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 13:32:31 -0200 Subject: [PATCH 04/14] Common: Fix SCOPE_EXIT to actually create unique identifiers. --- src/common/common_funcs.h | 4 ++++ src/common/scope_exit.h | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index c2750a63c..229eb74c9 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -31,6 +31,10 @@ template<> struct CompileTimeAssert {}; #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +/// Textually concatenates two tokens. The double-expansion is required by the C preprocessor. +#define CONCAT2(x, y) DO_CONCAT2(x, y) +#define DO_CONCAT2(x, y) x ## y + #ifndef _MSC_VER #include diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h index 263beaf0e..77dcbaa22 100644 --- a/src/common/scope_exit.h +++ b/src/common/scope_exit.h @@ -4,6 +4,8 @@ #pragma once +#include "common/common_funcs.h" + namespace detail { template struct ScopeExitHelper { @@ -34,4 +36,4 @@ namespace detail { * } * \endcode */ -#define SCOPE_EXIT(body) auto scope_exit_helper_##__LINE__ = detail::ScopeExit([&]() body) +#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) From 4bb33dfc30768c536d3f0ffb980464b1ab2d25d9 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 03:43:29 -0200 Subject: [PATCH 05/14] Kernel: Convert SharedMemory to not use Handles --- src/core/hle/kernel/shared_memory.cpp | 65 ++++++++------------------- src/core/hle/kernel/shared_memory.h | 56 ++++++++++++++--------- src/core/hle/service/apt_u.cpp | 8 ++-- src/core/hle/service/gsp_gpu.cpp | 16 ++++--- src/core/hle/service/hid/hid.cpp | 6 +-- src/core/hle/service/hid/hid.h | 6 ++- src/core/hle/service/hid/hid_user.cpp | 4 +- src/core/hle/svc.cpp | 44 +++++++++++------- 8 files changed, 105 insertions(+), 100 deletions(-) diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index fa8fc6f92..536d134b0 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -9,68 +9,39 @@ namespace Kernel { -class SharedMemory : public Object { -public: - std::string GetTypeName() const override { return "SharedMemory"; } +ResultVal> SharedMemory::Create(std::string name) { + SharedPtr shared_memory(new SharedMemory); - static const HandleType HANDLE_TYPE = HandleType::SharedMemory; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory)); - u32 base_address; ///< Address of shared memory block in RAM - MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) - MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field) - std::string name; ///< Name of shared memory object (optional) -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -/** - * Creates a shared memory object - * @param handle Handle of newly created shared memory object - * @param name Name of shared memory object - * @return Pointer to newly created shared memory object - */ -static SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { - SharedMemory* shared_memory = new SharedMemory; - // TOOD(yuriks): Fix error reporting - handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE); - shared_memory->name = name; - return shared_memory; + shared_memory->name = std::move(name); + return MakeResult>(std::move(shared_memory)); } -Handle CreateSharedMemory(const std::string& name) { - Handle handle; - CreateSharedMemory(handle, name); - return handle; -} - -ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, - MemoryPermission other_permissions) { +ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, + MemoryPermission other_permissions) { if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { - LOG_ERROR(Kernel_SVC, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", - handle, address); + LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", + GetHandle(), address); + // TODO: Verify error code with hardware return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); } - SharedMemory* shared_memory = Kernel::g_handle_table.Get(handle).get(); - if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); - shared_memory->base_address = address; - shared_memory->permissions = permissions; - shared_memory->other_permissions = other_permissions; + base_address = address; + permissions = permissions; + other_permissions = other_permissions; return RESULT_SUCCESS; } -ResultVal GetSharedMemoryPointer(Handle handle, u32 offset) { - SharedMemory* shared_memory = Kernel::g_handle_table.Get(handle).get(); - if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); +ResultVal SharedMemory::GetPointer(u32 offset) { + if (base_address != 0) + return MakeResult(Memory::GetPointer(base_address + offset)); - if (0 != shared_memory->base_address) - return MakeResult(Memory::GetPointer(shared_memory->base_address + offset)); - - LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", handle); + LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle()); // TODO(yuriks): Verify error code. return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, ErrorSummary::InvalidState, ErrorLevel::Permanent); diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index bb65c7ccd..eb063d39d 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -23,29 +23,41 @@ enum class MemoryPermission : u32 { DontCare = (1u << 28) }; -/** - * Creates a shared memory object - * @param name Optional name of shared memory object - * @return Handle of newly created shared memory object - */ -Handle CreateSharedMemory(const std::string& name="Unknown"); +class SharedMemory : public Object { +public: + /** + * Creates a shared memory object + * @param name Optional object name, used only for debugging purposes. + */ + static ResultVal> Create(std::string name = "Unknown"); -/** - * Maps a shared memory block to an address in system memory - * @param handle Shared memory block handle - * @param address Address in system memory to map shared memory block to - * @param permissions Memory block map permissions (specified by SVC field) - * @param other_permissions Memory block map other permissions (specified by SVC field) - */ -ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions, - MemoryPermission other_permissions); + std::string GetTypeName() const override { return "SharedMemory"; } -/** - * Gets a pointer to the shared memory block - * @param handle Shared memory block handle - * @param offset Offset from the start of the shared memory block to get pointer - * @return Pointer to the shared memory block from the specified offset - */ -ResultVal GetSharedMemoryPointer(Handle handle, u32 offset); + static const HandleType HANDLE_TYPE = HandleType::SharedMemory; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + /** + * Maps a shared memory block to an address in system memory + * @param address Address in system memory to map shared memory block to + * @param permissions Memory block map permissions (specified by SVC field) + * @param other_permissions Memory block map other permissions (specified by SVC field) + */ + ResultCode Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); + + /** + * Gets a pointer to the shared memory block + * @param offset Offset from the start of the shared memory block to get pointer + * @return Pointer to the shared memory block from the specified offset + */ + ResultVal GetPointer(u32 offset = 0); + + VAddr base_address; ///< Address of shared memory block in RAM + MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) + MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field) + std::string name; ///< Name of shared memory object (optional) + +private: + SharedMemory() = default; +}; } // namespace diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 001b0d183..1f6b148e8 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -26,7 +26,7 @@ namespace APT_U { static const VAddr SHARED_FONT_VADDR = 0x18000000; /// Handle to shared memory region designated to for shared system font -static Handle shared_font_mem = 0; +static Kernel::SharedPtr shared_font_mem; static Handle lock_handle = 0; static Handle notification_event_handle = 0; ///< APT notification event handle @@ -354,7 +354,7 @@ void GetSharedFont(Service::Interface* self) { cmd_buff[0] = 0x00440082; cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = SHARED_FONT_VADDR; - cmd_buff[4] = shared_font_mem; + cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom(); } else { cmd_buff[1] = -1; // Generic error (not really possible to verify this on hardware) LOG_ERROR(Kernel_SVC, "called, but %s has not been loaded!", SHARED_FONT); @@ -514,10 +514,10 @@ Interface::Interface() { file.ReadBytes(shared_font.data(), (size_t)file.GetSize()); // Create shared font memory object - shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem"); + shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem").MoveFrom(); } else { LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); - shared_font_mem = 0; + shared_font_mem = nullptr; } lock_handle = 0; diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 4ca2b9bd0..1be2438c8 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -23,12 +23,12 @@ GraphicsDebugger g_debugger; namespace GSP_GPU { Handle g_interrupt_event = 0; ///< Handle to event triggered when GSP interrupt has been signalled -Handle g_shared_memory = 0; ///< Handle to GSP shared memorys +Kernel::SharedPtr g_shared_memory; ///< GSP shared memoryings u32 g_thread_id = 1; ///< Thread index into interrupt relay queue, 1 is arbitrary /// Gets a pointer to a thread command buffer in GSP shared memory static inline u8* GetCommandBuffer(u32 thread_id) { - ResultVal ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * sizeof(CommandBuffer))); + ResultVal ptr = g_shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer))); return ptr.ValueOr(nullptr); } @@ -37,13 +37,13 @@ static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_in // For each thread there are two FrameBufferUpdate fields u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); - ResultVal ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, offset); + ResultVal ptr = g_shared_memory->GetPointer(offset); return reinterpret_cast(ptr.ValueOr(nullptr)); } /// Gets a pointer to the interrupt relay queue for a given thread index static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { - ResultVal ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(InterruptRelayQueue) * thread_id); + ResultVal ptr = g_shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id); return reinterpret_cast(ptr.ValueOr(nullptr)); } @@ -182,13 +182,15 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 flags = cmd_buff[1]; g_interrupt_event = cmd_buff[3]; - g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem"); + g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); + Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); + cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init cmd_buff[2] = g_thread_id++; // Thread ID - cmd_buff[4] = g_shared_memory; // GSP shared memory + cmd_buff[4] = shmem_handle; // GSP shared memory Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct? } @@ -204,7 +206,7 @@ void SignalInterrupt(InterruptId interrupt_id) { LOG_WARNING(Service_GSP, "cannot synchronize until GSP event has been created!"); return; } - if (0 == g_shared_memory) { + if (nullptr == g_shared_memory) { LOG_WARNING(Service_GSP, "cannot synchronize until GSP shared memory has been created!"); return; } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 5abcb2596..ee2ba7e01 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -12,7 +12,7 @@ namespace Service { namespace HID { -Handle g_shared_mem = 0; +Kernel::SharedPtr g_shared_mem = nullptr; Handle g_event_pad_or_touch_1 = 0; Handle g_event_pad_or_touch_2 = 0; @@ -30,7 +30,7 @@ static s16 next_circle_y = 0; * Gets a pointer to the PadData structure inside HID shared memory */ static inline PadData* GetPadData() { - return reinterpret_cast(Kernel::GetSharedMemoryPointer(g_shared_mem, 0).ValueOr(nullptr)); + return reinterpret_cast(g_shared_mem->GetPointer().ValueOr(nullptr)); } /** @@ -120,7 +120,7 @@ void PadUpdateComplete() { } void HIDInit() { - g_shared_mem = Kernel::CreateSharedMemory("HID:SharedMem"); // Create shared memory object + g_shared_mem = Kernel::SharedMemory::Create("HID:SharedMem").MoveFrom(); // Create event handles g_event_pad_or_touch_1 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1"); diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 73cdaa527..5e6236647 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -9,11 +9,15 @@ #include "core/hle/kernel/kernel.h" #include "common/bit_field.h" +namespace Kernel { + class SharedMemory; +} + namespace Service { namespace HID { // Handle to shared memory region designated to HID_User service -extern Handle g_shared_mem; +extern Kernel::SharedPtr g_shared_mem; // Event handles extern Handle g_event_pad_or_touch_1; diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp index 3a6275707..c167927ea 100644 --- a/src/core/hle/service/hid/hid_user.cpp +++ b/src/core/hle/service/hid/hid_user.cpp @@ -5,6 +5,7 @@ #include "common/log.h" #include "core/hle/hle.h" +#include "core/hle/kernel/shared_memory.h" #include "core/hle/service/hid/hid.h" #include "hid_user.h" @@ -46,7 +47,8 @@ void GetIPCHandles(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = 0; // No error - cmd_buff[3] = Service::HID::g_shared_mem; + // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) + cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::g_shared_mem).MoveFrom(); cmd_buff[4] = Service::HID::g_event_pad_or_touch_1; cmd_buff[5] = Service::HID::g_event_pad_or_touch_2; cmd_buff[6] = Service::HID::g_event_accelerometer; diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 3d743f125..165da0402 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -63,21 +63,28 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, /// Maps a memory block to specified address static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { + using Kernel::SharedMemory; + using Kernel::MemoryPermission; + LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", handle, addr, permissions, other_permissions); - Kernel::MemoryPermission permissions_type = static_cast(permissions); + SharedPtr shared_memory = Kernel::g_handle_table.Get(handle); + if (shared_memory == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + MemoryPermission permissions_type = static_cast(permissions); switch (permissions_type) { - case Kernel::MemoryPermission::Read: - case Kernel::MemoryPermission::Write: - case Kernel::MemoryPermission::ReadWrite: - case Kernel::MemoryPermission::Execute: - case Kernel::MemoryPermission::ReadExecute: - case Kernel::MemoryPermission::WriteExecute: - case Kernel::MemoryPermission::ReadWriteExecute: - case Kernel::MemoryPermission::DontCare: - Kernel::MapSharedMemory(handle, addr, permissions_type, - static_cast(other_permissions)); + case MemoryPermission::Read: + case MemoryPermission::Write: + case MemoryPermission::ReadWrite: + case MemoryPermission::Execute: + case MemoryPermission::ReadExecute: + case MemoryPermission::WriteExecute: + case MemoryPermission::ReadWriteExecute: + case MemoryPermission::DontCare: + shared_memory->Map(addr, permissions_type, + static_cast(other_permissions)); break; default: LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); @@ -463,12 +470,19 @@ static s64 GetSystemTick() { /// Creates a memory block at the specified address with the specified permissions and size static Result CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, - u32 other_permission) { - + u32 other_permission) { + using Kernel::SharedMemory; // TODO(Subv): Implement this function - Handle shared_memory = Kernel::CreateSharedMemory(); - *memblock = shared_memory; + ResultVal> shared_memory_res = SharedMemory::Create(); + if (shared_memory_res.Failed()) + return shared_memory_res.Code().raw; + + ResultVal handle_res = Kernel::g_handle_table.Create(*shared_memory_res); + if (handle_res.Failed()) + return handle_res.Code().raw; + + *memblock = *handle_res; LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); return 0; } From d9b19be1d9c1baa5e8b92c1960c14e435e6b532f Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 13:53:11 -0200 Subject: [PATCH 06/14] Kernel: Convert Semaphore to not use Handles --- src/core/hle/kernel/semaphore.cpp | 65 +++++++++++-------------------- src/core/hle/kernel/semaphore.h | 55 ++++++++++++++++++-------- src/core/hle/svc.cpp | 33 +++++++++++++--- 3 files changed, 87 insertions(+), 66 deletions(-) diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 135d8fb2a..a9e406ef4 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include - #include "common/common.h" #include "core/hle/kernel/kernel.h" @@ -12,69 +10,50 @@ namespace Kernel { -class Semaphore : public WaitObject { -public: - std::string GetTypeName() const override { return "Semaphore"; } - std::string GetName() const override { return name; } - - static const HandleType HANDLE_TYPE = HandleType::Semaphore; - HandleType GetHandleType() const override { return HANDLE_TYPE; } - - s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have - s32 available_count; ///< Number of free slots left in the semaphore - std::string name; ///< Name of semaphore (optional) - - bool ShouldWait() override { - return available_count <= 0; - } - - void Acquire() override { - _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); - --available_count; - } -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -ResultCode CreateSemaphore(Handle* handle, s32 initial_count, - s32 max_count, const std::string& name) { +ResultVal> Semaphore::Create(s32 initial_count, s32 max_count, + std::string name) { if (initial_count > max_count) return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Permanent); - Semaphore* semaphore = new Semaphore; - // TOOD(yuriks): Fix error reporting - *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); + SharedPtr semaphore(new Semaphore); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); // When the semaphore is created, some slots are reserved for other threads, // and the rest is reserved for the caller thread semaphore->max_count = max_count; semaphore->available_count = initial_count; - semaphore->name = name; + semaphore->name = std::move(name); - return RESULT_SUCCESS; + return MakeResult>(std::move(semaphore)); } -ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { - Semaphore* semaphore = g_handle_table.Get(handle).get(); - if (semaphore == nullptr) - return InvalidHandle(ErrorModule::Kernel); +bool Semaphore::ShouldWait() { + return available_count <= 0; +} - if (semaphore->max_count - semaphore->available_count < release_count) +void Semaphore::Acquire() { + _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); + --available_count; +} + +ResultVal Semaphore::Release(s32 release_count) { + if (max_count - available_count < release_count) return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); - *count = semaphore->available_count; - semaphore->available_count += release_count; + s32 previous_count = available_count; + available_count += release_count; // Notify some of the threads that the semaphore has been released // stop once the semaphore is full again or there are no more waiting threads - while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { - semaphore->Acquire(); + while (!ShouldWait() && WakeupNextThread() != nullptr) { + Acquire(); } - return RESULT_SUCCESS; + return MakeResult(previous_count); } } // namespace diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 8644ecf0c..b7f22b86e 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -4,29 +4,50 @@ #pragma once +#include +#include + #include "common/common_types.h" #include "core/hle/kernel/kernel.h" namespace Kernel { -/** - * Creates a semaphore. - * @param handle Pointer to the handle of the newly created object - * @param initial_count Number of slots reserved for other threads - * @param max_count Maximum number of slots the semaphore can have - * @param name Optional name of semaphore - * @return ResultCode of the error - */ -ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); +class Semaphore : public WaitObject { +public: + /** + * Creates a semaphore. + * @param handle Pointer to the handle of the newly created object + * @param initial_count Number of slots reserved for other threads + * @param max_count Maximum number of slots the semaphore can have + * @param name Optional name of semaphore + * @return The created semaphore + */ + static ResultVal> Create(s32 initial_count, s32 max_count, + std::string name = "Unknown"); -/** - * Releases a certain number of slots from a semaphore. - * @param count The number of free slots the semaphore had before this call - * @param handle The handle of the semaphore to release - * @param release_count The number of slots to release - * @return ResultCode of the error - */ -ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); + std::string GetTypeName() const override { return "Semaphore"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::Semaphore; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have + s32 available_count; ///< Number of free slots left in the semaphore + std::string name; ///< Name of semaphore (optional) + + bool ShouldWait() override; + void Acquire() override; + + /** + * Releases a certain number of slots from a semaphore. + * @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); + +private: + Semaphore() = default; +}; } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 165da0402..6cbe38bc3 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -374,17 +374,38 @@ static Result GetThreadId(u32* thread_id, Handle handle) { /// Creates a semaphore static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { - ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); + using Kernel::Semaphore; + + ResultVal> semaphore_res = Semaphore::Create(initial_count, max_count); + if (semaphore_res.Failed()) + return semaphore_res.Code().raw; + + ResultVal handle_res = Kernel::g_handle_table.Create(*semaphore_res); + if (handle_res.Failed()) + return handle_res.Code().raw; + + *semaphore = *handle_res; LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", initial_count, max_count, *semaphore); - return res.raw; + return RESULT_SUCCESS.raw; } /// Releases a certain number of slots in a semaphore -static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { - LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); - ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); - return res.raw; +static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { + using Kernel::Semaphore; + + LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); + + SharedPtr semaphore = Kernel::g_handle_table.Get(handle); + if (semaphore == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + ResultVal release_res = semaphore->Release(release_count); + if (release_res.Failed()) + return release_res.Code().raw; + + *count = *release_res; + return RESULT_SUCCESS.raw; } /// Query memory From 38e7122f23424d40e0555fa40daeff55e23e4da4 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 11 Jan 2015 14:46:49 -0200 Subject: [PATCH 07/14] Kernel: Convert AddressArbiter to not use Handles --- src/core/hle/kernel/address_arbiter.cpp | 39 ++++++------------------- src/core/hle/kernel/address_arbiter.h | 24 +++++++++++++-- src/core/hle/svc.cpp | 30 +++++++++++++++---- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 2a66f8dd5..2d01e2ef5 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -15,25 +15,18 @@ namespace Kernel { -class AddressArbiter : public Object { -public: - std::string GetTypeName() const override { return "Arbiter"; } - std::string GetName() const override { return name; } +ResultVal> AddressArbiter::Create(std::string name) { + SharedPtr address_arbiter(new AddressArbiter); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter)); - static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; - HandleType GetHandleType() const override { return HANDLE_TYPE; } + address_arbiter->name = std::move(name); - std::string name; ///< Name of address arbiter object (optional) -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) { - AddressArbiter* object = Kernel::g_handle_table.Get(handle).get(); - - if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return MakeResult>(std::move(address_arbiter)); +} +ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, + u64 nanoseconds) { switch (type) { // Signal thread(s) waiting for arbitrate address... @@ -91,18 +84,4 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3 return RESULT_SUCCESS; } -static AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { - AddressArbiter* address_arbiter = new AddressArbiter; - // TOOD(yuriks): Fix error reporting - handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE); - address_arbiter->name = name; - return address_arbiter; -} - -Handle CreateAddressArbiter(const std::string& name) { - Handle handle; - CreateAddressArbiter(handle, name); - return handle; -} - } // namespace Kernel diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 81084bdc8..536f0f017 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -26,8 +26,28 @@ enum class ArbitrationType : u32 { DecrementAndWaitIfLessThanWithTimeout, }; -ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds); +class AddressArbiter : public Object { +public: + /** + * Creates an address arbiter. + * + * @param name Optional name used for debugging. + * @returns The created AddressArbiter. + */ + static ResultVal> Create(std::string name = "Unknown"); -Handle CreateAddressArbiter(const std::string& name = "Unknown"); + std::string GetTypeName() const override { return "Arbiter"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + std::string name; ///< Name of address arbiter object (optional) + + ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); + +private: + AddressArbiter() = default; +}; } // namespace FileSys diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 6cbe38bc3..b093d0368 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -247,16 +247,34 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, /// Create an address arbiter (to allocate access to shared resources) static Result CreateAddressArbiter(u32* arbiter) { - Handle handle = Kernel::CreateAddressArbiter(); - *arbiter = handle; - return 0; + using Kernel::AddressArbiter; + + ResultVal> arbiter_res = AddressArbiter::Create(); + if (arbiter_res.Failed()) + return arbiter_res.Code().raw; + + ResultVal handle_res = Kernel::g_handle_table.Create(*arbiter_res); + if (handle_res.Failed()) + return handle_res.Code().raw; + + LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *handle_res); + + *arbiter = *handle_res; + return RESULT_SUCCESS.raw; } /// Arbitrate address -static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { - LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, +static Result ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { + using Kernel::AddressArbiter; + + LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, address, type, value); - return Kernel::ArbitrateAddress(arbiter, static_cast(type), + + SharedPtr arbiter = Kernel::g_handle_table.Get(handle); + if (arbiter == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + return arbiter->ArbitrateAddress(static_cast(type), address, value, nanoseconds).raw; } From 882b6fed75b7bf34809493482496e98c498a14e0 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Thu, 22 Jan 2015 23:12:19 -0200 Subject: [PATCH 08/14] Kernel: Convert Mutex to not use Handles --- src/core/hle/kernel/mutex.cpp | 131 +++++++++++---------------------- src/core/hle/kernel/mutex.h | 50 ++++++++++--- src/core/hle/service/apt_s.cpp | 1 + src/core/hle/service/apt_u.cpp | 16 ++-- src/core/hle/svc.cpp | 24 ++++-- 5 files changed, 109 insertions(+), 113 deletions(-) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index c94c2acc9..acf484659 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -13,59 +13,30 @@ namespace Kernel { -class Mutex : public WaitObject { -public: - std::string GetTypeName() const override { return "Mutex"; } - std::string GetName() const override { return name; } - - static const HandleType HANDLE_TYPE = HandleType::Mutex; - HandleType GetHandleType() const override { return HANDLE_TYPE; } - - bool initial_locked; ///< Initial lock state when mutex was created - bool locked; ///< Current locked state - std::string name; ///< Name of mutex (optional) - SharedPtr holding_thread; ///< Thread that has acquired the mutex - - bool ShouldWait() override; - void Acquire() override; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - typedef std::multimap, SharedPtr> MutexMap; static MutexMap g_mutex_held_locks; -/** - * Acquires the specified mutex for the specified thread - * @param mutex Mutex that is to be acquired - * @param thread Thread that will acquire the mutex - */ -static void MutexAcquireLock(Mutex* mutex, Thread* thread) { - g_mutex_held_locks.insert(std::make_pair(thread, mutex)); - mutex->holding_thread = thread; -} - /** * Resumes a thread waiting for the specified mutex * @param mutex The mutex that some thread is waiting on */ static void ResumeWaitingThread(Mutex* mutex) { + // Reset mutex lock thread handle, nothing is waiting + mutex->locked = false; + mutex->holding_thread = nullptr; + // Find the next waiting thread for the mutex... auto next_thread = mutex->WakeupNextThread(); if (next_thread != nullptr) { - MutexAcquireLock(mutex, next_thread); - } else { - // Reset mutex lock thread handle, nothing is waiting - mutex->locked = false; - mutex->holding_thread = nullptr; + mutex->Acquire(next_thread); } } void ReleaseThreadMutexes(Thread* thread) { - auto locked = g_mutex_held_locks.equal_range(thread); + auto locked_range = g_mutex_held_locks.equal_range(thread); // Release every mutex that the thread holds, and resume execution on the waiting threads - for (auto iter = locked.first; iter != locked.second; ++iter) { + for (auto iter = locked_range.first; iter != locked_range.second; ++iter) { ResumeWaitingThread(iter->second.get()); } @@ -73,62 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) { g_mutex_held_locks.erase(thread); } -static bool ReleaseMutex(Mutex* mutex) { - if (mutex->locked) { - auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); +ResultVal> Mutex::Create(bool initial_locked, std::string name) { + SharedPtr mutex(new Mutex); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex)); - for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { - if (iter->second == mutex) { - g_mutex_held_locks.erase(iter); - break; - } - } - - ResumeWaitingThread(mutex); - } - return true; -} - -ResultCode ReleaseMutex(Handle handle) { - Mutex* mutex = Kernel::g_handle_table.Get(handle).get(); - if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); - - if (!ReleaseMutex(mutex)) { - // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure - // what error condition this is supposed to be signaling. - return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel, - ErrorSummary::NothingHappened, ErrorLevel::Temporary); - } - return RESULT_SUCCESS; -} - -/** - * Creates a mutex - * @param handle Reference to handle for the newly created mutex - * @param initial_locked Specifies if the mutex should be locked initially - * @param name Optional name of mutex - * @return Pointer to new Mutex object - */ -static Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { - Mutex* mutex = new Mutex; - // TODO(yuriks): Fix error reporting - handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE); - - mutex->locked = mutex->initial_locked = initial_locked; - mutex->name = name; + mutex->initial_locked = initial_locked; + mutex->locked = false; + mutex->name = std::move(name); mutex->holding_thread = nullptr; // Acquire mutex with current thread if initialized as locked... - if (mutex->locked) - MutexAcquireLock(mutex, GetCurrentThread()); + if (initial_locked) + mutex->Acquire(); - return mutex; -} - -Handle CreateMutex(bool initial_locked, const std::string& name) { - Handle handle; - Mutex* mutex = CreateMutex(handle, initial_locked, name); - return handle; + return MakeResult>(mutex); } bool Mutex::ShouldWait() { @@ -136,9 +66,34 @@ bool Mutex::ShouldWait() { } void Mutex::Acquire() { + Acquire(GetCurrentThread()); +} + +void Mutex::Acquire(Thread* thread) { _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); + if (locked) + return; + locked = true; - MutexAcquireLock(this, GetCurrentThread()); + + g_mutex_held_locks.insert(std::make_pair(thread, this)); + holding_thread = thread; +} + +void Mutex::Release() { + if (!locked) + return; + + auto locked_range = g_mutex_held_locks.equal_range(holding_thread); + + for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) { + if (iter->second == this) { + g_mutex_held_locks.erase(iter); + break; + } + } + + ResumeWaitingThread(this); } } // namespace diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index bb8778c98..a6d822e60 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -4,25 +4,51 @@ #pragma once +#include + #include "common/common_types.h" #include "core/hle/kernel/kernel.h" namespace Kernel { -/** - * Releases a mutex - * @param handle Handle to mutex to release - */ -ResultCode ReleaseMutex(Handle handle); +class Thread; -/** - * Creates a mutex - * @param initial_locked Specifies if the mutex should be locked initially - * @param name Optional name of mutex - * @return Handle to newly created object - */ -Handle CreateMutex(bool initial_locked, const std::string& name="Unknown"); +class Mutex : public WaitObject { +public: + /** + * Creates a mutex. + * @param initial_locked Specifies if the mutex should be locked initially + * @param name Optional name of mutex + * @return Pointer to new Mutex object + */ + static ResultVal> Create(bool initial_locked, std::string name = "Unknown"); + + std::string GetTypeName() const override { return "Mutex"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::Mutex; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + bool initial_locked; ///< Initial lock state when mutex was created + bool locked; ///< Current locked state + std::string name; ///< Name of mutex (optional) + SharedPtr holding_thread; ///< Thread that has acquired the mutex + + bool ShouldWait() override; + void Acquire() override; + + /** + * Acquires the specified mutex for the specified thread + * @param mutex Mutex that is to be acquired + * @param thread Thread that will acquire the mutex + */ + void Acquire(Thread* thread); + void Release(); + +private: + Mutex() = default; +}; /** * Releases all the mutexes held by the specified thread diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp index 31e6653ef..7ad428ee7 100644 --- a/src/core/hle/service/apt_s.cpp +++ b/src/core/hle/service/apt_s.cpp @@ -10,6 +10,7 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/shared_memory.h" +#include "core/hle/kernel/thread.h" #include "core/hle/service/apt_s.h" //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 1f6b148e8..5d7a6e060 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -10,6 +10,7 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/shared_memory.h" +#include "core/hle/kernel/thread.h" #include "core/hle/service/apt_u.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -28,7 +29,7 @@ static const VAddr SHARED_FONT_VADDR = 0x18000000; /// Handle to shared memory region designated to for shared system font static Kernel::SharedPtr shared_font_mem; -static Handle lock_handle = 0; +static Kernel::SharedPtr lock; static Handle notification_event_handle = 0; ///< APT notification event handle static Handle pause_event_handle = 0; ///< APT pause event handle static std::vector shared_font; @@ -76,8 +77,8 @@ void Initialize(Service::Interface* self) { Kernel::ClearEvent(notification_event_handle); Kernel::SignalEvent(pause_event_handle); // Fire start event - _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock"); - Kernel::ReleaseMutex(lock_handle); + _assert_msg_(KERNEL, (nullptr != lock), "Cannot initialize without lock"); + lock->Release(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error } @@ -103,10 +104,9 @@ void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field - if (0 == lock_handle) { + if (nullptr == lock) { // TODO(bunnei): Verify if this is created here or at application boot? - lock_handle = Kernel::CreateMutex(false, "APT_U:Lock"); - Kernel::ReleaseMutex(lock_handle); + lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -116,7 +116,7 @@ void GetLockHandle(Service::Interface* self) { cmd_buff[3] = 0; cmd_buff[4] = 0; - cmd_buff[5] = lock_handle; + cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]); } @@ -520,7 +520,7 @@ Interface::Interface() { shared_font_mem = nullptr; } - lock_handle = 0; + lock = nullptr; Register(FunctionTable, ARRAY_SIZE(FunctionTable)); } diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index b093d0368..76ce59b29 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -364,18 +364,32 @@ static Result SetThreadPriority(Handle handle, s32 priority) { } /// Create a mutex -static Result CreateMutex(Handle* mutex, u32 initial_locked) { - *mutex = Kernel::CreateMutex((initial_locked != 0)); +static Result CreateMutex(Handle* handle, u32 initial_locked) { + using Kernel::Mutex; + + auto mutex_res = Mutex::Create(initial_locked != 0); + if (mutex_res.Failed()) + return mutex_res.Code().raw; + SharedPtr mutex = mutex_res.MoveFrom(); + + *handle = Kernel::g_handle_table.Create(mutex).MoveFrom(); LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", - initial_locked ? "true" : "false", *mutex); + initial_locked ? "true" : "false", *handle); return 0; } /// Release a mutex static Result ReleaseMutex(Handle handle) { + using Kernel::Mutex; + LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); - ResultCode res = Kernel::ReleaseMutex(handle); - return res.raw; + + SharedPtr mutex = Kernel::g_handle_table.Get(handle); + if (mutex == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + mutex->Release(); + return RESULT_SUCCESS.raw; } /// Get the ID for the specified thread. From ad80ff1e322430634e04ffcb39ffef268411ea6b Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 23 Jan 2015 02:19:33 -0200 Subject: [PATCH 09/14] Kernel: Convert Timer to (mostly) not use Handles --- src/core/hle/kernel/timer.cpp | 109 ++++++++++------------------------ src/core/hle/kernel/timer.h | 63 ++++++++++++-------- src/core/hle/svc.cpp | 47 ++++++++++++--- 3 files changed, 110 insertions(+), 109 deletions(-) diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index aee5dc599..503a5d2ce 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -13,75 +13,54 @@ namespace Kernel { -class Timer : public WaitObject { -public: - std::string GetTypeName() const override { return "Timer"; } - std::string GetName() const override { return name; } +/// The event type of the generic timer callback event +static int timer_callback_event_type = -1; - static const HandleType HANDLE_TYPE = HandleType::Timer; - HandleType GetHandleType() const override { return HANDLE_TYPE; } - - ResetType reset_type; ///< The ResetType of this timer - - bool signaled; ///< Whether the timer has been signaled or not - std::string name; ///< Name of timer (optional) - - u64 initial_delay; ///< The delay until the timer fires for the first time - u64 interval_delay; ///< The delay until the timer fires after the first time - - bool ShouldWait() override { - return !signaled; - } - - void Acquire() override { - _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); - } -}; - -/** - * Creates a timer. - * @param handle Reference to handle for the newly created timer - * @param reset_type ResetType describing how to create timer - * @param name Optional name of timer - * @return Newly created Timer object - */ -static Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) { - Timer* timer = new Timer; - - handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE); +ResultVal> Timer::Create(ResetType reset_type, std::string name) { + SharedPtr timer(new Timer); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer)); timer->reset_type = reset_type; timer->signaled = false; - timer->name = name; + timer->name = std::move(name); timer->initial_delay = 0; timer->interval_delay = 0; - return timer; + return MakeResult>(timer); } -ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) { - CreateTimer(*handle, reset_type, name); - return RESULT_SUCCESS; +bool Timer::ShouldWait() { + return !signaled; } -ResultCode ClearTimer(Handle handle) { - SharedPtr timer = Kernel::g_handle_table.Get(handle); - - if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel); - - timer->signaled = false; - return RESULT_SUCCESS; +void Timer::Acquire() { + _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); } -/// The event type of the generic timer callback event -static int TimerCallbackEventType = -1; +void Timer::Set(s64 initial, s64 interval) { + initial_delay = initial; + interval_delay = interval; + + u64 initial_microseconds = initial / 1000; + // TODO(yuriks): Figure out a replacement for GetHandle here + CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, + GetHandle()); +} + +void Timer::Cancel() { + CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle()); +} + +void Timer::Clear() { + signaled = false; +} /// The timer callback event, called when a timer is fired static void TimerCallback(u64 timer_handle, int cycles_late) { SharedPtr timer = Kernel::g_handle_table.Get(timer_handle); if (timer == nullptr) { - LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle); + LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); return; } @@ -99,36 +78,12 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { // Reschedule the timer with the interval delay u64 interval_microseconds = timer->interval_delay / 1000; CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, - TimerCallbackEventType, timer_handle); + timer_callback_event_type, timer_handle); } } -ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { - SharedPtr timer = Kernel::g_handle_table.Get(handle); - - if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel); - - timer->initial_delay = initial; - timer->interval_delay = interval; - - u64 initial_microseconds = initial / 1000; - CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle); - return RESULT_SUCCESS; -} - -ResultCode CancelTimer(Handle handle) { - SharedPtr timer = Kernel::g_handle_table.Get(handle); - - if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel); - - CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle); - return RESULT_SUCCESS; -} - void TimersInit() { - TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); + timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); } void TimersShutdown() { diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 8170e82d4..24552b4b9 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -11,37 +11,50 @@ namespace Kernel { -/** - * Cancels a timer - * @param handle Handle of the timer to cancel - */ -ResultCode CancelTimer(Handle handle); +class Timer : public WaitObject { +public: + /** + * Creates a timer + * @param reset_type ResetType describing how to create the timer + * @param name Optional name of timer + * @return The created Timer + */ + static ResultVal> Create(ResetType reset_type, std::string name = "Unknown"); -/** - * Starts a timer with the specified initial delay and interval - * @param handle Handle of the timer to start - * @param initial Delay until the timer is first fired - * @param interval Delay until the timer is fired after the first time - */ -ResultCode SetTimer(Handle handle, s64 initial, s64 interval); + std::string GetTypeName() const override { return "Timer"; } + std::string GetName() const override { return name; } -/** - * Clears a timer - * @param handle Handle of the timer to clear - */ -ResultCode ClearTimer(Handle handle); + static const HandleType HANDLE_TYPE = HandleType::Timer; + HandleType GetHandleType() const override { return HANDLE_TYPE; } -/** - * Creates a timer - * @param handle Handle to the newly created Timer object - * @param reset_type ResetType describing how to create the timer - * @param name Optional name of timer - * @return ResultCode of the error - */ -ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name="Unknown"); + ResetType reset_type; ///< The ResetType of this timer + + bool signaled; ///< Whether the timer has been signaled or not + std::string name; ///< Name of timer (optional) + + u64 initial_delay; ///< The delay until the timer fires for the first time + u64 interval_delay; ///< The delay until the timer fires after the first time + + bool ShouldWait() override; + void Acquire() override; + + /** + * Starts the timer, with the specified initial delay and interval. + * @param initial Delay until the timer is first fired + * @param interval Delay until the timer is fired after the first time + */ + void Set(s64 initial, s64 interval); + + void Cancel(); + void Clear(); + +private: + Timer() = default; +}; /// Initializes the required variables for timers void TimersInit(); /// Tears down the timer variables void TimersShutdown(); + } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 76ce59b29..95403644b 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -479,28 +479,61 @@ static Result ClearEvent(Handle evt) { /// Creates a timer static Result CreateTimer(Handle* handle, u32 reset_type) { - ResultCode res = Kernel::CreateTimer(handle, static_cast(reset_type)); - LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", - reset_type, *handle); - return res.raw; + using Kernel::Timer; + + auto timer_res = Timer::Create(static_cast(reset_type)); + if (timer_res.Failed()) + return timer_res.Code().raw; + + auto handle_res = Kernel::g_handle_table.Create(timer_res.MoveFrom()); + if (handle_res.Failed()) + return handle_res.Code().raw; + *handle = handle_res.MoveFrom(); + + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); + return RESULT_SUCCESS.raw; } /// Clears a timer static Result ClearTimer(Handle handle) { + using Kernel::Timer; + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); - return Kernel::ClearTimer(handle).raw; + + SharedPtr timer = Kernel::g_handle_table.Get(handle); + if (timer == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + timer->Clear(); + return RESULT_SUCCESS.raw; } /// Starts a timer static Result SetTimer(Handle handle, s64 initial, s64 interval) { + using Kernel::Timer; + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); - return Kernel::SetTimer(handle, initial, interval).raw; + + SharedPtr timer = Kernel::g_handle_table.Get(handle); + if (timer == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + timer->Set(initial, interval); + return RESULT_SUCCESS.raw; } /// Cancels a timer static Result CancelTimer(Handle handle) { + using Kernel::Timer; + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); - return Kernel::CancelTimer(handle).raw; + + SharedPtr timer = Kernel::g_handle_table.Get(handle); + if (timer == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + timer->Cancel(); + return RESULT_SUCCESS.raw; } /// Sleep the current thread From d52d85993683a6948285801ab54d51c79c98afba Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 23 Jan 2015 03:11:25 -0200 Subject: [PATCH 10/14] Kernel: Convert Event to not use Handles --- src/core/hle/kernel/event.cpp | 91 ++++++++------------------- src/core/hle/kernel/event.h | 47 ++++++++------ src/core/hle/service/apt_u.cpp | 26 ++++---- src/core/hle/service/dsp_dsp.cpp | 26 +++++--- src/core/hle/service/gsp_gpu.cpp | 19 +++--- src/core/hle/service/hid/hid.cpp | 28 +++++---- src/core/hle/service/hid/hid.h | 11 ++-- src/core/hle/service/hid/hid_user.cpp | 11 ++-- src/core/hle/service/srv.cpp | 8 +-- src/core/hle/svc.cpp | 40 ++++++++---- 10 files changed, 153 insertions(+), 154 deletions(-) diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 74df47a05..d9ad40c6a 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -14,78 +14,37 @@ namespace Kernel { -class Event : public WaitObject { -public: - std::string GetTypeName() const override { return "Event"; } - std::string GetName() const override { return name; } - - static const HandleType HANDLE_TYPE = HandleType::Event; - HandleType GetHandleType() const override { return HANDLE_TYPE; } - - ResetType intitial_reset_type; ///< ResetType specified at Event initialization - ResetType reset_type; ///< Current ResetType - - bool signaled; ///< Whether the event has already been signaled - std::string name; ///< Name of event (optional) - - bool ShouldWait() override { - return !signaled; - } - - void Acquire() override { - _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); - - // Release the event if it's not sticky... - if (reset_type != RESETTYPE_STICKY) - signaled = false; - } -}; - -ResultCode SignalEvent(const Handle handle) { - Event* evt = g_handle_table.Get(handle).get(); - if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel); - - evt->signaled = true; - evt->WakeupAllWaitingThreads(); - - return RESULT_SUCCESS; -} - -ResultCode ClearEvent(Handle handle) { - Event* evt = g_handle_table.Get(handle).get(); - if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel); - - evt->signaled = false; - - return RESULT_SUCCESS; -} - -/** - * Creates an event - * @param handle Reference to handle for the newly created mutex - * @param reset_type ResetType describing how to create event - * @param name Optional name of event - * @return Newly created Event object - */ -static Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { - Event* evt = new Event; - - // TOOD(yuriks): Fix error reporting - handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE); +ResultVal> Event::Create(ResetType reset_type, std::string name) { + SharedPtr evt(new Event); + // TOOD(yuriks): Don't create Handle (see Thread::Create()) + CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt)); evt->signaled = false; evt->reset_type = evt->intitial_reset_type = reset_type; - evt->name = name; + evt->name = std::move(name); - return evt; + return MakeResult>(evt); } -Handle CreateEvent(const ResetType reset_type, const std::string& name) { - Handle handle; - Event* evt = CreateEvent(handle, reset_type, name); - return handle; +bool Event::ShouldWait() { + return !signaled; +} + +void Event::Acquire() { + _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); + + // Release the event if it's not sticky... + if (reset_type != RESETTYPE_STICKY) + signaled = false; +} + +void Event::Signal() { + signaled = true; + WakeupAllWaitingThreads(); +} + +void Event::Clear() { + signaled = false; } } // namespace diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index c08b12ee1..47420b157 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -11,26 +11,35 @@ namespace Kernel { -/** - * Signals an event - * @param handle Handle to event to signal - * @return Result of operation, 0 on success, otherwise error code - */ -ResultCode SignalEvent(const Handle handle); +class Event : public WaitObject { +public: + /** + * Creates an event + * @param reset_type ResetType describing how to create event + * @param name Optional name of event + */ + static ResultVal> Create(ResetType reset_type, std::string name = "Unknown"); -/** - * Clears an event - * @param handle Handle to event to clear - * @return Result of operation, 0 on success, otherwise error code - */ -ResultCode ClearEvent(Handle handle); + std::string GetTypeName() const override { return "Event"; } + std::string GetName() const override { return name; } -/** - * Creates an event - * @param reset_type ResetType describing how to create event - * @param name Optional name of event - * @return Handle to newly created Event object - */ -Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown"); + static const HandleType HANDLE_TYPE = HandleType::Event; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType + + bool signaled; ///< Whether the event has already been signaled + std::string name; ///< Name of event (optional) + + bool ShouldWait() override; + void Acquire() override; + + void Signal(); + void Clear(); + +private: + Event() = default; +}; } // namespace diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 5d7a6e060..629b670ed 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -30,8 +30,8 @@ static const VAddr SHARED_FONT_VADDR = 0x18000000; static Kernel::SharedPtr shared_font_mem; static Kernel::SharedPtr lock; -static Handle notification_event_handle = 0; ///< APT notification event handle -static Handle pause_event_handle = 0; ///< APT pause event handle +static Kernel::SharedPtr notification_event; ///< APT notification event +static Kernel::SharedPtr pause_event = 0; ///< APT pause event static std::vector shared_font; /// Signals used by APT functions @@ -68,14 +68,16 @@ enum class AppID : u32 { void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - notification_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Notification"); - pause_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); + // TODO(bunnei): Check if these are created in Initialize or on APT process startup. + notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom(); + pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom(); - cmd_buff[3] = notification_event_handle; - cmd_buff[4] = pause_event_handle; + cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); + cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom(); - Kernel::ClearEvent(notification_event_handle); - Kernel::SignalEvent(pause_event_handle); // Fire start event + // TODO(bunnei): Check if these events are cleared/signaled every time Initialize is called. + notification_event->Clear(); + pause_event->Signal(); // Fire start event _assert_msg_(KERNEL, (nullptr != lock), "Cannot initialize without lock"); lock->Release(); @@ -94,7 +96,7 @@ void NotifyToWait(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 app_id = cmd_buff[1]; // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further. - Kernel::SignalEvent(pause_event_handle); + pause_event->Signal(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); @@ -104,10 +106,6 @@ void GetLockHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field - if (nullptr == lock) { - // TODO(bunnei): Verify if this is created here or at application boot? - lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); - } cmd_buff[1] = RESULT_SUCCESS.raw; // No error // Not sure what these parameters are used for, but retail apps check that they are 0 after @@ -520,7 +518,7 @@ Interface::Interface() { shared_font_mem = nullptr; } - lock = nullptr; + lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); Register(FunctionTable, ARRAY_SIZE(FunctionTable)); } diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index d5e39ea4b..9a38be393 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -13,8 +13,8 @@ namespace DSP_DSP { static u32 read_pipe_count = 0; -static Handle semaphore_event = 0; -static Handle interrupt_event = 0; +static Kernel::SharedPtr semaphore_event; +static Kernel::SharedPtr interrupt_event; void SignalInterrupt() { // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated @@ -24,7 +24,7 @@ void SignalInterrupt() { // DSP interrupts, and trigger them at the appropriate times. if (interrupt_event != 0) - Kernel::SignalEvent(interrupt_event); + interrupt_event->Signal(); } /** @@ -78,8 +78,8 @@ void LoadComponent(Service::Interface* self) { void GetSemaphoreEventHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = 0; // No error - cmd_buff[3] = semaphore_event; // Event handle + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle LOG_WARNING(Service_DSP, "(STUBBED) called"); } @@ -96,9 +96,16 @@ void GetSemaphoreEventHandle(Service::Interface* self) { void RegisterInterruptEvents(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - interrupt_event = static_cast(cmd_buff[4]); + auto evt = Kernel::g_handle_table.Get(cmd_buff[4]); + if (evt != nullptr) { + interrupt_event = evt; + cmd_buff[1] = 0; // No error + } else { + LOG_ERROR(Service_DSP, "called with invalid handle=%08X", cmd_buff[4]); - cmd_buff[1] = 0; // No error + // TODO(yuriks): An error should be returned from SendSyncRequest, not in the cmdbuf + cmd_buff[1] = -1; + } LOG_WARNING(Service_DSP, "(STUBBED) called"); } @@ -194,8 +201,9 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); - interrupt_event = 0; + semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, + "DSP_DSP::semaphore_event").MoveFrom(); + interrupt_event = nullptr; read_pipe_count = 0; Register(FunctionTable, ARRAY_SIZE(FunctionTable)); diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 1be2438c8..5b91f17d2 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -22,9 +22,12 @@ GraphicsDebugger g_debugger; namespace GSP_GPU { -Handle g_interrupt_event = 0; ///< Handle to event triggered when GSP interrupt has been signalled -Kernel::SharedPtr g_shared_memory; ///< GSP shared memoryings -u32 g_thread_id = 1; ///< Thread index into interrupt relay queue, 1 is arbitrary +/// Event triggered when GSP interrupt has been signalled +Kernel::SharedPtr g_interrupt_event; +/// GSP shared memoryings +Kernel::SharedPtr g_shared_memory; +/// Thread index into interrupt relay queue, 1 is arbitrary +u32 g_thread_id = 1; /// Gets a pointer to a thread command buffer in GSP shared memory static inline u8* GetCommandBuffer(u32 thread_id) { @@ -181,10 +184,10 @@ static void FlushDataCache(Service::Interface* self) { static void RegisterInterruptRelayQueue(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 flags = cmd_buff[1]; - g_interrupt_event = cmd_buff[3]; - g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); - _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); + g_interrupt_event = Kernel::g_handle_table.Get(cmd_buff[3]); + _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!"); + g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); @@ -192,7 +195,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { cmd_buff[2] = g_thread_id++; // Thread ID cmd_buff[4] = shmem_handle; // GSP shared memory - Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct? + g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? } /** @@ -234,7 +237,7 @@ void SignalInterrupt(InterruptId interrupt_id) { info->is_dirty = false; } } - Kernel::SignalEvent(g_interrupt_event); + g_interrupt_event->Signal(); } /// Executes the next GSP command diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index ee2ba7e01..835055af4 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -14,11 +14,11 @@ namespace HID { Kernel::SharedPtr g_shared_mem = nullptr; -Handle g_event_pad_or_touch_1 = 0; -Handle g_event_pad_or_touch_2 = 0; -Handle g_event_accelerometer = 0; -Handle g_event_gyroscope = 0; -Handle g_event_debug_pad = 0; +Kernel::SharedPtr g_event_pad_or_touch_1; +Kernel::SharedPtr g_event_pad_or_touch_2; +Kernel::SharedPtr g_event_accelerometer; +Kernel::SharedPtr g_event_gyroscope; +Kernel::SharedPtr g_event_debug_pad; // Next Pad state update information static PadState next_state = {{0}}; @@ -115,19 +115,21 @@ void PadUpdateComplete() { } // Signal both handles when there's an update to Pad or touch - Kernel::SignalEvent(g_event_pad_or_touch_1); - Kernel::SignalEvent(g_event_pad_or_touch_2); + g_event_pad_or_touch_1->Signal(); + g_event_pad_or_touch_2->Signal(); } void HIDInit() { - g_shared_mem = Kernel::SharedMemory::Create("HID:SharedMem").MoveFrom(); + using namespace Kernel; + + g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom(); // Create event handles - g_event_pad_or_touch_1 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1"); - g_event_pad_or_touch_2 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2"); - g_event_accelerometer = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventAccelerometer"); - g_event_gyroscope = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventGyroscope"); - g_event_debug_pad = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventDebugPad"); + g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom(); + g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom(); + g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom(); + g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom(); + g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom(); } void HIDShutdown() { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 5e6236647..2116d2ca3 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -11,6 +11,7 @@ namespace Kernel { class SharedMemory; + class Event; } namespace Service { @@ -20,11 +21,11 @@ namespace HID { extern Kernel::SharedPtr g_shared_mem; // Event handles -extern Handle g_event_pad_or_touch_1; -extern Handle g_event_pad_or_touch_2; -extern Handle g_event_accelerometer; -extern Handle g_event_gyroscope; -extern Handle g_event_debug_pad; +extern Kernel::SharedPtr g_event_pad_or_touch_1; +extern Kernel::SharedPtr g_event_pad_or_touch_2; +extern Kernel::SharedPtr g_event_accelerometer; +extern Kernel::SharedPtr g_event_gyroscope; +extern Kernel::SharedPtr g_event_debug_pad; /** * Structure of a Pad controller state. diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp index c167927ea..5444aa5ee 100644 --- a/src/core/hle/service/hid/hid_user.cpp +++ b/src/core/hle/service/hid/hid_user.cpp @@ -5,6 +5,7 @@ #include "common/log.h" #include "core/hle/hle.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/hid/hid.h" #include "hid_user.h" @@ -49,11 +50,11 @@ void GetIPCHandles(Service::Interface* self) { cmd_buff[1] = 0; // No error // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::g_shared_mem).MoveFrom(); - cmd_buff[4] = Service::HID::g_event_pad_or_touch_1; - cmd_buff[5] = Service::HID::g_event_pad_or_touch_2; - cmd_buff[6] = Service::HID::g_event_accelerometer; - cmd_buff[7] = Service::HID::g_event_gyroscope; - cmd_buff[8] = Service::HID::g_event_debug_pad; + cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_1).MoveFrom(); + cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_2).MoveFrom(); + cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::g_event_accelerometer).MoveFrom(); + cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::g_event_gyroscope).MoveFrom(); + cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::g_event_debug_pad).MoveFrom(); } const Interface::FunctionInfo FunctionTable[] = { diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 082834cfe..aa0aac3bb 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -11,7 +11,7 @@ namespace SRV { -static Handle g_event_handle = 0; +static Kernel::SharedPtr event_handle; static void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); @@ -23,11 +23,11 @@ static void GetProcSemaphore(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Change to a semaphore once these have been implemented - g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event"); - Kernel::ClearEvent(g_event_handle); + event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom(); + event_handle->Clear(); cmd_buff[1] = 0; // No error - cmd_buff[3] = g_event_handle; + cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); } static void GetServiceHandle(Service::Interface* self) { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 95403644b..0c50f0d5b 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -447,11 +447,17 @@ static Result QueryMemory(void* info, void* out, u32 addr) { } /// Create an event -static Result CreateEvent(Handle* evt, u32 reset_type) { - *evt = Kernel::CreateEvent((ResetType)reset_type); - LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", - reset_type, *evt); - return 0; +static Result CreateEvent(Handle* handle, u32 reset_type) { + auto evt_res = Kernel::Event::Create(static_cast(reset_type)); + if (evt_res.Failed()) + return evt_res.Code().raw; + auto handle_res = Kernel::g_handle_table.Create(evt_res.MoveFrom()); + if (handle_res.Failed()) + return handle_res.Code().raw; + *handle = handle_res.MoveFrom(); + + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); + return RESULT_SUCCESS.raw; } /// Duplicates a kernel handle @@ -465,16 +471,28 @@ static Result DuplicateHandle(Handle* out, Handle handle) { } /// Signals an event -static Result SignalEvent(Handle evt) { - LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); +static Result SignalEvent(Handle handle) { + LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); + + auto evt = Kernel::g_handle_table.Get(handle); + if (evt == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + evt->Signal(); HLE::Reschedule(__func__); - return Kernel::SignalEvent(evt).raw; + return RESULT_SUCCESS.raw; } /// Clears an event -static Result ClearEvent(Handle evt) { - LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); - return Kernel::ClearEvent(evt).raw; +static Result ClearEvent(Handle handle) { + LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); + + auto evt = Kernel::g_handle_table.Get(handle); + if (evt == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + evt->Clear(); + return RESULT_SUCCESS.raw; } /// Creates a timer From 44f90340dcf8dc0686bf63ad2244567c55e08e70 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 23 Jan 2015 03:36:58 -0200 Subject: [PATCH 11/14] SVC: Change return type of handlers to ResultCode --- src/core/hle/function_wrappers.h | 79 +++++++------- src/core/hle/svc.cpp | 180 +++++++++++++++---------------- 2 files changed, 127 insertions(+), 132 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index a2f51b41b..ebb6ba1af 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -33,114 +33,109 @@ static inline void FuncReturn64(u64 res) { } //////////////////////////////////////////////////////////////////////////////////////////////////// -// Function wrappers that return type s32 +// Function wrappers that return type ResultCode -template void Wrap() { - FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3))); +template void Wrap() { + FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw); } -template void Wrap() { - FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4))); +template void Wrap() { + FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw); } -template void Wrap(){ +template void Wrap(){ u32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { +template void Wrap() { s32 param_1 = 0; s32 retval = func(¶m_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), - (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))); + (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))).raw; Core::g_app_core->SetReg(1, (u32)param_1); FuncReturn(retval); } -// TODO(bunnei): Is this correct? Probably not - Last parameter looks wrong for ArbitrateAddress -template void Wrap() { - FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4)))); +template void Wrap() { + FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw); } -template void Wrap(){ +template void Wrap(){ u32 param_1 = 0; - u32 retval = func(¶m_1); + u32 retval = func(¶m_1).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { - FuncReturn(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2)))); +template void Wrap() { + FuncReturn(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw); } -template void Wrap(){ - FuncReturn(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2))); +template void Wrap(){ + FuncReturn(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2)).raw); } -template void Wrap(){ +template void Wrap(){ s32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(1)); + u32 retval = func(¶m_1, PARAM(1)).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { - FuncReturn(func(PARAM(0), (s32)PARAM(1))); +template void Wrap() { + FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); } -template void Wrap(){ +template void Wrap(){ u32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(1)); + u32 retval = func(¶m_1, PARAM(1)).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { - FuncReturn(func(PARAM(0))); +template void Wrap() { + FuncReturn(func(PARAM(0)).raw); } -template void Wrap() { - FuncReturn(func(Memory::GetPointer(PARAM(0)))); -} - -template void Wrap(){ +template void Wrap(){ FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), - (s32)PARAM(3))); + (s32)PARAM(3)).raw); } -template void Wrap() { +template void Wrap() { u32 param_1 = 0; - u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))); + u32 retval = func(¶m_1, Memory::GetCharPointer(PARAM(1))).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { +template void Wrap() { u32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(1), PARAM(2)); + u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { +template void Wrap() { s32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(1), PARAM(2)); + u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { +template void Wrap() { u32 param_1 = 0; - u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)); + u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; Core::g_app_core->SetReg(1, param_1); FuncReturn(retval); } -template void Wrap() { +template void Wrap() { s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2); s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1); - FuncReturn(func(PARAM(0), param1, param2)); + FuncReturn(func(PARAM(0), param1, param2).raw); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 0c50f0d5b..bec9837a4 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -38,7 +38,7 @@ enum ControlMemoryOperation { }; /// Map application or GSP heap memory -static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { +static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", operation, addr0, addr1, size, permissions); @@ -58,11 +58,11 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, default: LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation); } - return 0; + return RESULT_SUCCESS; } /// Maps a memory block to specified address -static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { +static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { using Kernel::SharedMemory; using Kernel::MemoryPermission; @@ -71,7 +71,7 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other SharedPtr shared_memory = Kernel::g_handle_table.Get(handle); if (shared_memory == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); MemoryPermission permissions_type = static_cast(permissions); switch (permissions_type) { @@ -89,11 +89,11 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other default: LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); } - return 0; + return RESULT_SUCCESS; } /// Connect to an OS service given the port name, returns the handle to the port to out -static Result ConnectToPort(Handle* out, const char* port_name) { +static ResultCode ConnectToPort(Handle* out, const char* port_name) { Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); @@ -101,33 +101,33 @@ static Result ConnectToPort(Handle* out, const char* port_name) { *out = service->GetHandle(); - return 0; + return RESULT_SUCCESS; } /// Synchronize to an OS service -static Result SendSyncRequest(Handle handle) { +static ResultCode SendSyncRequest(Handle handle) { SharedPtr session = Kernel::g_handle_table.Get(handle); if (session == nullptr) { - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); } LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); - return session->SyncRequest().Code().raw; + return session->SyncRequest().Code(); } /// Close a handle -static Result CloseHandle(Handle handle) { +static ResultCode CloseHandle(Handle handle) { // ImplementMe LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); - return 0; + return RESULT_SUCCESS; } /// Wait for a handle to synchronize, timeout after the specified nanoseconds -static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { +static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { auto object = Kernel::g_handle_table.GetWaitObject(handle); if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); @@ -144,22 +144,22 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { HLE::Reschedule(__func__); // NOTE: output of this SVC will be set later depending on how the thread resumes - return RESULT_INVALID.raw; + return RESULT_INVALID; } object->Acquire(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Wait for the given handles to synchronize, timeout after the specified nanoseconds -static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { +static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { bool wait_thread = !wait_all; int handle_index = 0; // Check if 'handles' is invalid if (handles == nullptr) - return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent).raw; + return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If // this happens, the running application will crash. @@ -167,7 +167,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, // Check if 'handle_count' is invalid if (handle_count < 0) - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; + return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if // necessary @@ -176,7 +176,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, for (int i = 0; i < handle_count; ++i) { auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); // Check if the current thread should wait on this object... if (object->ShouldWait()) { @@ -220,7 +220,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, HLE::Reschedule(__func__); // NOTE: output of this SVC will be set later depending on how the thread resumes - return RESULT_INVALID.raw; + return RESULT_INVALID; } // Acquire objects if we did not wait... @@ -242,29 +242,29 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, // not seem to set it to any meaningful value. *out = wait_all ? 0 : handle_index; - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Create an address arbiter (to allocate access to shared resources) -static Result CreateAddressArbiter(u32* arbiter) { +static ResultCode CreateAddressArbiter(u32* arbiter) { using Kernel::AddressArbiter; ResultVal> arbiter_res = AddressArbiter::Create(); if (arbiter_res.Failed()) - return arbiter_res.Code().raw; + return arbiter_res.Code(); ResultVal handle_res = Kernel::g_handle_table.Create(*arbiter_res); if (handle_res.Failed()) - return handle_res.Code().raw; + return handle_res.Code(); LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *handle_res); *arbiter = *handle_res; - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Arbitrate address -static Result ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { +static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { using Kernel::AddressArbiter; LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, @@ -272,10 +272,10 @@ static Result ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, SharedPtr arbiter = Kernel::g_handle_table.Get(handle); if (arbiter == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); return arbiter->ArbitrateAddress(static_cast(type), - address, value, nanoseconds).raw; + address, value, nanoseconds); } /// Used to output a message on a debug hardware unit - does nothing on a retail unit @@ -284,26 +284,26 @@ static void OutputDebugString(const char* string) { } /// Get resource limit -static Result GetResourceLimit(Handle* resource_limit, Handle process) { +static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) { // With regards to proceess values: // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for // the current KThread. *resource_limit = 0xDEADBEEF; LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); - return 0; + return RESULT_SUCCESS; } /// Get resource limit current values -static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, +static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, s32 name_count) { LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", resource_limit, names, name_count); Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now - return 0; + return RESULT_SUCCESS; } /// Creates a new thread -static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { +static ResultCode CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { using Kernel::Thread; std::string name; @@ -317,7 +317,7 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top ResultVal> thread_res = Kernel::Thread::Create( name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); if (thread_res.Failed()) - return thread_res.Code().raw; + return thread_res.Code(); SharedPtr thread = std::move(*thread_res); // TODO(yuriks): Create new handle instead of using built-in @@ -332,7 +332,7 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling"); } - return 0; + return RESULT_SUCCESS; } /// Called when a thread exits @@ -344,214 +344,214 @@ static void ExitThread() { } /// Gets the priority for the specified thread -static Result GetThreadPriority(s32* priority, Handle handle) { +static ResultCode GetThreadPriority(s32* priority, Handle handle) { const SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); *priority = thread->GetPriority(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Sets the priority for the specified thread -static Result SetThreadPriority(Handle handle, s32 priority) { +static ResultCode SetThreadPriority(Handle handle, s32 priority) { SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); thread->SetPriority(priority); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Create a mutex -static Result CreateMutex(Handle* handle, u32 initial_locked) { +static ResultCode CreateMutex(Handle* handle, u32 initial_locked) { using Kernel::Mutex; auto mutex_res = Mutex::Create(initial_locked != 0); if (mutex_res.Failed()) - return mutex_res.Code().raw; + return mutex_res.Code(); SharedPtr mutex = mutex_res.MoveFrom(); *handle = Kernel::g_handle_table.Create(mutex).MoveFrom(); LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", initial_locked ? "true" : "false", *handle); - return 0; + return RESULT_SUCCESS; } /// Release a mutex -static Result ReleaseMutex(Handle handle) { +static ResultCode ReleaseMutex(Handle handle) { using Kernel::Mutex; LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); SharedPtr mutex = Kernel::g_handle_table.Get(handle); if (mutex == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); mutex->Release(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Get the ID for the specified thread. -static Result GetThreadId(u32* thread_id, Handle handle) { +static ResultCode GetThreadId(u32* thread_id, Handle handle) { LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); const SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); *thread_id = thread->GetThreadId(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Creates a semaphore -static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { +static ResultCode CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { using Kernel::Semaphore; ResultVal> semaphore_res = Semaphore::Create(initial_count, max_count); if (semaphore_res.Failed()) - return semaphore_res.Code().raw; + return semaphore_res.Code(); ResultVal handle_res = Kernel::g_handle_table.Create(*semaphore_res); if (handle_res.Failed()) - return handle_res.Code().raw; + return handle_res.Code(); *semaphore = *handle_res; LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", initial_count, max_count, *semaphore); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Releases a certain number of slots in a semaphore -static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { +static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { using Kernel::Semaphore; LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); SharedPtr semaphore = Kernel::g_handle_table.Get(handle); if (semaphore == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); ResultVal release_res = semaphore->Release(release_count); if (release_res.Failed()) - return release_res.Code().raw; + return release_res.Code(); *count = *release_res; - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Query memory -static Result QueryMemory(void* info, void* out, u32 addr) { +static ResultCode QueryMemory(void* info, void* out, u32 addr) { LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); - return 0; + return RESULT_SUCCESS; } /// Create an event -static Result CreateEvent(Handle* handle, u32 reset_type) { +static ResultCode CreateEvent(Handle* handle, u32 reset_type) { auto evt_res = Kernel::Event::Create(static_cast(reset_type)); if (evt_res.Failed()) - return evt_res.Code().raw; + return evt_res.Code(); auto handle_res = Kernel::g_handle_table.Create(evt_res.MoveFrom()); if (handle_res.Failed()) - return handle_res.Code().raw; + return handle_res.Code(); *handle = handle_res.MoveFrom(); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Duplicates a kernel handle -static Result DuplicateHandle(Handle* out, Handle handle) { +static ResultCode DuplicateHandle(Handle* out, Handle handle) { ResultVal out_h = Kernel::g_handle_table.Duplicate(handle); if (out_h.Succeeded()) { *out = *out_h; LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); } - return out_h.Code().raw; + return out_h.Code(); } /// Signals an event -static Result SignalEvent(Handle handle) { +static ResultCode SignalEvent(Handle handle) { LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); auto evt = Kernel::g_handle_table.Get(handle); if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); evt->Signal(); HLE::Reschedule(__func__); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Clears an event -static Result ClearEvent(Handle handle) { +static ResultCode ClearEvent(Handle handle) { LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); auto evt = Kernel::g_handle_table.Get(handle); if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); evt->Clear(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Creates a timer -static Result CreateTimer(Handle* handle, u32 reset_type) { +static ResultCode CreateTimer(Handle* handle, u32 reset_type) { using Kernel::Timer; auto timer_res = Timer::Create(static_cast(reset_type)); if (timer_res.Failed()) - return timer_res.Code().raw; + return timer_res.Code(); auto handle_res = Kernel::g_handle_table.Create(timer_res.MoveFrom()); if (handle_res.Failed()) - return handle_res.Code().raw; + return handle_res.Code(); *handle = handle_res.MoveFrom(); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Clears a timer -static Result ClearTimer(Handle handle) { +static ResultCode ClearTimer(Handle handle) { using Kernel::Timer; LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); SharedPtr timer = Kernel::g_handle_table.Get(handle); if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); timer->Clear(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Starts a timer -static Result SetTimer(Handle handle, s64 initial, s64 interval) { +static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { using Kernel::Timer; LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); SharedPtr timer = Kernel::g_handle_table.Get(handle); if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); timer->Set(initial, interval); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Cancels a timer -static Result CancelTimer(Handle handle) { +static ResultCode CancelTimer(Handle handle) { using Kernel::Timer; LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); SharedPtr timer = Kernel::g_handle_table.Get(handle); if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return InvalidHandle(ErrorModule::Kernel); timer->Cancel(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Sleep the current thread @@ -573,22 +573,22 @@ static s64 GetSystemTick() { } /// Creates a memory block at the specified address with the specified permissions and size -static Result CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, +static ResultCode CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, u32 other_permission) { using Kernel::SharedMemory; // TODO(Subv): Implement this function ResultVal> shared_memory_res = SharedMemory::Create(); if (shared_memory_res.Failed()) - return shared_memory_res.Code().raw; + return shared_memory_res.Code(); ResultVal handle_res = Kernel::g_handle_table.Create(*shared_memory_res); if (handle_res.Failed()) - return handle_res.Code().raw; + return handle_res.Code(); *memblock = *handle_res; LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); - return 0; + return RESULT_SUCCESS; } const HLE::FunctionDef SVC_Table[] = { From 09ae6e1fa38bbf75dcb2796e96575fdba32ec69c Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 23 Jan 2015 03:44:52 -0200 Subject: [PATCH 12/14] Remove result.h InvalidHandle It was only being used in two places, where it was replaced by a local constant. --- src/core/hle/kernel/kernel.h | 3 ++- src/core/hle/result.h | 5 ----- src/core/hle/service/fs/archive.cpp | 23 ++++++++++++--------- src/core/hle/svc.cpp | 31 +++++++++++++++-------------- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 08a5db3b7..9860479ac 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -31,7 +31,8 @@ class Thread; const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Temporary); // TOOD: Verify code -const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel); +const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, + ErrorSummary::InvalidArgument, ErrorLevel::Permanent); enum KernelHandle : Handle { CurrentThread = 0xFFFF8000, diff --git a/src/core/hle/result.h b/src/core/hle/result.h index ad06d00aa..948b9e38e 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -227,11 +227,6 @@ inline ResultCode UnimplementedFunction(ErrorModule module) { return ResultCode(ErrorDescription::NotImplemented, module, ErrorSummary::NotSupported, ErrorLevel::Permanent); } -/// Returned when a function is passed an invalid handle. -inline ResultCode InvalidHandle(ErrorModule module) { - return ResultCode(ErrorDescription::InvalidHandle, module, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); -} /** * This is an optional value type. It holds a `ResultCode` and, if that code is a success code, diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 1bb4e4b23..6682f6590 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -43,6 +43,11 @@ const std::string SDCARD_ID = "00000000000000000000000000000000"; namespace Service { namespace FS { +// TODO: Verify code +/// Returned when a function is passed an invalid handle. +const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, + ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + // Command to access archive file enum class FileCommand : u32 { Dummy1 = 0x000100C6, @@ -280,7 +285,7 @@ ResultVal OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi ResultCode CloseArchive(ArchiveHandle handle) { if (handle_map.erase(handle) == 0) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; else return RESULT_SUCCESS; } @@ -301,7 +306,7 @@ ResultCode CreateArchive(std::unique_ptr&& backend, Arc ResultVal OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; std::unique_ptr backend = archive->backend->OpenFile(path, mode); if (backend == nullptr) { @@ -318,7 +323,7 @@ ResultVal OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; if (archive->backend->DeleteFile(path)) return RESULT_SUCCESS; @@ -331,7 +336,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil Archive* src_archive = GetArchive(src_archive_handle); Archive* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; if (src_archive == dest_archive) { if (src_archive->backend->RenameFile(src_path, dest_path)) @@ -350,7 +355,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; if (archive->backend->DeleteDirectory(path)) return RESULT_SUCCESS; @@ -361,7 +366,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; return archive->backend->CreateFile(path, file_size); } @@ -369,7 +374,7 @@ ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; if (archive->backend->CreateDirectory(path)) return RESULT_SUCCESS; @@ -382,7 +387,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons Archive* src_archive = GetArchive(src_archive_handle); Archive* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; if (src_archive == dest_archive) { if (src_archive->backend->RenameDirectory(src_path, dest_path)) @@ -407,7 +412,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons ResultVal OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) - return InvalidHandle(ErrorModule::FS); + return ERR_INVALID_HANDLE; std::unique_ptr backend = archive->backend->OpenDirectory(path); if (backend == nullptr) { diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index bec9837a4..46fca51c7 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -26,6 +26,7 @@ // Namespace SVC using Kernel::SharedPtr; +using Kernel::ERR_INVALID_HANDLE; namespace SVC { @@ -71,7 +72,7 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o SharedPtr shared_memory = Kernel::g_handle_table.Get(handle); if (shared_memory == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; MemoryPermission permissions_type = static_cast(permissions); switch (permissions_type) { @@ -108,7 +109,7 @@ static ResultCode ConnectToPort(Handle* out, const char* port_name) { static ResultCode SendSyncRequest(Handle handle) { SharedPtr session = Kernel::g_handle_table.Get(handle); if (session == nullptr) { - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; } LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); @@ -127,7 +128,7 @@ static ResultCode CloseHandle(Handle handle) { static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { auto object = Kernel::g_handle_table.GetWaitObject(handle); if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); @@ -176,7 +177,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou for (int i = 0; i < handle_count; ++i) { auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; // Check if the current thread should wait on this object... if (object->ShouldWait()) { @@ -272,7 +273,7 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val SharedPtr arbiter = Kernel::g_handle_table.Get(handle); if (arbiter == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; return arbiter->ArbitrateAddress(static_cast(type), address, value, nanoseconds); @@ -347,7 +348,7 @@ static void ExitThread() { static ResultCode GetThreadPriority(s32* priority, Handle handle) { const SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; *priority = thread->GetPriority(); return RESULT_SUCCESS; @@ -357,7 +358,7 @@ static ResultCode GetThreadPriority(s32* priority, Handle handle) { static ResultCode SetThreadPriority(Handle handle, s32 priority) { SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; thread->SetPriority(priority); return RESULT_SUCCESS; @@ -386,7 +387,7 @@ static ResultCode ReleaseMutex(Handle handle) { SharedPtr mutex = Kernel::g_handle_table.Get(handle); if (mutex == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; mutex->Release(); return RESULT_SUCCESS; @@ -398,7 +399,7 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) { const SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; *thread_id = thread->GetThreadId(); return RESULT_SUCCESS; @@ -430,7 +431,7 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) SharedPtr semaphore = Kernel::g_handle_table.Get(handle); if (semaphore == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; ResultVal release_res = semaphore->Release(release_count); if (release_res.Failed()) @@ -476,7 +477,7 @@ static ResultCode SignalEvent(Handle handle) { auto evt = Kernel::g_handle_table.Get(handle); if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; evt->Signal(); HLE::Reschedule(__func__); @@ -489,7 +490,7 @@ static ResultCode ClearEvent(Handle handle) { auto evt = Kernel::g_handle_table.Get(handle); if (evt == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; evt->Clear(); return RESULT_SUCCESS; @@ -520,7 +521,7 @@ static ResultCode ClearTimer(Handle handle) { SharedPtr timer = Kernel::g_handle_table.Get(handle); if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; timer->Clear(); return RESULT_SUCCESS; @@ -534,7 +535,7 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { SharedPtr timer = Kernel::g_handle_table.Get(handle); if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; timer->Set(initial, interval); return RESULT_SUCCESS; @@ -548,7 +549,7 @@ static ResultCode CancelTimer(Handle handle) { SharedPtr timer = Kernel::g_handle_table.Get(handle); if (timer == nullptr) - return InvalidHandle(ErrorModule::Kernel); + return ERR_INVALID_HANDLE; timer->Cancel(); return RESULT_SUCCESS; From 58b544db9958078098a8daf6316cbb58faa729dc Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 23 Jan 2015 04:00:39 -0200 Subject: [PATCH 13/14] SVC: Use CASCADE_RESULT in SVC handlers --- src/core/hle/function_wrappers.h | 4 -- src/core/hle/svc.cpp | 103 ++++++++++--------------------- 2 files changed, 31 insertions(+), 76 deletions(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index ebb6ba1af..0b6b6f518 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -39,10 +39,6 @@ template void Wrap() { FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw); } -template void Wrap() { - FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw); -} - template void Wrap(){ u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 46fca51c7..88813c2ce 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -247,20 +247,12 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou } /// Create an address arbiter (to allocate access to shared resources) -static ResultCode CreateAddressArbiter(u32* arbiter) { +static ResultCode CreateAddressArbiter(Handle* out_handle) { using Kernel::AddressArbiter; - ResultVal> arbiter_res = AddressArbiter::Create(); - if (arbiter_res.Failed()) - return arbiter_res.Code(); - - ResultVal handle_res = Kernel::g_handle_table.Create(*arbiter_res); - if (handle_res.Failed()) - return handle_res.Code(); - - LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *handle_res); - - *arbiter = *handle_res; + CASCADE_RESULT(SharedPtr arbiter, AddressArbiter::Create()); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter))); + LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle); return RESULT_SUCCESS; } @@ -304,7 +296,7 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim } /// Creates a new thread -static ResultCode CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { +static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { using Kernel::Thread; std::string name; @@ -315,18 +307,13 @@ static ResultCode CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack name = Common::StringFromFormat("unknown-%08x", entry_point); } - ResultVal> thread_res = Kernel::Thread::Create( - name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); - if (thread_res.Failed()) - return thread_res.Code(); - SharedPtr thread = std::move(*thread_res); - - // TODO(yuriks): Create new handle instead of using built-in - Core::g_app_core->SetReg(1, thread->GetHandle()); + CASCADE_RESULT(SharedPtr thread, Kernel::Thread::Create( + name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, - name.c_str(), arg, stack_top, priority, processor_id, thread->GetHandle()); + name.c_str(), arg, stack_top, priority, processor_id, *out_handle); if (THREADPROCESSORID_1 == processor_id) { LOG_WARNING(Kernel_SVC, @@ -365,17 +352,14 @@ static ResultCode SetThreadPriority(Handle handle, s32 priority) { } /// Create a mutex -static ResultCode CreateMutex(Handle* handle, u32 initial_locked) { +static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { using Kernel::Mutex; - auto mutex_res = Mutex::Create(initial_locked != 0); - if (mutex_res.Failed()) - return mutex_res.Code(); - SharedPtr mutex = mutex_res.MoveFrom(); + CASCADE_RESULT(SharedPtr mutex, Mutex::Create(initial_locked != 0)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); - *handle = Kernel::g_handle_table.Create(mutex).MoveFrom(); LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", - initial_locked ? "true" : "false", *handle); + initial_locked ? "true" : "false", *out_handle); return RESULT_SUCCESS; } @@ -406,20 +390,14 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) { } /// Creates a semaphore -static ResultCode CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { +static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) { using Kernel::Semaphore; - ResultVal> semaphore_res = Semaphore::Create(initial_count, max_count); - if (semaphore_res.Failed()) - return semaphore_res.Code(); + CASCADE_RESULT(SharedPtr semaphore, Semaphore::Create(initial_count, max_count)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); - ResultVal handle_res = Kernel::g_handle_table.Create(*semaphore_res); - if (handle_res.Failed()) - return handle_res.Code(); - - *semaphore = *handle_res; LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", - initial_count, max_count, *semaphore); + initial_count, max_count, *out_handle); return RESULT_SUCCESS; } @@ -433,11 +411,7 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) if (semaphore == nullptr) return ERR_INVALID_HANDLE; - ResultVal release_res = semaphore->Release(release_count); - if (release_res.Failed()) - return release_res.Code(); - - *count = *release_res; + CASCADE_RESULT(*count, semaphore->Release(release_count)); return RESULT_SUCCESS; } @@ -448,16 +422,12 @@ static ResultCode QueryMemory(void* info, void* out, u32 addr) { } /// Create an event -static ResultCode CreateEvent(Handle* handle, u32 reset_type) { - auto evt_res = Kernel::Event::Create(static_cast(reset_type)); - if (evt_res.Failed()) - return evt_res.Code(); - auto handle_res = Kernel::g_handle_table.Create(evt_res.MoveFrom()); - if (handle_res.Failed()) - return handle_res.Code(); - *handle = handle_res.MoveFrom(); +static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { + CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast(reset_type))); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); - LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", + reset_type, *out_handle); return RESULT_SUCCESS; } @@ -497,19 +467,14 @@ static ResultCode ClearEvent(Handle handle) { } /// Creates a timer -static ResultCode CreateTimer(Handle* handle, u32 reset_type) { +static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { using Kernel::Timer; - auto timer_res = Timer::Create(static_cast(reset_type)); - if (timer_res.Failed()) - return timer_res.Code(); + CASCADE_RESULT(auto timer, Timer::Create(static_cast(reset_type))); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); - auto handle_res = Kernel::g_handle_table.Create(timer_res.MoveFrom()); - if (handle_res.Failed()) - return handle_res.Code(); - *handle = handle_res.MoveFrom(); - - LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type, *handle); + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", + reset_type, *out_handle); return RESULT_SUCCESS; } @@ -574,20 +539,14 @@ static s64 GetSystemTick() { } /// Creates a memory block at the specified address with the specified permissions and size -static ResultCode CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, +static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, u32 other_permission) { using Kernel::SharedMemory; // TODO(Subv): Implement this function - ResultVal> shared_memory_res = SharedMemory::Create(); - if (shared_memory_res.Failed()) - return shared_memory_res.Code(); + CASCADE_RESULT(auto shared_memory, SharedMemory::Create()); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); - ResultVal handle_res = Kernel::g_handle_table.Create(*shared_memory_res); - if (handle_res.Failed()) - return handle_res.Code(); - - *memblock = *handle_res; LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); return RESULT_SUCCESS; } From d917a9bf7774fac3d7bccda761976615722ff3e6 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Tue, 27 Jan 2015 02:40:21 -0200 Subject: [PATCH 14/14] Kernel: Mark all appropriate kernel objects as "final" --- src/core/hle/kernel/address_arbiter.h | 2 +- src/core/hle/kernel/event.h | 2 +- src/core/hle/kernel/mutex.h | 2 +- src/core/hle/kernel/semaphore.h | 2 +- src/core/hle/kernel/shared_memory.h | 2 +- src/core/hle/kernel/thread.h | 3 +-- src/core/hle/kernel/timer.h | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 536f0f017..638afff9e 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -26,7 +26,7 @@ enum class ArbitrationType : u32 { DecrementAndWaitIfLessThanWithTimeout, }; -class AddressArbiter : public Object { +class AddressArbiter final : public Object { public: /** * Creates an address arbiter. diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 47420b157..2c3e6b14e 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -11,7 +11,7 @@ namespace Kernel { -class Event : public WaitObject { +class Event final : public WaitObject { public: /** * Creates an event diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index a6d822e60..1e69528f1 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -14,7 +14,7 @@ namespace Kernel { class Thread; -class Mutex : public WaitObject { +class Mutex final : public WaitObject { public: /** * Creates a mutex. diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index b7f22b86e..9bb404ab6 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -13,7 +13,7 @@ namespace Kernel { -class Semaphore : public WaitObject { +class Semaphore final : public WaitObject { public: /** * Creates a semaphore. diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index eb063d39d..f9ae23e93 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -23,7 +23,7 @@ enum class MemoryPermission : u32 { DontCare = (1u << 28) }; -class SharedMemory : public Object { +class SharedMemory final : public Object { public: /** * Creates a shared memory object diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 5fab1ab58..d6299364a 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -40,7 +40,7 @@ enum ThreadStatus { namespace Kernel { -class Thread : public WaitObject { +class Thread final : public WaitObject { public: static ResultVal> Create(std::string name, VAddr entry_point, s32 priority, u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size); @@ -115,7 +115,6 @@ public: bool idle = false; private: - Thread() = default; }; diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 24552b4b9..c45e79954 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -11,7 +11,7 @@ namespace Kernel { -class Timer : public WaitObject { +class Timer final : public WaitObject { public: /** * Creates a timer