mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	fs_user: Add a delay for each file open
This commit is contained in:
		
							parent
							
								
									d0de727a97
								
							
						
					
					
						commit
						fc7e6c9cc9
					
				
					 14 changed files with 153 additions and 11 deletions
				
			
		|  | @ -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<DefaultDelayGenerator>(); | ||||
|         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(); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     std::unique_ptr<DelayGenerator> delay_generator; | ||||
| }; | ||||
| 
 | ||||
| class ArchiveFactory : NonCopyable { | ||||
|  |  | |||
|  | @ -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<u64>(static_cast<u64>(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<DelayGenerator> 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<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons | |||
|             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)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,14 @@ public: | |||
|         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>> SDMCArchive::OpenFile(const Path& path, | ||||
|  | @ -378,7 +386,8 @@ bool ArchiveFactory_SDMC::Initialize() { | |||
| 
 | ||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path, | ||||
|                                                                      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)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<DelayGenerator> delay_generator_) | ||||
|         : mount_point(mount_point_) { | ||||
|         delay_generator = std::move(delay_generator_); | ||||
|     } | ||||
| 
 | ||||
|     std::string GetName() const override { | ||||
|         return "SDMCArchive: " + mount_point; | ||||
|  |  | |||
|  | @ -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<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, | ||||
|                                                                        const Mode& mode) const { | ||||
|     if (mode.read_flag) { | ||||
|  | @ -51,7 +73,10 @@ bool ArchiveFactory_SDMCWriteOnly::Initialize() { | |||
| 
 | ||||
| ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path, | ||||
|                                                                               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)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<DelayGenerator> delay_generator_) | ||||
|         : SDMCArchive(mount_point, std::move(delay_generator_)) {} | ||||
| 
 | ||||
|     std::string GetName() const override { | ||||
|         return "SDMCWriteOnlyArchive: " + mount_point; | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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<DefaultDelayGenerator>(); | ||||
|         return delay_generator->GetOpenDelayNs(); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Get the size of the file in bytes | ||||
|      * @return Size of the file in bytes | ||||
|  |  | |||
|  | @ -14,7 +14,11 @@ | |||
| 
 | ||||
| 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 { | ||||
|     return "IVFC"; | ||||
|  |  | |||
|  | @ -31,6 +31,13 @@ class IVFCDelayGenerator : public DelayGenerator { | |||
|         u64 IPCDelayNanoseconds = std::max<u64>(static_cast<u64>(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<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/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<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/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<RomFSReader> file); | ||||
|     IVFCArchive(std::shared_ptr<RomFSReader> file, | ||||
|                 std::unique_ptr<DelayGenerator> delay_generator_); | ||||
| 
 | ||||
|     std::string GetName() const override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,6 +25,14 @@ public: | |||
|         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>> SaveDataArchive::OpenFile(const Path& path, | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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<Kernel::Object>(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<Kernel::Thread> thread, | ||||
|                              Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { | ||||
|                               // Nothing to do here
 | ||||
|                           }); | ||||
| } | ||||
| 
 | ||||
| void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue