Skip to content

Commit deaf731

Browse files
committed
use thread-safe buffer on read_at()
1 parent a04e624 commit deaf731

2 files changed

Lines changed: 48 additions & 50 deletions

File tree

rpcs3/Loader/ISO.cpp

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ struct iso_sector
2525
u64 size_aligned;
2626
};
2727

28+
static void* get_aligned_buf()
29+
{
30+
static thread_local struct aligned_buf
31+
{
32+
void* buf;
33+
34+
aligned_buf() noexcept
35+
{
36+
// IMPORTANT NOTE: It must be aligned (probably enough on multiple of 4) to support raw device, otherwise any read from file will fail
37+
#if defined(_WIN32)
38+
buf = _aligned_malloc(ISO_SECTOR_SIZE, ISO_SECTOR_SIZE * 2);
39+
#else
40+
buf = std::aligned_alloc(ISO_SECTOR_SIZE * 2, ISO_SECTOR_SIZE);
41+
#endif
42+
}
43+
44+
~aligned_buf() noexcept
45+
{
46+
#if defined(_WIN32)
47+
_aligned_free(buf);
48+
#else
49+
std::free(buf);
50+
#endif
51+
}
52+
} s_aligned_buf {};
53+
54+
return s_aligned_buf.buf;
55+
}
56+
2857
static bool is_iso_file(const fs::file& file, u64* size = nullptr)
2958
{
3059
if (!file || file.size() < 32768ULL + 6)
@@ -598,9 +627,8 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
598627

599628
const u64 archive_first_offset = file_offset(offset);
600629
const u64 archive_last_offset = archive_first_offset + max_size - 1;
601-
602630
iso_sector first_sec, last_sec;
603-
u64 offset_aligned_first_out = 0;
631+
void* aligned_buf = get_aligned_buf(); // thread-safe buffer
604632

605633
first_sec.lba_address = (archive_first_offset / ISO_SECTOR_SIZE) * ISO_SECTOR_SIZE;
606634
first_sec.offset = archive_first_offset % ISO_SECTOR_SIZE;
@@ -614,6 +642,8 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
614642
// First sector
615643
//
616644

645+
u64 offset_aligned_first_out = 0;
646+
617647
if (!m_raw_device)
618648
{
619649
const u64 offset_aligned = first_sec.offset & ~0xF;
@@ -632,10 +662,10 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
632662
first_sec.address_aligned = first_sec.lba_address;
633663
}
634664

635-
u64 total_read = m_file.read_at(first_sec.address_aligned, &reinterpret_cast<u8*>(m_buf)[first_sec.offset_aligned], first_sec.size_aligned);
665+
u64 total_read = m_file.read_at(first_sec.address_aligned, &reinterpret_cast<u8*>(aligned_buf)[first_sec.offset_aligned], first_sec.size_aligned);
636666

637-
m_dec->decrypt(first_sec.address_aligned, &reinterpret_cast<u8*>(m_buf)[first_sec.offset_aligned], first_sec.size_aligned, m_meta.name);
638-
std::memcpy(buffer, &reinterpret_cast<u8*>(m_buf)[first_sec.offset], first_sec.size);
667+
m_dec->decrypt(first_sec.address_aligned, &reinterpret_cast<u8*>(aligned_buf)[first_sec.offset_aligned], first_sec.size_aligned, m_meta.name);
668+
std::memcpy(buffer, &reinterpret_cast<u8*>(aligned_buf)[first_sec.offset], first_sec.size);
639669

640670
const u64 sector_count = (last_sec.lba_address - first_sec.lba_address) / ISO_SECTOR_SIZE + 1;
641671

@@ -644,8 +674,6 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
644674
if (total_read != first_sec.size_aligned)
645675
{
646676
iso_log.error("read_at: %s: Error reading from file (%llu/%llu)", m_meta.name, total_read, first_sec.size_aligned);
647-
648-
seek(m_pos, fs::seek_set);
649677
return 0;
650678
}
651679

@@ -672,10 +700,10 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
672700

673701
for (u64 i = 0; i < sector_count - 2; i++, inner_sector_offset += ISO_SECTOR_SIZE)
674702
{
675-
total_read += m_file.read_at(first_sec.lba_address + ISO_SECTOR_SIZE + inner_sector_offset, m_buf, ISO_SECTOR_SIZE);
703+
total_read += m_file.read_at(first_sec.lba_address + ISO_SECTOR_SIZE + inner_sector_offset, aligned_buf, ISO_SECTOR_SIZE);
676704

677-
m_dec->decrypt(first_sec.lba_address + ISO_SECTOR_SIZE + inner_sector_offset, m_buf, ISO_SECTOR_SIZE, m_meta.name);
678-
std::memcpy(&reinterpret_cast<u8*>(buffer)[first_sec.size + inner_sector_offset], m_buf, ISO_SECTOR_SIZE);
705+
m_dec->decrypt(first_sec.lba_address + ISO_SECTOR_SIZE + inner_sector_offset, aligned_buf, ISO_SECTOR_SIZE, m_meta.name);
706+
std::memcpy(&reinterpret_cast<u8*>(buffer)[first_sec.size + inner_sector_offset], aligned_buf, ISO_SECTOR_SIZE);
679707
}
680708
}
681709
}
@@ -695,10 +723,10 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
695723
last_sec.size_aligned = ISO_SECTOR_SIZE;
696724
}
697725

