mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
sys_fs: Optimize concurrent file reads
This commit is contained in:
parent
f07e17f6aa
commit
4b827a8d9c
3 changed files with 36 additions and 14 deletions
|
@ -1854,8 +1854,9 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto file = std::as_const(all_files).find(file_path);
|
const auto file = std::as_const(all_files).find(file_path);
|
||||||
|
const u64 pos = fileSet->fileOffset;
|
||||||
|
|
||||||
if (file == all_files.cend() || file->second.size() <= fileSet->fileOffset)
|
if (file == all_files.cend() || file->second.size() <= pos)
|
||||||
{
|
{
|
||||||
cellSaveData.error("Failed to open file %s%s (size=%d, fileOffset=%d)", dir_path, file_path, file == all_files.cend() ? -1 : file->second.size(), fileSet->fileOffset);
|
cellSaveData.error("Failed to open file %s%s (size=%d, fileOffset=%d)", dir_path, file_path, file == all_files.cend() ? -1 : file->second.size(), fileSet->fileOffset);
|
||||||
savedata_result = CELL_SAVEDATA_ERROR_FAILURE;
|
savedata_result = CELL_SAVEDATA_ERROR_FAILURE;
|
||||||
|
@ -1863,8 +1864,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read from memory file to vm
|
// Read from memory file to vm
|
||||||
file->second.seek(fileSet->fileOffset);
|
const u64 rr = lv2_file::op_read(file->second, fileSet->fileBuf, fileSet->fileSize, pos);
|
||||||
const u64 rr = lv2_file::op_read(file->second, fileSet->fileBuf, fileSet->fileSize);
|
|
||||||
fileGet->excSize = ::narrow<u32>(rr);
|
fileGet->excSize = ::narrow<u32>(rr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
LOG_CHANNEL(sys_fs);
|
LOG_CHANNEL(sys_fs);
|
||||||
|
|
||||||
|
@ -371,7 +372,7 @@ lv2_fs_object::lv2_fs_object(utils::serial& ar, bool)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 lv2_file::op_read(const fs::file& file, vm::ptr<void> buf, u64 size)
|
u64 lv2_file::op_read(const fs::file& file, vm::ptr<void> buf, u64 size, u64 opt_pos)
|
||||||
{
|
{
|
||||||
// Copy data from intermediate buffer (avoid passing vm pointer to a native API)
|
// Copy data from intermediate buffer (avoid passing vm pointer to a native API)
|
||||||
std::vector<uchar> local_buf(std::min<u64>(size, 65536));
|
std::vector<uchar> local_buf(std::min<u64>(size, 65536));
|
||||||
|
@ -381,7 +382,7 @@ u64 lv2_file::op_read(const fs::file& file, vm::ptr<void> buf, u64 size)
|
||||||
while (result < size)
|
while (result < size)
|
||||||
{
|
{
|
||||||
const u64 block = std::min<u64>(size - result, local_buf.size());
|
const u64 block = std::min<u64>(size - result, local_buf.size());
|
||||||
const u64 nread = file.read(+local_buf.data(), block);
|
const u64 nread = (opt_pos == umax ? file.read(local_buf.data(), block) : file.read_at(opt_pos + result, local_buf.data(), block));
|
||||||
|
|
||||||
std::memcpy(static_cast<uchar*>(buf.get_ptr()) + result, local_buf.data(), nread);
|
std::memcpy(static_cast<uchar*>(buf.get_ptr()) + result, local_buf.data(), nread);
|
||||||
result += nread;
|
result += nread;
|
||||||
|
@ -1930,7 +1931,19 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
sys_fs.error("%s type: Writing %u bytes to FD=%d (path=%s)", file->type, arg->size, file->name.data());
|
sys_fs.error("%s type: Writing %u bytes to FD=%d (path=%s)", file->type, arg->size, file->name.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard lock(file->mp->mutex);
|
std::unique_lock wlock(file->mp->mutex, std::defer_lock);
|
||||||
|
std::shared_lock rlock(file->mp->mutex, std::defer_lock);
|
||||||
|
|
||||||
|
if (op == 0x8000000b)
|
||||||
|
{
|
||||||
|
// Writer lock
|
||||||
|
wlock.lock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reader lock (not needing exclusivity in this special case because the state should not change)
|
||||||
|
rlock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
if (!file->file)
|
if (!file->file)
|
||||||
{
|
{
|
||||||
|
@ -1947,14 +1960,23 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 old_pos = file->file.pos();
|
u64 old_pos = umax;
|
||||||
file->file.seek(arg->offset);
|
const u64 op_pos = arg->offset;
|
||||||
|
|
||||||
|
if (op == 0x8000000b)
|
||||||
|
{
|
||||||
|
old_pos = file->file.pos();
|
||||||
|
file->file.seek(op_pos);
|
||||||
|
}
|
||||||
|
|
||||||
arg->out_size = op == 0x8000000a
|
arg->out_size = op == 0x8000000a
|
||||||
? file->op_read(arg->buf, arg->size)
|
? file->op_read(arg->buf, arg->size, op_pos)
|
||||||
: file->op_write(arg->buf, arg->size);
|
: file->op_write(arg->buf, arg->size);
|
||||||
|
|
||||||
ensure(old_pos == file->file.seek(old_pos));
|
if (op == 0x8000000b)
|
||||||
|
{
|
||||||
|
ensure(old_pos == file->file.seek(old_pos));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: EDATA corruption detection
|
// TODO: EDATA corruption detection
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ struct lv2_fs_mount_point
|
||||||
const bs_t<lv2_mp_flag> flags{};
|
const bs_t<lv2_mp_flag> flags{};
|
||||||
lv2_fs_mount_point* const next = nullptr;
|
lv2_fs_mount_point* const next = nullptr;
|
||||||
|
|
||||||
mutable std::recursive_mutex mutex;
|
mutable shared_mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern lv2_fs_mount_point g_mp_sys_dev_hdd0;
|
extern lv2_fs_mount_point g_mp_sys_dev_hdd0;
|
||||||
|
@ -340,11 +340,11 @@ struct lv2_file final : lv2_fs_object
|
||||||
static open_result_t open(std::string_view vpath, s32 flags, s32 mode, const void* arg = {}, u64 size = 0);
|
static open_result_t open(std::string_view vpath, s32 flags, s32 mode, const void* arg = {}, u64 size = 0);
|
||||||
|
|
||||||
// File reading with intermediate buffer
|
// File reading with intermediate buffer
|
||||||
static u64 op_read(const fs::file& file, vm::ptr<void> buf, u64 size);
|
static u64 op_read(const fs::file& file, vm::ptr<void> buf, u64 size, u64 opt_pos = umax);
|
||||||
|
|
||||||
u64 op_read(vm::ptr<void> buf, u64 size) const
|
u64 op_read(vm::ptr<void> buf, u64 size, u64 opt_pos = umax) const
|
||||||
{
|
{
|
||||||
return op_read(file, buf, size);
|
return op_read(file, buf, size, opt_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// File writing with intermediate buffer
|
// File writing with intermediate buffer
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue