From 447029a70064e886d3b0b5ec24413ffd202420f1 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 3 Jun 2019 22:57:59 +0300 Subject: [PATCH] Implement fs::file::write_gather (Vectored I/O) --- Utilities/File.cpp | 40 ++++++++++++++++++++++++++++++++ Utilities/File.h | 15 ++++++++++++ rpcs3/Emu/Cell/SPURecompiler.cpp | 15 +++++++----- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 0a5ef837b6..6ae18395c0 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -125,6 +125,7 @@ static fs::error to_error(DWORD e) #include #include #include +#include #include #include #include @@ -203,6 +204,34 @@ namespace fs #endif } + u64 file_base::write_gather(const iovec_clone* buffers, u64 buf_count) + { + u64 total = 0; + + for (u64 i = 0; i < buf_count; i++) + { + if (!buffers[i].iov_base || buffers[i].iov_len + total < total) + { + g_tls_error = error::inval; + return -1; + } + + total += buffers[i].iov_len; + } + + const auto buf = std::make_unique(total); + + u64 copied = 0; + + for (u64 i = 0; i < buf_count; i++) + { + std::memcpy(buf.get() + copied, buffers[i].iov_base, buffers[i].iov_len); + copied += buffers[i].iov_len; + } + + return this->write(buf.get(), total); + } + dir_base::~dir_base() { } @@ -1157,6 +1186,17 @@ fs::file::file(const std::string& path, bs_t mode) { return m_fd; } + + u64 write_gather(const iovec_clone* buffers, u64 buf_count) override + { + static_assert(sizeof(iovec) == sizeof(iovec_clone), "Weird iovec size"); + static_assert(offsetof(iovec, iov_len) == offsetof(iovec_clone, iov_len), "Weird iovec::iov_len offset"); + + const auto result = ::writev(m_fd, (const iovec*)buffers, buf_count); + verify("file::write_gather" HERE), result != -1; + + return result; + } }; m_file = std::make_unique(fd); diff --git a/Utilities/File.h b/Utilities/File.h index fa434dee6d..9b802cdef7 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -65,6 +65,13 @@ namespace fs s64 ctime; }; + // Helper, layout is equal to iovec struct + struct iovec_clone + { + const void* iov_base; + std::size_t iov_len; + }; + // File handle base struct file_base { @@ -78,6 +85,7 @@ namespace fs virtual u64 seek(s64 offset, seek_mode whence) = 0; virtual u64 size() = 0; virtual native_handle get_handle(); + virtual u64 write_gather(const iovec_clone* buffers, u64 buf_count); }; // Directory entry (TODO) @@ -362,6 +370,13 @@ namespace fs // Get native handle if available native_handle get_handle() const; + // Gathered write + u64 write_gather(const iovec_clone* buffers, u64 buf_count) const + { + if (!m_file) xnull(); + return m_file->write_gather(buffers, buf_count); + } + #ifdef _WIN32 // Windows-specific function bool set_delete(bool autodelete = true) const; diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index c168c721ca..ff6dc304e4 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -265,15 +265,18 @@ void spu_cache::add(const std::vector& func) return; } - // Allocate buffer - const auto buf = std::make_unique[]>(func.size() + 1); + be_t size = ::size32(func) - 1; + be_t addr = func[0]; - buf[0] = ::size32(func) - 1; - buf[1] = func[0]; - std::memcpy(buf.get() + 2, func.data() + 1, func.size() * 4 - 4); + const fs::iovec_clone gather[3] + { + {&size, sizeof(size)}, + {&addr, sizeof(addr)}, + {func.data() + 1, func.size() * 4 - 4} + }; // Append data - m_file.write(buf.get(), func.size() * 4 + 4); + m_file.write_gather(gather, 3); } void spu_cache::initialize()