Merge pull request #4396 from FearlessTobi/open-delays
fs_user: Add a delay for each file open
This commit is contained in:
		| @@ -11,6 +11,7 @@ | |||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/swap.h" | #include "common/swap.h" | ||||||
|  | #include "core/file_sys/delay_generator.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
|  |  | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
| @@ -153,6 +154,18 @@ public: | |||||||
|      * @return The number of free bytes in the archive |      * @return The number of free bytes in the archive | ||||||
|      */ |      */ | ||||||
|     virtual u64 GetFreeBytes() const = 0; |     virtual u64 GetFreeBytes() const = 0; | ||||||
|  |  | ||||||
|  |     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<DefaultDelayGenerator>(); | ||||||
|  |         return delay_generator->GetOpenDelayNs(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  |     std::unique_ptr<DelayGenerator> delay_generator; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class ArchiveFactory : NonCopyable { | class ArchiveFactory : NonCopyable { | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ private: | |||||||
| class ExtSaveDataDelayGenerator : public DelayGenerator { | class ExtSaveDataDelayGenerator : public DelayGenerator { | ||||||
| public: | public: | ||||||
|     u64 GetReadDelayNs(std::size_t length) override { |     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 |         // not for extsaveData | ||||||
|         // For now we will take that |         // For now we will take that | ||||||
|         static constexpr u64 slope(183); |         static constexpr u64 slope(183); | ||||||
| @@ -69,6 +69,14 @@ public: | |||||||
|             std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); |             std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); | ||||||
|         return ipc_delay_nanoseconds; |         return ipc_delay_nanoseconds; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     u64 GetOpenDelayNs() override { | ||||||
|  |         // 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; | ||||||
|  |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -80,7 +88,11 @@ public: | |||||||
|  */ |  */ | ||||||
| class ExtSaveDataArchive : public SaveDataArchive { | class ExtSaveDataArchive : public SaveDataArchive { | ||||||
| public: | public: | ||||||
|     explicit ExtSaveDataArchive(const std::string& mount_point) : SaveDataArchive(mount_point) {} |     explicit ExtSaveDataArchive(const std::string& mount_point, | ||||||
|  |                                 std::unique_ptr<DelayGenerator> delay_generator_) | ||||||
|  |         : SaveDataArchive(mount_point) { | ||||||
|  |         delay_generator = std::move(delay_generator_); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     std::string GetName() const override { |     std::string GetName() const override { | ||||||
|         return "ExtSaveDataArchive: " + mount_point; |         return "ExtSaveDataArchive: " + mount_point; | ||||||
| @@ -232,7 +244,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons | |||||||
|             return ERR_NOT_FORMATTED; |             return ERR_NOT_FORMATTED; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     auto archive = std::make_unique<ExtSaveDataArchive>(fullpath); |     std::unique_ptr<DelayGenerator> delay_generator = std::make_unique<ExtSaveDataDelayGenerator>(); | ||||||
|  |     auto archive = std::make_unique<ExtSaveDataArchive>(fullpath, std::move(delay_generator)); | ||||||
|     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,6 +29,14 @@ public: | |||||||
|         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); |         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); | ||||||
|         return IPCDelayNanoseconds; |         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<std::unique_ptr<FileBackend>> SDMCArchive::OpenFile(const Path& path, | ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFile(const Path& path, | ||||||
| @@ -378,7 +386,8 @@ bool ArchiveFactory_SDMC::Initialize() { | |||||||
|  |  | ||||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path, | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path, | ||||||
|                                                                      u64 program_id) { |                                                                      u64 program_id) { | ||||||
|     auto archive = std::make_unique<SDMCArchive>(sdmc_directory); |     std::unique_ptr<DelayGenerator> delay_generator = std::make_unique<SDMCDelayGenerator>(); | ||||||
|  |     auto archive = std::make_unique<SDMCArchive>(sdmc_directory, std::move(delay_generator)); | ||||||
|     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,7 +17,11 @@ namespace FileSys { | |||||||
| /// Archive backend for SDMC archive | /// Archive backend for SDMC archive | ||||||
| class SDMCArchive : public ArchiveBackend { | class SDMCArchive : public ArchiveBackend { | ||||||
| public: | public: | ||||||
|     explicit SDMCArchive(const std::string& mount_point_) : mount_point(mount_point_) {} |     explicit SDMCArchive(const std::string& mount_point_, | ||||||
|  |                          std::unique_ptr<DelayGenerator> delay_generator_) | ||||||
|  |         : mount_point(mount_point_) { | ||||||
|  |         delay_generator = std::move(delay_generator_); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     std::string GetName() const override { |     std::string GetName() const override { | ||||||
|         return "SDMCArchive: " + mount_point; |         return "SDMCArchive: " + mount_point; | ||||||
|   | |||||||
| @@ -15,6 +15,28 @@ | |||||||
|  |  | ||||||
| namespace FileSys { | 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<u64>(static_cast<u64>(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<std::unique_ptr<FileBackend>> SDMCWriteOnlyArchive::OpenFile(const Path& path, | ResultVal<std::unique_ptr<FileBackend>> SDMCWriteOnlyArchive::OpenFile(const Path& path, | ||||||
|                                                                        const Mode& mode) const { |                                                                        const Mode& mode) const { | ||||||
|     if (mode.read_flag) { |     if (mode.read_flag) { | ||||||
| @@ -51,7 +73,10 @@ bool ArchiveFactory_SDMCWriteOnly::Initialize() { | |||||||
|  |  | ||||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path, | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path, | ||||||
|                                                                               u64 program_id) { |                                                                               u64 program_id) { | ||||||
|     auto archive = std::make_unique<SDMCWriteOnlyArchive>(sdmc_directory); |     std::unique_ptr<DelayGenerator> delay_generator = | ||||||
|  |         std::make_unique<SDMCWriteOnlyDelayGenerator>(); | ||||||
|  |     auto archive = | ||||||
|  |         std::make_unique<SDMCWriteOnlyArchive>(sdmc_directory, std::move(delay_generator)); | ||||||
|     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,7 +19,9 @@ namespace FileSys { | |||||||
|  */ |  */ | ||||||
| class SDMCWriteOnlyArchive : public SDMCArchive { | class SDMCWriteOnlyArchive : public SDMCArchive { | ||||||
| public: | public: | ||||||
|     explicit SDMCWriteOnlyArchive(const std::string& mount_point) : SDMCArchive(mount_point) {} |     explicit SDMCWriteOnlyArchive(const std::string& mount_point, | ||||||
|  |                                   std::unique_ptr<DelayGenerator> delay_generator_) | ||||||
|  |         : SDMCArchive(mount_point, std::move(delay_generator_)) {} | ||||||
|  |  | ||||||
|     std::string GetName() const override { |     std::string GetName() const override { | ||||||
|         return "SDMCWriteOnlyArchive: " + mount_point; |         return "SDMCWriteOnlyArchive: " + mount_point; | ||||||
|   | |||||||
| @@ -19,4 +19,11 @@ u64 DefaultDelayGenerator::GetReadDelayNs(std::size_t length) { | |||||||
|     return IPCDelayNanoseconds; |     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 | } // namespace FileSys | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ class DelayGenerator { | |||||||
| public: | public: | ||||||
|     virtual ~DelayGenerator(); |     virtual ~DelayGenerator(); | ||||||
|     virtual u64 GetReadDelayNs(std::size_t length) = 0; |     virtual u64 GetReadDelayNs(std::size_t length) = 0; | ||||||
|  |     virtual u64 GetOpenDelayNs() = 0; | ||||||
|  |  | ||||||
|     // TODO (B3N30): Add getter for all other file/directory io operations |     // TODO (B3N30): Add getter for all other file/directory io operations | ||||||
| }; | }; | ||||||
| @@ -20,6 +21,7 @@ public: | |||||||
| class DefaultDelayGenerator : public DelayGenerator { | class DefaultDelayGenerator : public DelayGenerator { | ||||||
| public: | public: | ||||||
|     u64 GetReadDelayNs(std::size_t length) override; |     u64 GetReadDelayNs(std::size_t length) override; | ||||||
|  |     u64 GetOpenDelayNs() override; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace FileSys | } // namespace FileSys | ||||||
|   | |||||||
| @@ -55,6 +55,15 @@ public: | |||||||
|         return delay_generator->GetReadDelayNs(length); |         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<DefaultDelayGenerator>(); | ||||||
|  |         return delay_generator->GetOpenDelayNs(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Get the size of the file in bytes |      * Get the size of the file in bytes | ||||||
|      * @return Size of the file in bytes |      * @return Size of the file in bytes | ||||||
|   | |||||||
| @@ -14,7 +14,11 @@ | |||||||
|  |  | ||||||
| namespace FileSys { | namespace FileSys { | ||||||
|  |  | ||||||
| IVFCArchive::IVFCArchive(std::shared_ptr<RomFSReader> file) : romfs_file(std::move(file)) {} | IVFCArchive::IVFCArchive(std::shared_ptr<RomFSReader> file, | ||||||
|  |                          std::unique_ptr<DelayGenerator> delay_generator_) | ||||||
|  |     : romfs_file(std::move(file)) { | ||||||
|  |     delay_generator = std::move(delay_generator_); | ||||||
|  | } | ||||||
|  |  | ||||||
| std::string IVFCArchive::GetName() const { | std::string IVFCArchive::GetName() const { | ||||||
|     return "IVFC"; |     return "IVFC"; | ||||||
|   | |||||||
| @@ -31,6 +31,13 @@ class IVFCDelayGenerator : public DelayGenerator { | |||||||
|         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); |         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); | ||||||
|         return IPCDelayNanoseconds; |         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 { | class RomFSDelayGenerator : public DelayGenerator { | ||||||
| @@ -45,6 +52,14 @@ public: | |||||||
|         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); |         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); | ||||||
|         return IPCDelayNanoseconds; |         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 { | class ExeFSDelayGenerator : public DelayGenerator { | ||||||
| @@ -59,6 +74,14 @@ public: | |||||||
|         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); |         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); | ||||||
|         return IPCDelayNanoseconds; |         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 { | class IVFCArchive : public ArchiveBackend { | ||||||
| public: | public: | ||||||
|     IVFCArchive(std::shared_ptr<RomFSReader> file); |     IVFCArchive(std::shared_ptr<RomFSReader> file, | ||||||
|  |                 std::unique_ptr<DelayGenerator> delay_generator_); | ||||||
|  |  | ||||||
|     std::string GetName() const override; |     std::string GetName() const override; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,6 +25,14 @@ public: | |||||||
|         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); |         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(length) * slope + offset, minimum); | ||||||
|         return IPCDelayNanoseconds; |         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<std::unique_ptr<FileBackend>> SaveDataArchive::OpenFile(const Path& path, | ResultVal<std::unique_ptr<FileBackend>> SaveDataArchive::OpenFile(const Path& path, | ||||||
|   | |||||||
| @@ -77,19 +77,21 @@ ResultCode ArchiveManager::RegisterArchiveType(std::unique_ptr<FileSys::ArchiveF | |||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
| ResultVal<std::shared_ptr<File>> ArchiveManager::OpenFileFromArchive(ArchiveHandle archive_handle, | std::tuple<ResultVal<std::shared_ptr<File>>, std::chrono::nanoseconds> | ||||||
|                                                                      const FileSys::Path& path, | ArchiveManager::OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, | ||||||
|                                                                      const FileSys::Mode mode) { |                                     const FileSys::Mode mode) { | ||||||
|     ArchiveBackend* archive = GetArchive(archive_handle); |     ArchiveBackend* archive = GetArchive(archive_handle); | ||||||
|     if (archive == nullptr) |     if (archive == nullptr) | ||||||
|         return FileSys::ERR_INVALID_ARCHIVE_HANDLE; |         return std::make_tuple(FileSys::ERR_INVALID_ARCHIVE_HANDLE, | ||||||
|  |                                static_cast<std::chrono::nanoseconds>(0)); | ||||||
|  |  | ||||||
|  |     std::chrono::nanoseconds open_timeout_ns{archive->GetOpenDelayNs()}; | ||||||
|     auto backend = archive->OpenFile(path, mode); |     auto backend = archive->OpenFile(path, mode); | ||||||
|     if (backend.Failed()) |     if (backend.Failed()) | ||||||
|         return backend.Code(); |         return std::make_tuple(backend.Code(), open_timeout_ns); | ||||||
|  |  | ||||||
|     auto file = std::shared_ptr<File>(new File(system, std::move(backend).Unwrap(), path)); |     auto file = std::shared_ptr<File>(new File(system, std::move(backend).Unwrap(), path)); | ||||||
|     return MakeResult<std::shared_ptr<File>>(std::move(file)); |     return std::make_tuple(MakeResult<std::shared_ptr<File>>(std::move(file)), open_timeout_ns); | ||||||
| } | } | ||||||
|  |  | ||||||
| ResultCode ArchiveManager::DeleteFileFromArchive(ArchiveHandle archive_handle, | ResultCode ArchiveManager::DeleteFileFromArchive(ArchiveHandle archive_handle, | ||||||
|   | |||||||
| @@ -77,11 +77,10 @@ public: | |||||||
|      * @param archive_handle Handle to an open Archive object |      * @param archive_handle Handle to an open Archive object | ||||||
|      * @param path Path to the File inside of the Archive |      * @param path Path to the File inside of the Archive | ||||||
|      * @param mode Mode under which to open the File |      * @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<std::shared_ptr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |     std::tuple<ResultVal<std::shared_ptr<File>>, std::chrono::nanoseconds> OpenFileFromArchive( | ||||||
|                                                          const FileSys::Path& path, |         ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); | ||||||
|                                                          const FileSys::Mode mode); |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Delete a File from an Archive |      * Delete a File from an Archive | ||||||
|   | |||||||
| @@ -71,12 +71,12 @@ void File::Read(Kernel::HLERequestContext& ctx) { | |||||||
|     rb.PushMappedBuffer(buffer); |     rb.PushMappedBuffer(buffer); | ||||||
|  |  | ||||||
|     std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)}; |     std::chrono::nanoseconds read_timeout_ns{backend->GetReadDelayNs(length)}; | ||||||
|     ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), "file::read", |     ctx.SleepClientThread( | ||||||
|                           read_timeout_ns, |         system.Kernel().GetThreadManager().GetCurrentThread(), "file::read", read_timeout_ns, | ||||||
|                           [](Kernel::SharedPtr<Kernel::Thread> thread, |         [](Kernel::SharedPtr<Kernel::Thread> /*thread*/, Kernel::HLERequestContext& /*ctx*/, | ||||||
|                              Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { |            Kernel::ThreadWakeupReason /*reason*/) { | ||||||
|                               // Nothing to do here |             // Nothing to do here | ||||||
|                           }); |         }); | ||||||
| } | } | ||||||
|  |  | ||||||
| void File::Write(Kernel::HLERequestContext& ctx) { | void File::Write(Kernel::HLERequestContext& ctx) { | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ | |||||||
| #include "core/hle/ipc_helpers.h" | #include "core/hle/ipc_helpers.h" | ||||||
| #include "core/hle/kernel/client_port.h" | #include "core/hle/kernel/client_port.h" | ||||||
| #include "core/hle/kernel/client_session.h" | #include "core/hle/kernel/client_session.h" | ||||||
|  | #include "core/hle/kernel/event.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/kernel/server_session.h" | #include "core/hle/kernel/server_session.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| @@ -59,7 +60,7 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) { | |||||||
|  |  | ||||||
|     LOG_DEBUG(Service_FS, "path={}, mode={} attrs={}", file_path.DebugStr(), mode.hex, attributes); |     LOG_DEBUG(Service_FS, "path={}, mode={} attrs={}", file_path.DebugStr(), mode.hex, attributes); | ||||||
|  |  | ||||||
|     ResultVal<std::shared_ptr<File>> file_res = |     const auto [file_res, open_timeout_ns] = | ||||||
|         archives.OpenFileFromArchive(archive_handle, file_path, mode); |         archives.OpenFileFromArchive(archive_handle, file_path, mode); | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(file_res.Code()); |     rb.Push(file_res.Code()); | ||||||
| @@ -70,6 +71,13 @@ void FS_USER::OpenFile(Kernel::HLERequestContext& ctx) { | |||||||
|         rb.PushMoveObjects<Kernel::Object>(nullptr); |         rb.PushMoveObjects<Kernel::Object>(nullptr); | ||||||
|         LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr()); |         LOG_ERROR(Service_FS, "failed to get a handle for file {}", file_path.DebugStr()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     ctx.SleepClientThread( | ||||||
|  |         system.Kernel().GetThreadManager().GetCurrentThread(), "fs_user::open", open_timeout_ns, | ||||||
|  |         [](Kernel::SharedPtr<Kernel::Thread> /*thread*/, Kernel::HLERequestContext& /*ctx*/, | ||||||
|  |            Kernel::ThreadWakeupReason /*reason*/) { | ||||||
|  |             // Nothing to do here | ||||||
|  |         }); | ||||||
| } | } | ||||||
|  |  | ||||||
| void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { | void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { | ||||||
| @@ -110,7 +118,7 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { | |||||||
|     } |     } | ||||||
|     SCOPE_EXIT({ archives.CloseArchive(*archive_handle); }); |     SCOPE_EXIT({ archives.CloseArchive(*archive_handle); }); | ||||||
|  |  | ||||||
|     ResultVal<std::shared_ptr<File>> file_res = |     const auto [file_res, open_timeout_ns] = | ||||||
|         archives.OpenFileFromArchive(*archive_handle, file_path, mode); |         archives.OpenFileFromArchive(*archive_handle, file_path, mode); | ||||||
|     rb.Push(file_res.Code()); |     rb.Push(file_res.Code()); | ||||||
|     if (file_res.Succeeded()) { |     if (file_res.Succeeded()) { | ||||||
| @@ -121,6 +129,14 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { | |||||||
|         LOG_ERROR(Service_FS, "failed to get a handle for file {} mode={} attributes={}", |         LOG_ERROR(Service_FS, "failed to get a handle for file {} mode={} attributes={}", | ||||||
|                   file_path.DebugStr(), mode.hex, attributes); |                   file_path.DebugStr(), mode.hex, attributes); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     ctx.SleepClientThread(system.Kernel().GetThreadManager().GetCurrentThread(), | ||||||
|  |                           "fs_user::open_directly", open_timeout_ns, | ||||||
|  |                           [](Kernel::SharedPtr<Kernel::Thread> /*thread*/, | ||||||
|  |                              Kernel::HLERequestContext& /*ctx*/, | ||||||
|  |                              Kernel::ThreadWakeupReason /*reason*/) { | ||||||
|  |                               // Nothing to do here | ||||||
|  |                           }); | ||||||
| } | } | ||||||
|  |  | ||||||
| void FS_USER::DeleteFile(Kernel::HLERequestContext& ctx) { | void FS_USER::DeleteFile(Kernel::HLERequestContext& ctx) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user