diff options
author | bunnei <bunneidev@gmail.com> | 2014-11-24 21:31:53 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2014-11-24 21:31:53 +0100 |
commit | bb730855e58d18d8964d158a55822c40503d548f (patch) | |
tree | 9c3ff113839583d1deca837e9888d81f25d485a0 /src/core/hle/kernel | |
parent | Merge pull request #191 from archshift/deletexyz (diff) | |
parent | Use pointers instead of passing handles around in some functions. (diff) | |
download | yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.gz yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.bz2 yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.lz yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.xz yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.zst yuzu-bb730855e58d18d8964d158a55822c40503d548f.zip |
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 15 | ||||
-rw-r--r-- | src/core/hle/kernel/address_arbiter.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/archive.cpp | 176 | ||||
-rw-r--r-- | src/core/hle/kernel/archive.h | 23 | ||||
-rw-r--r-- | src/core/hle/kernel/event.cpp | 43 | ||||
-rw-r--r-- | src/core/hle/kernel/event.h | 12 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 44 | ||||
-rw-r--r-- | src/core/hle/kernel/mutex.cpp | 35 | ||||
-rw-r--r-- | src/core/hle/kernel/mutex.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/shared_memory.cpp | 43 | ||||
-rw-r--r-- | src/core/hle/kernel/shared_memory.h | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 78 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 7 |
13 files changed, 195 insertions, 291 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 2b21657da..db571b895 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -25,22 +25,17 @@ public: std::string name; ///< Name of address arbiter object (optional) - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { + ResultVal<bool> WaitSynchronization() override { // TODO(bunnei): ImplementMe ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); - return 0; + return UnimplementedFunction(ErrorModule::OS); } }; //////////////////////////////////////////////////////////////////////////////////////////////////// /// Arbitrate an address -Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { +ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { switch (type) { // Signal thread(s) waiting for arbitrate address... @@ -65,9 +60,9 @@ Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 va default: ERROR_LOG(KERNEL, "unknown type=%d", type); - return -1; + return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); } - return 0; + return RESULT_SUCCESS; } /// Create an address arbiter diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 6886e479d..8a5fb10b4 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -28,7 +28,7 @@ enum class ArbitrationType : u32 { }; /// Arbitrate an address -Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value); +ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value); /// Create an address arbiter Handle CreateAddressArbiter(const std::string& name = "Unknown"); diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index 900f484c7..e273444c9 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp @@ -9,8 +9,9 @@ #include "core/file_sys/archive.h" #include "core/file_sys/archive_sdmc.h" #include "core/file_sys/directory.h" -#include "core/hle/service/service.h" #include "core/hle/kernel/archive.h" +#include "core/hle/result.h" +#include "core/hle/service/service.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Kernel namespace @@ -51,12 +52,7 @@ public: std::string name; ///< Name of archive (optional) FileSys::Archive* backend; ///< Archive backend interface - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) override { + ResultVal<bool> SyncRequest() override { u32* cmd_buff = Service::GetCommandBuffer(); FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); @@ -106,22 +102,17 @@ public: default: { ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); - return -1; + return UnimplementedFunction(ErrorModule::FS); } } cmd_buff[1] = 0; // No error - return 0; + return MakeResult<bool>(false); } - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { + ResultVal<bool> WaitSynchronization() override { // TODO(bunnei): ImplementMe ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); - return 0; + return UnimplementedFunction(ErrorModule::FS); } }; @@ -136,12 +127,7 @@ public: FileSys::Path path; ///< Path of the file std::unique_ptr<FileSys::File> backend; ///< File backend interface - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) override { + ResultVal<bool> SyncRequest() override { u32* cmd_buff = Service::GetCommandBuffer(); FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); switch (cmd) { @@ -183,7 +169,8 @@ public: case FileCommand::SetSize: { u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); - DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), size); + DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", + GetTypeName().c_str(), GetName().c_str(), size); backend->SetSize(size); break; } @@ -198,22 +185,18 @@ public: // Unknown command... default: ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); - cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. - return -1; + ResultCode error = UnimplementedFunction(ErrorModule::FS); + cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. + return error; } cmd_buff[1] = 0; // No error - return 0; + return MakeResult<bool>(false); } - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { + ResultVal<bool> WaitSynchronization() override { // TODO(bunnei): ImplementMe ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); - return 0; + return UnimplementedFunction(ErrorModule::FS); } }; @@ -228,12 +211,7 @@ public: FileSys::Path path; ///< Path of the directory std::unique_ptr<FileSys::Directory> backend; ///< File backend interface - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) override { + ResultVal<bool> SyncRequest() override { u32* cmd_buff = Service::GetCommandBuffer(); DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); switch (cmd) { @@ -243,8 +221,9 @@ public: { u32 count = cmd_buff[1]; u32 address = cmd_buff[3]; - FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); - DEBUG_LOG(KERNEL, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); + auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); + DEBUG_LOG(KERNEL, "Read %s %s: count=%d", + GetTypeName().c_str(), GetName().c_str(), count); // Number of entries actually read cmd_buff[2] = backend->Read(count, entries); @@ -261,22 +240,18 @@ public: // Unknown command... default: ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); - cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. - return -1; + ResultCode error = UnimplementedFunction(ErrorModule::FS); + cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. + return error; } cmd_buff[1] = 0; // No error - return 0; + return MakeResult<bool>(false); } - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { + ResultVal<bool> WaitSynchronization() override { // TODO(bunnei): ImplementMe ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); - return 0; + return UnimplementedFunction(ErrorModule::FS); } }; @@ -284,89 +259,58 @@ public: std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode -/** - * Opens an archive - * @param id_code IdCode of the archive to open - * @return Handle to archive if it exists, otherwise a null handle (0) - */ -Handle OpenArchive(FileSys::Archive::IdCode id_code) { +ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) { auto itr = g_archive_map.find(id_code); if (itr == g_archive_map.end()) { - return 0; + return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Permanent); } - return itr->second; + + return MakeResult<Handle>(itr->second); } -/** - * Closes an archive - * @param id_code IdCode of the archive to open - * @return Result of operation, 0 on success, otherwise error code - */ -Result CloseArchive(FileSys::Archive::IdCode id_code) { +ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { auto itr = g_archive_map.find(id_code); if (itr == g_archive_map.end()) { ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); - return -1; + return InvalidHandle(ErrorModule::FS); } INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); - return 0; + return RESULT_SUCCESS; } /** * Mounts an archive * @param archive Pointer to the archive to mount - * @return Result of operation, 0 on success, otherwise error code */ -Result MountArchive(Archive* archive) { +ResultCode MountArchive(Archive* archive) { FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); - if (0 != OpenArchive(id_code)) { + ResultVal<Handle> archive_handle = OpenArchive(id_code); + if (archive_handle.Succeeded()) { ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); - return -1; + return archive_handle.Code(); } g_archive_map[id_code] = archive->GetHandle(); INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); - return 0; + return RESULT_SUCCESS; } -/** - * Creates an Archive - * @param handle Handle to newly created archive object - * @param backend File system backend interface to the archive - * @param name Optional name of Archive - * @return Newly created Archive object - */ -Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) { +ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) { Archive* archive = new Archive; - handle = Kernel::g_object_pool.Create(archive); + Handle handle = Kernel::g_object_pool.Create(archive); archive->name = name; archive->backend = backend; - MountArchive(archive); - - return archive; -} - -/** - * Creates an Archive - * @param backend File system backend interface to the archive - * @param name Optional name of Archive - * @return Handle to newly created Archive object - */ -Handle CreateArchive(FileSys::Archive* backend, const std::string& name) { - Handle handle; - CreateArchive(handle, backend, name); - return handle; + ResultCode result = MountArchive(archive); + if (result.IsError()) { + return result; + } + + return RESULT_SUCCESS; } -/** - * Open a File from an Archive - * @param archive_handle Handle to an open Archive object - * @param path Path to the File inside of the Archive - * @param mode Mode under which to open the File - * @return Opened File object - */ -Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { +ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create // the archive file handles at app loading, and then keep them persistent throughout execution. // Archives file handles are just reused and not actually freed until emulation shut down. @@ -376,19 +320,24 @@ Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, con // design. While the functionally of this is OK, our implementation decision to separate // normal files from archive file pointers is very likely wrong. // See https://github.com/citra-emu/citra/issues/205 - return archive_handle; + return MakeResult<Handle>(archive_handle); File* file = new File; Handle handle = Kernel::g_object_pool.Create(file); - Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); + Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); + if (archive == nullptr) { + return InvalidHandle(ErrorModule::FS); + } file->path = path; file->backend = archive->backend->OpenFile(path, mode); - if (!file->backend) - return 0; + if (!file->backend) { + return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Permanent); + } - return handle; + return MakeResult<Handle>(handle); } /** @@ -442,15 +391,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa * @param path Path to the Directory inside of the Archive * @return Opened Directory object */ -Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { +ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { Directory* directory = new Directory; Handle handle = Kernel::g_object_pool.Create(directory); - Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); + Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); + if (archive == nullptr) { + return InvalidHandle(ErrorModule::FS); + } directory->path = path; directory->backend = archive->backend->OpenDirectory(path); - return handle; + return MakeResult<Handle>(handle); } /// Initialize archives diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h index 95b3c6656..6fc4f0f25 100644 --- a/src/core/hle/kernel/archive.h +++ b/src/core/hle/kernel/archive.h @@ -6,8 +6,9 @@ #include "common/common_types.h" -#include "core/hle/kernel/kernel.h" #include "core/file_sys/archive.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // Kernel namespace @@ -17,33 +18,31 @@ namespace Kernel { /** * Opens an archive * @param id_code IdCode of the archive to open - * @return Handle to archive if it exists, otherwise a null handle (0) + * @return Handle to the opened archive */ -Handle OpenArchive(FileSys::Archive::IdCode id_code); +ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code); /** * Closes an archive * @param id_code IdCode of the archive to open - * @return true if it worked fine */ -Result CloseArchive(FileSys::Archive::IdCode id_code); +ResultCode CloseArchive(FileSys::Archive::IdCode id_code); /** * Creates an Archive * @param backend File system backend interface to the archive - * @param name Optional name of Archive - * @return Handle to newly created Archive object + * @param name Name of Archive */ -Handle CreateArchive(FileSys::Archive* backend, const std::string& name); +ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); /** * Open a File from an Archive * @param archive_handle Handle to an open Archive object * @param path Path to the File inside of the Archive * @param mode Mode under which to open the File - * @return Opened File object + * @return Handle to the opened File object */ -Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); +ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); /** * Delete a File from an Archive @@ -73,9 +72,9 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa * Open a Directory from an Archive * @param archive_handle Handle to an open Archive object * @param path Path to the Directory inside of the Archive - * @return Opened Directory object + * @return Handle to the opened File object */ -Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); +ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); /// Initialize archives void ArchiveInit(); diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e0117c0bc..288080209 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -30,13 +30,8 @@ public: std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event std::string name; ///< Name of event (optional) - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { - *wait = locked; + ResultVal<bool> WaitSynchronization() override { + bool wait = locked; if (locked) { Handle thread = GetCurrentThreadHandle(); if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { @@ -47,7 +42,7 @@ public: if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } - return 0; + return MakeResult<bool>(wait); } }; @@ -57,12 +52,12 @@ public: * @param permanent_locked Boolean permanent locked value to set event * @return Result of operation, 0 on success, otherwise error code */ -Result SetPermanentLock(Handle handle, const bool permanent_locked) { - Event* evt = g_object_pool.GetFast<Event>(handle); - _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); +ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.Get<Event>(handle); + if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); evt->permanent_locked = permanent_locked; - return 0; + return RESULT_SUCCESS; } /** @@ -71,14 +66,14 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { * @param locked Boolean locked value to set event * @return Result of operation, 0 on success, otherwise error code */ -Result SetEventLocked(const Handle handle, const bool locked) { - Event* evt = g_object_pool.GetFast<Event>(handle); - _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); +ResultCode SetEventLocked(const Handle handle, const bool locked) { + Event* evt = g_object_pool.Get<Event>(handle); + if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!evt->permanent_locked) { evt->locked = locked; } - return 0; + return RESULT_SUCCESS; } /** @@ -86,9 +81,9 @@ Result SetEventLocked(const Handle handle, const bool locked) { * @param handle Handle to event to signal * @return Result of operation, 0 on success, otherwise error code */ -Result SignalEvent(const Handle handle) { - Event* evt = g_object_pool.GetFast<Event>(handle); - _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); +ResultCode SignalEvent(const Handle handle) { + Event* evt = g_object_pool.Get<Event>(handle); + if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); // Resume threads waiting for event to signal bool event_caught = false; @@ -106,7 +101,7 @@ Result SignalEvent(const Handle handle) { if (!evt->permanent_locked) { evt->locked = event_caught; } - return 0; + return RESULT_SUCCESS; } /** @@ -114,14 +109,14 @@ Result SignalEvent(const Handle handle) { * @param handle Handle to event to clear * @return Result of operation, 0 on success, otherwise error code */ -Result ClearEvent(Handle handle) { - Event* evt = g_object_pool.GetFast<Event>(handle); - _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); +ResultCode ClearEvent(Handle handle) { + Event* evt = g_object_pool.Get<Event>(handle); + if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!evt->permanent_locked) { evt->locked = true; } - return 0; + return RESULT_SUCCESS; } /** diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 6add72897..73aec4e79 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -15,31 +15,27 @@ namespace Kernel { * Changes whether an event is locked or not * @param handle Handle to event to change * @param locked Boolean locked value to set event - * @return Result of operation, 0 on success, otherwise error code */ -Result SetEventLocked(const Handle handle, const bool locked); +ResultCode SetEventLocked(const Handle handle, const bool locked); /** * Hackish function to set an events permanent lock state, used to pass through synch blocks * @param handle Handle to event to change * @param permanent_locked Boolean permanent locked value to set event - * @return Result of operation, 0 on success, otherwise error code */ -Result SetPermanentLock(Handle handle, const bool permanent_locked); +ResultCode SetPermanentLock(Handle handle, const bool permanent_locked); /** * Signals an event * @param handle Handle to event to signal - * @return Result of operation, 0 on success, otherwise error code */ -Result SignalEvent(const Handle handle); +ResultCode SignalEvent(const Handle handle); /** * Clears an event * @param handle Handle to event to clear - * @return Result of operation, 0 on success, otherwise error code */ -Result ClearEvent(Handle handle); +ResultCode ClearEvent(Handle handle); /** * Creates an event diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index e0c94f186..8d3937ce8 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -7,6 +7,7 @@ #include <array> #include <string> #include "common/common.h" +#include "core/hle/result.h" typedef u32 Handle; typedef s32 Result; @@ -52,21 +53,19 @@ public: virtual Kernel::HandleType GetHandleType() const = 0; /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code + * Synchronize kernel object. + * @return True if the current thread should wait as a result of the sync */ - virtual Result SyncRequest(bool* wait) { + virtual ResultVal<bool> SyncRequest() { ERROR_LOG(KERNEL, "(UNIMPLEMENTED)"); - return -1; + return UnimplementedFunction(ErrorModule::Kernel); } /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code + * Wait for kernel object to synchronize. + * @return True if the current thread should wait as a result of the wait */ - virtual Result WaitSynchronization(bool* wait) = 0; + virtual ResultVal<bool> WaitSynchronization() = 0; }; class ObjectPool : NonCopyable { @@ -80,38 +79,29 @@ public: static Object* CreateByIDType(int type); template <class T> - u32 Destroy(Handle handle) { - u32 error; - if (Get<T>(handle, error)) { + void Destroy(Handle handle) { + if (Get<T>(handle)) { occupied[handle - HANDLE_OFFSET] = false; delete pool[handle - HANDLE_OFFSET]; } - return error; } bool IsValid(Handle handle); template <class T> - T* Get(Handle handle, u32& outError) { + T* Get(Handle handle) { if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { - // Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP - if (handle != 0 && (u32)handle != 0x80020001) { + if (handle != 0) { WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); } - outError = 0;//T::GetMissingErrorCode(); - return 0; + return nullptr; } else { - // Previously we had a dynamic_cast here, but since RTTI was disabled traditionally, - // it just acted as a static case and everything worked. This means that we will never - // see the Wrong type object error below, but we'll just have to live with that danger. - T* t = static_cast<T*>(pool[handle - HANDLE_OFFSET]); - if (t == 0 || t->GetHandleType() != T::GetStaticHandleType()) { + Object* t = pool[handle - HANDLE_OFFSET]; + if (t->GetHandleType() != T::GetStaticHandleType()) { WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle); - outError = 0;//T::GetMissingErrorCode(); - return 0; + return nullptr; } - outError = 0;//SCE_KERNEL_ERROR_OK; - return t; + return static_cast<T*>(t); } } diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 31129fd86..b303ba128 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -27,31 +27,20 @@ public: std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex std::string name; ///< Name of mutex (optional) - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) override { + ResultVal<bool> SyncRequest() override { // TODO(bunnei): ImplementMe locked = true; - return 0; + return MakeResult<bool>(false); } - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { + ResultVal<bool> WaitSynchronization() override { // TODO(bunnei): ImplementMe - *wait = locked; - + bool wait = locked; if (locked) { Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); } - return 0; + return MakeResult<bool>(wait); } }; @@ -119,15 +108,17 @@ bool ReleaseMutex(Mutex* mutex) { * Releases a mutex * @param handle Handle to mutex to release */ -Result ReleaseMutex(Handle handle) { - Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle); - - _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!"); +ResultCode ReleaseMutex(Handle handle) { + Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle); + if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!ReleaseMutex(mutex)) { - return -1; + // 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 0; + return RESULT_SUCCESS; } /** diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 313ba6fee..155449f95 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -13,9 +13,8 @@ namespace Kernel { /** * Releases a mutex * @param handle Handle to mutex to release - * @return Result of operation, 0 on success, otherwise error code */ -Result ReleaseMutex(Handle handle); +ResultCode ReleaseMutex(Handle handle); /** * Creates a mutex diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index 7ef3e54cc..cfcc0e0b7 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -16,15 +16,10 @@ public: static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; } - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { + ResultVal<bool> WaitSynchronization() override { // TODO(bunnei): ImplementMe ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); - return 0; + return UnimplementedFunction(ErrorModule::OS); } u32 base_address; ///< Address of shared memory block in RAM @@ -48,11 +43,6 @@ SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { return shared_memory; } -/** - * 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) { Handle handle; CreateSharedMemory(handle, name); @@ -67,39 +57,36 @@ Handle CreateSharedMemory(const std::string& name) { * @param other_permissions Memory block map other permissions (specified by SVC field) * @return Result of operation, 0 on success, otherwise error code */ -Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, +ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, MemoryPermission other_permissions) { if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", handle, address); - return -1; + return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, + ErrorSummary::InvalidArgument, ErrorLevel::Permanent); } - SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); - _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); + SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); + if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); shared_memory->base_address = address; shared_memory->permissions = permissions; shared_memory->other_permissions = other_permissions; - return 0; + return RESULT_SUCCESS; } -/** - * 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 - */ -u8* GetSharedMemoryPointer(Handle handle, u32 offset) { - SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); - _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); +ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { + SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); + if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); if (0 != shared_memory->base_address) - return Memory::GetPointer(shared_memory->base_address + offset); + return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset)); ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle); - return nullptr; + // TODO(yuriks): Verify error code. + return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, + ErrorSummary::InvalidState, ErrorLevel::Permanent); } } // namespace diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 0aec03538..304cf5b67 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -32,9 +32,8 @@ Handle CreateSharedMemory(const std::string& name="Unknown"); * @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 */ -Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, +ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions, MemoryPermission other_permissions); /** @@ -43,6 +42,6 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, * @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 */ -u8* GetSharedMemoryPointer(Handle handle, u32 offset); +ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset); } // namespace diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cc70cbca7..f3f54a4e9 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -11,10 +11,11 @@ #include "common/thread_queue_list.h" #include "core/core.h" -#include "core/mem_map.h" #include "core/hle/hle.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" +#include "core/hle/result.h" +#include "core/mem_map.h" namespace Kernel { @@ -33,21 +34,17 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } - /** - * Wait for kernel object to synchronize - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result WaitSynchronization(bool* wait) override { - if (status != THREADSTATUS_DORMANT) { + ResultVal<bool> WaitSynchronization() override { + const bool wait = status != THREADSTATUS_DORMANT; + if (wait) { Handle thread = GetCurrentThreadHandle(); if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { waiting_threads.push_back(thread); } WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); - *wait = true; } - return 0; + + return MakeResult<bool>(wait); } ThreadContext context; @@ -144,27 +141,22 @@ void ChangeReadyState(Thread* t, bool ready) { } /// Verify that a thread has not been released from waiting -inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { - Thread* thread = g_object_pool.GetFast<Thread>(handle); - _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); - - if (type != thread->wait_type || wait_handle != thread->wait_handle) - return false; - - return true; +inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) { + _dbg_assert_(KERNEL, thread != nullptr); + return type == thread->wait_type && wait_handle == thread->wait_handle; } /// Stops the current thread -void StopThread(Handle handle, const char* reason) { - Thread* thread = g_object_pool.GetFast<Thread>(handle); - _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); +ResultCode StopThread(Handle handle, const char* reason) { + Thread* thread = g_object_pool.Get<Thread>(handle); + if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); ChangeReadyState(thread, false); thread->status = THREADSTATUS_DORMANT; - for (size_t i = 0; i < thread->waiting_threads.size(); ++i) { - const Handle waiting_thread = thread->waiting_threads[i]; + for (Handle waiting_handle : thread->waiting_threads) { + Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { - ResumeThreadFromWait(waiting_thread); + ResumeThreadFromWait(waiting_handle); } } thread->waiting_threads.clear(); @@ -172,6 +164,8 @@ void StopThread(Handle handle, const char* reason) { // Stopped threads are never waiting. thread->wait_type = WAITTYPE_NONE; thread->wait_handle = 0; + + return RESULT_SUCCESS; } /// Changes a threads state @@ -195,13 +189,15 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { s32 priority = THREADPRIO_LOWEST; // Iterate through threads, find highest priority thread that is waiting to be arbitrated... - for (const auto& handle : thread_queue) { + for (Handle handle : thread_queue) { + Thread* thread = g_object_pool.Get<Thread>(handle); // TODO(bunnei): Verify arbiter address... - if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) + if (!VerifyWait(thread, WAITTYPE_ARB, arbiter)) continue; - Thread* thread = g_object_pool.GetFast<Thread>(handle); + if (thread == nullptr) + continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. if(thread->current_priority <= priority) { highest_priority_thread = handle; priority = thread->current_priority; @@ -218,10 +214,11 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { void ArbitrateAllThreads(u32 arbiter, u32 address) { // Iterate through threads, find highest priority thread that is waiting to be arbitrated... - for (const auto& handle : thread_queue) { + for (Handle handle : thread_queue) { + Thread* thread = g_object_pool.Get<Thread>(handle); // TODO(bunnei): Verify arbiter address... - if (VerifyWait(handle, WAITTYPE_ARB, arbiter)) + if (VerifyWait(thread, WAITTYPE_ARB, arbiter)) ResumeThreadFromWait(handle); } } @@ -272,7 +269,7 @@ Thread* NextThread() { if (next == 0) { return nullptr; } - return Kernel::g_object_pool.GetFast<Thread>(next); + return Kernel::g_object_pool.Get<Thread>(next); } /** @@ -289,8 +286,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle) { - u32 error; - Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error); + Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); if (thread) { thread->status &= ~THREADSTATUS_WAIT; if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { @@ -378,19 +374,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 } /// Get the priority of the thread specified by handle -u32 GetThreadPriority(const Handle handle) { - Thread* thread = g_object_pool.GetFast<Thread>(handle); - _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); - return thread->current_priority; +ResultVal<u32> GetThreadPriority(const Handle handle) { + Thread* thread = g_object_pool.Get<Thread>(handle); + if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); + + return MakeResult<u32>(thread->current_priority); } /// Set the priority of the thread specified by handle -Result SetThreadPriority(Handle handle, s32 priority) { +ResultCode SetThreadPriority(Handle handle, s32 priority) { Thread* thread = nullptr; if (!handle) { thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? } else { - thread = g_object_pool.GetFast<Thread>(handle); + thread = g_object_pool.Get<Thread>(handle); + if (thread == nullptr) { + return InvalidHandle(ErrorModule::Kernel); + } } _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); @@ -417,7 +417,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { thread_ready_queue.push_back(thread->current_priority, handle); } - return 0; + return RESULT_SUCCESS; } /// Sets up the primary application thread diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 2a43797ee..ce63a70d3 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -6,6 +6,7 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" enum ThreadPriority { THREADPRIO_HIGHEST = 0, ///< Highest thread priority @@ -55,7 +56,7 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); void Reschedule(); /// Stops the current thread -void StopThread(Handle thread, const char* reason); +ResultCode StopThread(Handle thread, const char* reason); /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle); @@ -80,10 +81,10 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHa void WaitThread_Synchronization(); /// Get the priority of the thread specified by handle -u32 GetThreadPriority(const Handle handle); +ResultVal<u32> GetThreadPriority(const Handle handle); /// Set the priority of the thread specified by handle -Result SetThreadPriority(Handle handle, s32 priority); +ResultCode SetThreadPriority(Handle handle, s32 priority); /// Initialize threading void ThreadingInit(); |