698-
total_read += m_file.read_at(last_sec.address_aligned, m_buf, last_sec.size_aligned);
726+
total_read += m_file.read_at(last_sec.address_aligned, aligned_buf, last_sec.size_aligned);
699727

700-
m_dec->decrypt(last_sec.address_aligned, m_buf, last_sec.size_aligned, m_meta.name);
701-
std::memcpy(&reinterpret_cast<u8*>(buffer)[max_size - last_sec.size], m_buf, last_sec.size);
728+
m_dec->decrypt(last_sec.address_aligned, aligned_buf, last_sec.size_aligned, m_meta.name);
729+
std::memcpy(&reinterpret_cast<u8*>(buffer)[max_size - last_sec.size], aligned_buf, last_sec.size);
702730

703731
//
704732
// As last, check for an unlikely reading error (decoding also failed due to use of partially initialized buffer)
@@ -709,7 +737,6 @@ u64 iso_file_encrypted::read_at(u64 offset, void* buffer, u64 size)
709737
iso_log.error("read_at: %s: Error reading from file (%llu/%llu)", m_meta.name,
710738
total_read, ISO_SECTOR_SIZE + ISO_SECTOR_SIZE + (sector_count - 2) * ISO_SECTOR_SIZE);
711739

712-
seek(m_pos, fs::seek_set);
713740
return 0;
714741
}
715742

@@ -1136,13 +1163,6 @@ iso_file::iso_file(const std::string& path, bs_t<fs::open_mode> mode)
11361163
m_file.seek(m_meta.extents[0].start * ISO_SECTOR_SIZE);
11371164

11381165
m_raw_device = fs::is_optical_raw_device(path);
1139-
1140-
// IMPORTANT NOTE: It must be aligned (probably enough on multiple of 4) to support raw device, otherwise any read from file will fail
1141-
#if defined(_WIN32)
1142-
m_buf = _aligned_malloc(ISO_SECTOR_SIZE, ISO_SECTOR_SIZE * 2);
1143-
#else
1144-
m_buf = std::aligned_alloc(ISO_SECTOR_SIZE * 2, ISO_SECTOR_SIZE);
1145-
#endif
11461166
}
11471167

11481168
iso_file::iso_file(const std::string& path, bs_t<fs::open_mode> mode, const iso_fs_node& node)
@@ -1160,22 +1180,6 @@ iso_file::iso_file(const std::string& path, bs_t<fs::open_mode> mode, const iso_
11601180
m_file.seek(m_meta.extents[0].start * ISO_SECTOR_SIZE);
11611181

11621182
m_raw_device = fs::is_optical_raw_device(path);
1163-
1164-
// IMPORTANT NOTE: It must be aligned (probably enough on multiple of 4) to support raw device, otherwise any read from file will fail
1165-
#if defined(_WIN32)
1166-
m_buf = _aligned_malloc(ISO_SECTOR_SIZE, ISO_SECTOR_SIZE * 2);
1167-
#else
1168-
m_buf = std::aligned_alloc(ISO_SECTOR_SIZE * 2, ISO_SECTOR_SIZE);
1169-
#endif
1170-
}
1171-
1172-
iso_file::~iso_file()
1173-
{
1174-
#if defined(_WIN32)
1175-
_aligned_free(m_buf);
1176-
#else
1177-
std::free(m_buf);
1178-
#endif
11791183
}
11801184

11811185
fs::stat_t iso_file::get_stat()
@@ -1261,8 +1265,6 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
12611265
if (total_read != max_size)
12621266
{
12631267
iso_log.error("read_at: %s: Error reading from file (%llu/%llu)", m_meta.name, total_read, max_size);
1264-
1265-
seek(m_pos, fs::seek_set);
12661268
return 0;
12671269
}
12681270

