From fc7e6c9cc90699f587c7b2ebe73cad6adad25d00 Mon Sep 17 00:00:00 2001 From: fearlessTobi Date: Fri, 2 Nov 2018 18:11:22 +0100 Subject: [PATCH 1/3] fs_user: Add a delay for each file open --- src/core/file_sys/archive_backend.h | 22 +++++++++++++++++ src/core/file_sys/archive_extsavedata.cpp | 19 ++++++++++++--- src/core/file_sys/archive_sdmc.cpp | 11 ++++++++- src/core/file_sys/archive_sdmc.h | 6 ++++- src/core/file_sys/archive_sdmcwriteonly.cpp | 27 ++++++++++++++++++++- src/core/file_sys/archive_sdmcwriteonly.h | 4 ++- src/core/file_sys/delay_generator.cpp | 7 ++++++ src/core/file_sys/delay_generator.h | 2 ++ src/core/file_sys/file_backend.h | 9 +++++++ src/core/file_sys/ivfc_archive.cpp | 6 ++++- src/core/file_sys/ivfc_archive.h | 26 +++++++++++++++++++- src/core/file_sys/savedata_archive.cpp | 8 ++++++ src/core/hle/service/fs/archive.h | 4 +-- src/core/hle/service/fs/fs_user.cpp | 13 ++++++++++ 14 files changed, 153 insertions(+), 11 deletions(-) diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index 1a57e12d3..1e9ee2c60 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h @@ -12,6 +12,7 @@ #include "common/common_types.h" #include "common/swap.h" #include "core/hle/result.h" +#include "delay_generator.h" namespace FileSys { @@ -153,6 +154,27 @@ public: * @return The number of free bytes in the archive */ virtual u64 GetFreeBytes() const = 0; + + u64 GetReadDelayNs(std::size_t length) { + if (delay_generator != nullptr) { + return delay_generator->GetReadDelayNs(length); + } + LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default"); + delay_generator = std::make_unique(); + return delay_generator->GetReadDelayNs(length); + } + + u64 GetOpenDelayNs() { + if (delay_generator != nullptr) { + return delay_generator->GetOpenDelayNs(); + } + LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default"); + delay_generator = std::make_unique(); + return delay_generator->GetOpenDelayNs(); + } + +protected: + std::unique_ptr delay_generator; }; class ArchiveFactory : NonCopyable { diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 2839483f5..519c233de 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -59,7 +59,7 @@ private: class ExtSaveDataDelayGenerator : public DelayGenerator { public: u64 GetReadDelayNs(std::size_t length) override { - // This is the delay measured for a savedate read, + // This is the delay measured for a savedata read, // not for extsaveData // For now we will take that static constexpr u64 slope(183); @@ -69,6 +69,14 @@ public: std::max(static_cast(length) * slope + offset, minimum); return ipc_delay_nanoseconds; } + + u64 GetOpenDelayNs() override { + // This is the delay measured for a savedata open, + // not for extsaveData + // For now we will take that + static constexpr u64 IPCDelayNanoseconds(269082); + return IPCDelayNanoseconds; + } }; /** @@ -80,7 +88,11 @@ public: */ class ExtSaveDataArchive : public SaveDataArchive { public: - explicit ExtSaveDataArchive(const std::string& mount_point) : SaveDataArchive(mount_point) {} + explicit ExtSaveDataArchive(const std::string& mount_point, + std::unique_ptr delay_generator_) + : SaveDataArchive(mount_point) { + delay_generator = std::move(delay_generator_); + } std::string GetName() const override { return "ExtSaveDataArchive: " + mount_point; @@ -232,7 +244,8 @@ ResultVal> ArchiveFactory_ExtSaveData::Open(cons return ERR_NOT_FORMATTED; } } - auto archive = std::make_unique(fullpath); + std::unique_ptr delay_generator = std::make_unique(); + auto archive = std::make_unique(fullpath, std::move(delay_generator)); return MakeResult>(std::move(archive)); } diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index cff4cd395..d2269fe7c 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp @@ -29,6 +29,14 @@ public: u64 IPCDelayNanoseconds = std::max(static_cast(length) * slope + offset, minimum); return IPCDelayNanoseconds; } + + u64 GetOpenDelayNs() override { + // This is the delay measured on O3DS and O2DS with + // https://gist.github.com/FearlessTobi/c37e143c314789251f98f2c45cd706d2 + // from the results the average of each length was taken. + static constexpr u64 IPCDelayNanoseconds(269082); + return IPCDelayNanoseconds; + } }; ResultVal> SDMCArchive::OpenFile(const Path& path, @@ -378,7 +386,8 @@ bool ArchiveFactory_SDMC::Initialize() { ResultVal> ArchiveFactory_SDMC::Open(const Path& path, u64 program_id) { - auto archive = std::make_unique(sdmc_directory); + std::unique_ptr delay_generator = std::make_unique(); + auto archive = std::make_unique(sdmc_directory, std::move(delay_generator)); return MakeResult>(std::move(archive)); } diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 637d4dc16..41d7b7c59 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h @@ -17,7 +17,11 @@ namespace FileSys { /// Archive backend for SDMC archive class SDMCArchive : public ArchiveBackend { public: - explicit SDMCArchive(const std::string& mount_point_) : mount_point(mount_point_) {} + explicit SDMCArchive(const std::string& mount_point_, + std::unique_ptr delay_generator_) + : mount_point(mount_point_) { + delay_generator = std::move(delay_generator_); + } std::string GetName() const override { return "SDMCArchive: " + mount_point; diff --git a/src/core/file_sys/archive_sdmcwriteonly.cpp b/src/core/file_sys/archive_sdmcwriteonly.cpp index b9534f12d..74552d751 100644 --- a/src/core/file_sys/archive_sdmcwriteonly.cpp +++ b/src/core/file_sys/archive_sdmcwriteonly.cpp @@ -15,6 +15,28 @@ namespace FileSys { +class SDMCWriteOnlyDelayGenerator : public DelayGenerator { +public: + u64 GetReadDelayNs(std::size_t length) override { + // This is the delay measured on O3DS and O2DS with + // https://gist.github.com/B3n30/ac40eac20603f519ff106107f4ac9182 + // from the results the average of each length was taken. + static constexpr u64 slope(183); + static constexpr u64 offset(524879); + static constexpr u64 minimum(631826); + u64 IPCDelayNanoseconds = std::max(static_cast(length) * slope + offset, minimum); + return IPCDelayNanoseconds; + } + + u64 GetOpenDelayNs() override { + // This is the delay measured on O3DS and O2DS with + // https://gist.github.com/FearlessTobi/c37e143c314789251f98f2c45cd706d2 + // from the results the average of each length was taken. + static constexpr u64 IPCDelayNanoseconds(269082); + return IPCDelayNanoseconds; + } +}; + ResultVal> SDMCWriteOnlyArchive::OpenFile(const Path& path, const Mode& mode) const { if (mode.read_flag) { @@ -51,7 +73,10 @@ bool ArchiveFactory_SDMCWriteOnly::Initialize() { ResultVal> ArchiveFactory_SDMCWriteOnly::Open(const Path& path, u64 program_id) { - auto archive = std::make_unique(sdmc_directory); + std::unique_ptr delay_generator = + std::make_unique(); + auto archive = + std::make_unique(sdmc_directory, std::move(delay_generator)); return MakeResult>(std::move(archive)); } diff --git a/src/core/file_sys/archive_sdmcwriteonly.h b/src/core/file_sys/archive_sdmcwriteonly.h index 050fc19c8..8191f053f 100644 --- a/src/core/file_sys/archive_sdmcwriteonly.h +++ b/src/core/file_sys/archive_sdmcwriteonly.h @@ -19,7 +19,9 @@ namespace FileSys { */ class SDMCWriteOnlyArchive : public SDMCArchive { public: - explicit SDMCWriteOnlyArchive(const std::string& mount_point) : SDMCArchive(mount_point) {} + explicit SDMCWriteOnlyArchive(const std::string& mount_point, + std::unique_ptr delay_generator_) + : SDMCArchive(mount_point, std::move(delay_generator_)) {} std::string GetName() const override { return "SDMCWriteOnlyArchive: " + mount_point; diff --git a/src/core/file_sys/delay_generator.cpp b/src/core/file_sys/delay_generator.cpp index 654550061..04f877f83 100644 --- a/src/core/file_sys/delay_generator.cpp +++ b/src/core/file_sys/delay_generator.cpp @@ -19,4 +19,11 @@ u64 DefaultDelayGenerator::GetReadDelayNs(std::size_t length) { return IPCDelayNanoseconds; } +u64 DefaultDelayGenerator::GetOpenDelayNs() { + // This is the delay measured for a romfs open. + // For now we will take that as a default + static constexpr u64 IPCDelayNanoseconds(9438006); + return IPCDelayNanoseconds; +} + } // namespace FileSys diff --git a/src/core/file_sys/delay_generator.h b/src/core/file_sys/delay_generator.h index 06ef97281..d530f2ee2 100644 --- a/src/core/file_sys/delay_generator.h +++ b/src/core/file_sys/delay_generator.h @@ -13,6 +13,7 @@ class DelayGenerator { public: virtual ~DelayGenerator(); virtual u64 GetReadDelayNs(std::size_t length) = 0; + virtual u64 GetOpenDelayNs() = 0; // TODO (B3N30): Add getter for all other file/directory io operations }; @@ -20,6 +21,7 @@ public: class DefaultDelayGenerator : public DelayGenerator { public: u64 GetReadDelayNs(std::size_t length) override; + u64 GetOpenDelayNs() override; }; } // namespace FileSys diff --git a/src/core/file_sys/file_backend.h b/src/core/file_sys/file_backend.h index 103b81d60..c865c98e8 100644 --- a/src/core/file_sys/file_backend.h +++ b/src/core/file_sys/file_backend.h @@ -55,6 +55,15 @@ public: return delay_generator->GetReadDelayNs(length); } + u64 GetOpenDelayNs() { + if (delay_generator != nullptr) { + return delay_generator->GetOpenDelayNs(); + } + LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default"); + delay_generator = std::make_unique(); + return delay_generator->GetOpenDelayNs(); + } + /** * Get the size of the file in bytes * @return Size of the file in bytes diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index 5a11e786d..ba16f8cd8 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp @@ -14,7 +14,11 @@ namespace FileSys { -IVFCArchive::IVFCArchive(std::shared_ptr file) : romfs_file(std::move(file)) {} +IVFCArchive::IVFCArchive(std::shared_ptr file, + std::unique_ptr delay_generator_) + : romfs_file(std::move(file)) { + delay_generator = std::move(delay_generator_); +} std::string IVFCArchive::GetName() const { return "IVFC"; diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h index ded0b9075..8168e04f4 100644 --- a/src/core/file_sys/ivfc_archive.h +++ b/src/core/file_sys/ivfc_archive.h @@ -31,6 +31,13 @@ class IVFCDelayGenerator : public DelayGenerator { u64 IPCDelayNanoseconds = std::max(static_cast(length) * slope + offset, minimum); return IPCDelayNanoseconds; } + + u64 GetOpenDelayNs() override { + // This is the delay measured for a romfs open. + // For now we will take that as a default + static constexpr u64 IPCDelayNanoseconds(9438006); + return IPCDelayNanoseconds; + } }; class RomFSDelayGenerator : public DelayGenerator { @@ -45,6 +52,14 @@ public: u64 IPCDelayNanoseconds = std::max(static_cast(length) * slope + offset, minimum); return IPCDelayNanoseconds; } + + u64 GetOpenDelayNs() override { + // This is the delay measured on O3DS and O2DS with + // https://gist.github.com/FearlessTobi/eb1d70619c65c7e6f02141d71e79a36e + // from the results the average of each length was taken. + static constexpr u64 IPCDelayNanoseconds(9438006); + return IPCDelayNanoseconds; + } }; class ExeFSDelayGenerator : public DelayGenerator { @@ -59,6 +74,14 @@ public: u64 IPCDelayNanoseconds = std::max(static_cast(length) * slope + offset, minimum); return IPCDelayNanoseconds; } + + u64 GetOpenDelayNs() override { + // This is the delay measured on O3DS and O2DS with + // https://gist.github.com/FearlessTobi/eb1d70619c65c7e6f02141d71e79a36e + // from the results the average of each length was taken. + static constexpr u64 IPCDelayNanoseconds(9438006); + return IPCDelayNanoseconds; + } }; /** @@ -68,7 +91,8 @@ public: */ class IVFCArchive : public ArchiveBackend { public: - IVFCArchive(std::shared_ptr file); + IVFCArchive(std::shared_ptr file, + std::unique_ptr delay_generator_); std::string GetName() const override; diff --git a/src/core/file_sys/savedata_archive.cpp b/src/core/file_sys/savedata_archive.cpp index b2569e498..8d7830468 100644 --- a/src/core/file_sys/savedata_archive.cpp +++ b/src/core/file_sys/savedata_archive.cpp @@ -25,6 +25,14 @@ public: u64 IPCDelayNanoseconds = std::max(static_cast(length) * slope + offset, minimum); return IPCDelayNanoseconds; } + + u64 GetOpenDelayNs() override { + // This is the delay measured on O3DS and O2DS with + // https://gist.github.com/FearlessTobi/c37e143c314789251f98f2c45cd706d2 + // from the results the average of each length was taken. + static constexpr u64 IPCDelayNanoseconds(269082); + return IPCDelayNanoseconds; + } }; ResultVal> SaveDataArchive::OpenFile(const Path& path, diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index c1dd2bd1b..45f6b7eec 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -234,6 +234,8 @@ public: /// Registers a new NCCH file with the SelfNCCH archive factory void RegisterSelfNCCH(Loader::AppLoader& app_loader); + ArchiveBackend* GetArchive(ArchiveHandle handle); + private: Core::System& system; @@ -248,8 +250,6 @@ private: /// Register all archive types void RegisterArchiveTypes(); - ArchiveBackend* GetArchive(ArchiveHandle handle); - /** * Map of registered archives, identified by id code. Once an archive is registered here, it is * never removed until UnregisterArchiveTypes is called. diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index bbcc2e6fd..c4b8843c3 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -16,6 +16,7 @@ #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/event.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/server_session.h" #include "core/hle/result.h" @@ -70,6 +71,18 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) { rb.PushMoveObjects(nullptr); LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr()); } + + auto archive = archives.GetArchive(archive_handle); + if (archive == nullptr) + return; + + std::chrono::nanoseconds open_timeout_ns{archive->GetOpenDelayNs()}; + ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), "fs_user::open", + open_timeout_ns, + [](Kernel::SharedPtr thread, + Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { + // Nothing to do here + }); } void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { From 5055a6c262bde4af32ea9f7f80ad94ca7d5f9db1 Mon Sep 17 00:00:00 2001 From: fearlessTobi Date: Fri, 2 Nov 2018 23:08:34 +0100 Subject: [PATCH 2/3] Address review comments --- src/core/file_sys/archive_backend.h | 11 +---------- src/core/hle/service/fs/archive.cpp | 14 ++++++++------ src/core/hle/service/fs/archive.h | 11 +++++------ src/core/hle/service/fs/file.cpp | 12 ++++++------ src/core/hle/service/fs/fs_user.cpp | 29 ++++++++++++++++------------- 5 files changed, 36 insertions(+), 41 deletions(-) diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index 1e9ee2c60..259ece84a 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h @@ -11,8 +11,8 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/file_sys/delay_generator.h" #include "core/hle/result.h" -#include "delay_generator.h" namespace FileSys { @@ -155,15 +155,6 @@ public: */ virtual u64 GetFreeBytes() const = 0; - u64 GetReadDelayNs(std::size_t length) { - if (delay_generator != nullptr) { - return delay_generator->GetReadDelayNs(length); - } - LOG_ERROR(Service_FS, "Delay generator was not initalized. Using default"); - delay_generator = std::make_unique(); - return delay_generator->GetReadDelayNs(length); - } - u64 GetOpenDelayNs() { if (delay_generator != nullptr) { return delay_generator->GetOpenDelayNs(); diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 184c319f0..6e179978b 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -77,19 +77,21 @@ ResultCode ArchiveManager::RegisterArchiveType(std::unique_ptr> ArchiveManager::OpenFileFromArchive(ArchiveHandle archive_handle, - const FileSys::Path& path, - const FileSys::Mode mode) { +std::tuple>, std::chrono::nanoseconds> +ArchiveManager::OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, + const FileSys::Mode mode) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return FileSys::ERR_INVALID_ARCHIVE_HANDLE; + return std::make_tuple(FileSys::ERR_INVALID_ARCHIVE_HANDLE, + static_cast(0)); + std::chrono::nanoseconds open_timeout_ns{archive->GetOpenDelayNs()}; auto backend = archive->OpenFile(path, mode); if (backend.Failed()) - return backend.Code(); + return std::make_tuple(backend.Code(), open_timeout_ns); auto file = std::shared_ptr(new File(system, std::move(backend).Unwrap(), path)); - return MakeResult>(std::move(file)); + return std::make_tuple(MakeResult>(std::move(file)), open_timeout_ns); } ResultCode ArchiveManager::DeleteFileFromArchive(ArchiveHandle archive_handle, diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index 45f6b7eec..862e74980 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -77,11 +77,10 @@ public: * @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 The opened File object + * @return Tuple of the opened File object and the open delay */ - ResultVal> OpenFileFromArchive(ArchiveHandle archive_handle, - const FileSys::Path& path, - const FileSys::Mode mode); + std::tuple>, std::chrono::nanoseconds> OpenFileFromArchive( + ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); /** * Delete a File from an Archive @@ -234,8 +233,6 @@ public: /// Registers a new NCCH file with the SelfNCCH archive factory void RegisterSelfNCCH(Loader::AppLoader& app_loader); - ArchiveBackend* GetArchive(ArchiveHandle handle); - private: Core::System& system; @@ -250,6 +247,8 @@ private: /// Register all archive types void RegisterArchiveTypes(); + ArchiveBackend* GetArchive(ArchiveHandle handle); + /** * Map of registered archives, identified by id code. Once an archive is registered here, it is * never removed until UnregisterArchiveTypes is called. diff --git a/src/core/hle/service/fs/file.cpp b/src/core/hle/service/fs/file.cpp index d4beda2c4..0edd93644 100644 --- a/src/core/hle/service/fs/file.cpp +++ b/src/core/hle/service/fs/file.cpp @@ -71,12 +71,12 @@ void File::Read(Kernel::HLERequestContext& ctx) { rb.PushMappedBuffer(buffer); std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)}; - ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), "file::read", - read_timeout_ns, - [](Kernel::SharedPtr thread, - Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { - // Nothing to do here - }); + ctx.SleepClientThread( + system.Kernel().GetThreadManager().GetCurrentThread(), "file::read", read_timeout_ns, + [](Kernel::SharedPtr /*thread*/, Kernel::HLERequestContext& /*ctx*/, + Kernel::ThreadWakeupReason /*reason*/) { + // Nothing to do here + }); } void File::Write(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index c4b8843c3..51bc18374 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -60,7 +60,7 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "path={}, mode={} attrs={}", file_path.DebugStr(), mode.hex, attributes); - ResultVal> file_res = + const auto [file_res, open_timeout_ns] = archives.OpenFileFromArchive(archive_handle, file_path, mode); IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); rb.Push(file_res.Code()); @@ -72,17 +72,12 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr()); } - auto archive = archives.GetArchive(archive_handle); - if (archive == nullptr) - return; - - std::chrono::nanoseconds open_timeout_ns{archive->GetOpenDelayNs()}; - ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), "fs_user::open", - open_timeout_ns, - [](Kernel::SharedPtr thread, - Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { - // Nothing to do here - }); + ctx.SleepClientThread( + system.Kernel().GetThreadManager().GetCurrentThread(), "fs_user::open", open_timeout_ns, + [](Kernel::SharedPtr /*thread*/, Kernel::HLERequestContext& /*ctx*/, + Kernel::ThreadWakeupReason /*reason*/) { + // Nothing to do here + }); } void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { @@ -123,7 +118,7 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { } SCOPE_EXIT({ archives.CloseArchive(*archive_handle); }); - ResultVal> file_res = + const auto [file_res, open_timeout_ns] = archives.OpenFileFromArchive(*archive_handle, file_path, mode); rb.Push(file_res.Code()); if (file_res.Succeeded()) { @@ -134,6 +129,14 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_FS, "failed to get a handle for file {} mode={} attributes={}", file_path.DebugStr(), mode.hex, attributes); } + + ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), + "fs_user::open_directly", open_timeout_ns, + [](Kernel::SharedPtr /*thread*/, + Kernel::HLERequestContext& /*ctx*/, + Kernel::ThreadWakeupReason /*reason*/) { + // Nothing to do here + }); } void FS_USER::DeleteFile(Kernel::HLERequestContext& ctx) { From 2999c8325eb3ca2ef071a36b66bf6046dca83edf Mon Sep 17 00:00:00 2001 From: fearlessTobi Date: Wed, 6 Mar 2019 17:59:28 +0100 Subject: [PATCH 3/3] archive_extsavedata: add correct FileOpen delays --- src/core/file_sys/archive_extsavedata.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 519c233de..efcdb2d7f 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -71,10 +71,10 @@ public: } u64 GetOpenDelayNs() override { - // This is the delay measured for a savedata open, - // not for extsaveData - // For now we will take that - static constexpr u64 IPCDelayNanoseconds(269082); + // This is the delay measured on N3DS with + // https://gist.github.com/FearlessTobi/929b68489f4abb2c6cf81d56970a20b4 + // from the results the average of each length was taken. + static constexpr u64 IPCDelayNanoseconds(3085068); return IPCDelayNanoseconds; } };