File xenia_PR2123.patch of Package xenia
From e99a74685af3872d09efb99dda2e99c96740e628 Mon Sep 17 00:00:00 2001
From: Gliniak <Gliniak93@gmail.com>
Date: Sun, 5 Feb 2023 12:11:57 +0100
Subject: [PATCH] [STFS] Add critical section to file reading
Seems like reading same file concurrently from many threads
can cause situation when random thread receives incorrect data
---
src/xenia/vfs/devices/stfs_container_file.cc | 13 ++++++++-----
src/xenia/vfs/devices/stfs_container_file.h | 2 ++
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/xenia/vfs/devices/stfs_container_file.cc b/src/xenia/vfs/devices/stfs_container_file.cc
index 791d791016..4fec1d2c5f 100644
--- a/src/xenia/vfs/devices/stfs_container_file.cc
+++ b/src/xenia/vfs/devices/stfs_container_file.cc
@@ -52,12 +52,15 @@ X_STATUS StfsContainerFile::ReadSync(void* buffer, size_t buffer_length,
size_t read_length =
std::min(record.length - read_offset, remaining_length);
- auto& file = entry_->files()->at(record.file);
- xe::filesystem::Seek(file, record.offset + read_offset, SEEK_SET);
- auto num_read = fread(p, 1, read_length, file);
+ auto global_lock = global_critical_region_.Acquire();
+ {
+ auto& file = entry_->files()->at(record.file);
+ xe::filesystem::Seek(file, record.offset + read_offset, SEEK_SET);
+ auto num_read = fread(p, 1, read_length, file);
- *out_bytes_read += num_read;
- p += num_read;
+ *out_bytes_read += num_read;
+ p += num_read;
+ }
src_offset += record.length;
remaining_length -= read_length;
if (remaining_length == 0) {
diff --git a/src/xenia/vfs/devices/stfs_container_file.h b/src/xenia/vfs/devices/stfs_container_file.h
index d680dffe52..1fcc705c2f 100644
--- a/src/xenia/vfs/devices/stfs_container_file.h
+++ b/src/xenia/vfs/devices/stfs_container_file.h
@@ -10,6 +10,7 @@
#ifndef XENIA_VFS_DEVICES_STFS_CONTAINER_FILE_H_
#define XENIA_VFS_DEVICES_STFS_CONTAINER_FILE_H_
+#include "xenia/base/mutex.h"
#include "xenia/vfs/file.h"
#include "xenia/xbox.h"
@@ -35,6 +36,7 @@ class StfsContainerFile : public File {
X_STATUS SetLength(size_t length) override { return X_STATUS_ACCESS_DENIED; }
private:
+ xe::global_critical_region global_critical_region_;
StfsContainerEntry* entry_;
};