@@ -1292,6 +1294,7 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
12921294

12931295
const u64 archive_last_offset = archive_first_offset + max_size - 1;
12941296
iso_sector first_sec, last_sec;
1297+
void* aligned_buf = get_aligned_buf(); // thread-safe buffer
12951298

12961299
first_sec.lba_address = (archive_first_offset / ISO_SECTOR_SIZE) * ISO_SECTOR_SIZE;
12971300
first_sec.offset = archive_first_offset % ISO_SECTOR_SIZE;
@@ -1305,9 +1308,9 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
13051308
// First sector
13061309
//
13071310

1308-
u64 total_read = m_file.read_at(first_sec.lba_address, m_buf, ISO_SECTOR_SIZE);
1311+
u64 total_read = m_file.read_at(first_sec.lba_address, aligned_buf, ISO_SECTOR_SIZE);
13091312

1310-
std::memcpy(buffer, &reinterpret_cast<u8*>(m_buf)[first_sec.offset], first_sec.size);
1313+
std::memcpy(buffer, &reinterpret_cast<u8*>(aligned_buf)[first_sec.offset], first_sec.size);
13111314

13121315
const u64 sector_count = (last_sec.lba_address - first_sec.lba_address) / ISO_SECTOR_SIZE + 1;
13131316

@@ -1316,8 +1319,6 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
13161319
if (total_read != ISO_SECTOR_SIZE)
13171320
{
13181321
iso_log.error("read_at: %s: Error reading from file (%llu/%llu)", m_meta.name, total_read, ISO_SECTOR_SIZE);
1319-
1320-
seek(m_pos, fs::seek_set);
13211322
return 0;
13221323
}
13231324

@@ -1334,19 +1335,19 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
13341335

13351336
for (u64 i = 0; i < sector_count - 2; i++, sector_offset += ISO_SECTOR_SIZE)
13361337
{
1337-
total_read += m_file.read_at(first_sec.lba_address + ISO_SECTOR_SIZE + sector_offset, m_buf, ISO_SECTOR_SIZE);
1338+
total_read += m_file.read_at(first_sec.lba_address + ISO_SECTOR_SIZE + sector_offset, aligned_buf, ISO_SECTOR_SIZE);
13381339

1339-
std::memcpy(&reinterpret_cast<u8*>(buffer)[first_sec.size + sector_offset], m_buf, ISO_SECTOR_SIZE);
1340+
std::memcpy(&reinterpret_cast<u8*>(buffer)[first_sec.size + sector_offset], aligned_buf, ISO_SECTOR_SIZE);
13401341
}
13411342
}
13421343

13431344
//
13441345
// Last sector
13451346
//
13461347

1347-
total_read += m_file.read_at(last_sec.address_aligned, m_buf, ISO_SECTOR_SIZE);
1348+
total_read += m_file.read_at(last_sec.address_aligned, aligned_buf, ISO_SECTOR_SIZE);
13481349

1349-
std::memcpy(&reinterpret_cast<u8*>(buffer)[max_size - last_sec.size], m_buf, last_sec.size);
1350+
std::memcpy(&reinterpret_cast<u8*>(buffer)[max_size - last_sec.size], aligned_buf, last_sec.size);
13501351

13511352
//
13521353
// As last, check for an unlikely reading error
@@ -1357,7 +1358,6 @@ u64 iso_file::read_at(u64 offset, void* buffer, u64 size)
13571358
iso_log.error("read_at: %s: Error reading from file (%llu/%llu)", m_meta.name,
13581359
total_read, ISO_SECTOR_SIZE + ISO_SECTOR_SIZE + (sector_count - 2) * ISO_SECTOR_SIZE);
13591360

1360-
seek(m_pos, fs::seek_set);
13611361
return 0;
13621362
}
13631363

rpcs3/Loader/ISO.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ class iso_file : public fs::file_base
108108
fs::file m_file;
109109
iso_fs_metadata m_meta;
110110
bool m_raw_device = false;
111-
void* m_buf = nullptr;
112111
u64 m_pos = 0;
113112

114113
std::pair<u64, iso_extent_info> get_extent_pos(u64 pos) const;
@@ -119,7 +118,6 @@ class iso_file : public fs::file_base
119118
public:
120119
iso_file(const std::string& path, bs_t<fs::open_mode> mode);
121120
iso_file(const std::string& path, bs_t<fs::open_mode> mode, const iso_fs_node& node);
122-
virtual ~iso_file();
123121

124122
explicit operator bool() const { return m_file.operator bool(); }
125123

0 commit comments

Comments
 (0)