mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-17 01:15:30 +00:00
Implement fs::file::write_gather (Vectored I/O)
This commit is contained in:
parent
31994dd3b2
commit
447029a700
@ -125,6 +125,7 @@ static fs::error to_error(DWORD e)
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/uio.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
@ -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<uchar>(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<open_mode> 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<unix_file>(fd);
|
||||
|
@ -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;
|
||||
|
@ -265,15 +265,18 @@ void spu_cache::add(const std::vector<u32>& func)
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate buffer
|
||||
const auto buf = std::make_unique<be_t<u32>[]>(func.size() + 1);
|
||||
be_t<u32> size = ::size32(func) - 1;
|
||||
be_t<u32> 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()
|
||||
|
Loading…
Reference in New Issue
Block a user