summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO/VolumeVerifier.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2019-08-06 11:39:09 +0200
committerJosJuice <josjuice@gmail.com>2019-08-06 16:42:59 +0200
commit34fb608dd6b4137ecc98e1c03228165a27eb800a (patch)
tree8d421c7c280520b614d2c0de25b576fa8a70888f /Source/Core/DiscIO/VolumeVerifier.cpp
parentf754a1a548f2e599e4cc2d1d799f2d21b520076f (diff)
VolumeVerifier: Multithreading
Diffstat (limited to 'Source/Core/DiscIO/VolumeVerifier.cpp')
-rw-r--r--Source/Core/DiscIO/VolumeVerifier.cpp140
1 files changed, 101 insertions, 39 deletions
diff --git a/Source/Core/DiscIO/VolumeVerifier.cpp b/Source/Core/DiscIO/VolumeVerifier.cpp
index 33a3a03e98..4d1bdc9a40 100644
--- a/Source/Core/DiscIO/VolumeVerifier.cpp
+++ b/Source/Core/DiscIO/VolumeVerifier.cpp
@@ -6,7 +6,9 @@
#include <algorithm>
#include <cinttypes>
+#include <future>
#include <limits>
+#include <mutex>
#include <optional>
#include <string>
#include <unordered_set>
@@ -683,6 +685,34 @@ void VolumeVerifier::SetUpHashing()
}
}
+void VolumeVerifier::WaitForAsyncOperations() const
+{
+ if (m_crc32_future.valid())
+ m_crc32_future.wait();
+ if (m_md5_future.valid())
+ m_md5_future.wait();
+ if (m_sha1_future.valid())
+ m_sha1_future.wait();
+ if (m_content_future.valid())
+ m_content_future.wait();
+ if (m_block_future.valid())
+ m_block_future.wait();
+}
+
+bool VolumeVerifier::ReadChunkAndWaitForAsyncOperations(u64 bytes_to_read)
+{
+ std::vector<u8> data(bytes_to_read);
+ {
+ std::lock_guard lk(m_volume_mutex);
+ if (!m_volume.Read(m_progress, bytes_to_read, data.data(), PARTITION_NONE))
+ return false;
+ }
+
+ WaitForAsyncOperations();
+ m_data = std::move(data);
+ return true;
+}
+
void VolumeVerifier::Process()
{
ASSERT(m_started);
@@ -718,13 +748,8 @@ void VolumeVerifier::Process()
}
bytes_to_read = std::min(bytes_to_read, m_max_progress - m_progress);
- bool read_succeeded = false;
- std::vector<u8> data(bytes_to_read);
- if (m_calculating_any_hash || content_read || block_read)
- {
- if (m_volume.Read(m_progress, bytes_to_read, data.data(), PARTITION_NONE))
- read_succeeded = true;
- }
+ const bool is_data_needed = m_calculating_any_hash || content_read || block_read;
+ const bool read_succeeded = is_data_needed && ReadChunkAndWaitForAsyncOperations(bytes_to_read);
if (m_calculating_any_hash)
{
@@ -736,55 +761,90 @@ void VolumeVerifier::Process()
{
if (m_hashes_to_calculate.crc32)
{
- // It would be nice to use crc32_z here instead of crc32, but it isn't available on Android
- m_crc32_context =
- crc32(m_crc32_context, data.data(), static_cast<unsigned int>(bytes_to_read));
+ m_crc32_future = std::async(std::launch::async, [this] {
+ // Would be nice to use crc32_z here instead of crc32, but it isn't available on Android
+ m_crc32_context =
+ crc32(m_crc32_context, m_data.data(), static_cast<unsigned int>(m_data.size()));
+ });
}
if (m_hashes_to_calculate.md5)
- mbedtls_md5_update_ret(&m_md5_context, data.data(), bytes_to_read);
+ {
+ m_md5_future = std::async(std::launch::async, [this] {
+ mbedtls_md5_update_ret(&m_md5_context, m_data.data(), m_data.size());
+ });
+ }
if (m_hashes_to_calculate.sha1)
- mbedtls_sha1_update_ret(&m_sha1_context, data.data(), bytes_to_read);
+ {
+ m_sha1_future = std::async(std::launch::async, [this] {
+ mbedtls_sha1_update_ret(&m_sha1_context, m_data.data(), m_data.size());
+ });
+ }
}
}
if (content_read)
{
- if (!read_succeeded || !m_volume.CheckContentIntegrity(content, data, m_ticket))
- {
- AddProblem(
- Severity::High,
- StringFromFormat(Common::GetStringT("Content %08x is corrupt.").c_str(), content.id));
- }
+ m_content_future = std::async(std::launch::async, [this, read_succeeded, content] {
+ if (!read_succeeded || !m_volume.CheckContentIntegrity(content, m_data, m_ticket))
+ {
+ AddProblem(
+ Severity::High,
+ StringFromFormat(Common::GetStringT("Content %08x is corrupt.").c_str(), content.id));
+ }
+ });
m_content_index++;
}
- while (m_block_index < m_blocks.size() &&
- m_blocks[m_block_index].offset < m_progress + bytes_to_read)
+ if (m_block_index < m_blocks.size() &&
+ m_blocks[m_block_index].offset < m_progress + bytes_to_read)
{
- const bool success = m_blocks[m_block_index].offset == m_progress ?
- read_succeeded && m_volume.CheckBlockIntegrity(
- m_blocks[m_block_index].block_index, data,
- m_blocks[m_block_index].partition) :
- m_volume.CheckBlockIntegrity(m_blocks[m_block_index].block_index,
- m_blocks[m_block_index].partition);
- if (!success)
+ m_md5_future = std::async(
+ std::launch::async,
+ [this, read_succeeded, bytes_to_read](size_t block_index, u64 progress) {
+ while (block_index < m_blocks.size() &&
+ m_blocks[block_index].offset < progress + bytes_to_read)
+ {
+ bool success;
+ if (m_blocks[block_index].offset == progress)
+ {
+ success = read_succeeded &&
+ m_volume.CheckBlockIntegrity(m_blocks[block_index].block_index, m_data,
+ m_blocks[block_index].partition);
+ }
+ else
+ {
+ std::lock_guard lk(m_volume_mutex);
+ success = m_volume.CheckBlockIntegrity(m_blocks[block_index].block_index,
+ m_blocks[block_index].partition);
+ }
+
+ if (!success)
+ {
+ const u64 offset = m_blocks[block_index].offset;
+ if (m_scrubber.CanBlockBeScrubbed(offset))
+ {
+ WARN_LOG(DISCIO, "Integrity check failed for unused block at 0x%" PRIx64, offset);
+ m_unused_block_errors[m_blocks[block_index].partition]++;
+ }
+ else
+ {
+ WARN_LOG(DISCIO, "Integrity check failed for block at 0x%" PRIx64, offset);
+ m_block_errors[m_blocks[block_index].partition]++;
+ }
+ }
+ block_index++;
+ }
+ },
+ m_block_index, m_progress);
+
+ while (m_block_index < m_blocks.size() &&
+ m_blocks[m_block_index].offset < m_progress + bytes_to_read)
{
- const u64 offset = m_blocks[m_block_index].offset;
- if (m_scrubber.CanBlockBeScrubbed(offset))
- {
- WARN_LOG(DISCIO, "Integrity check failed for unused block at 0x%" PRIx64, offset);
- m_unused_block_errors[m_blocks[m_block_index].partition]++;
- }
- else
- {
- WARN_LOG(DISCIO, "Integrity check failed for block at 0x%" PRIx64, offset);
- m_block_errors[m_blocks[m_block_index].partition]++;
- }
+ m_block_index++;
}
- m_block_index++;
}
m_progress += bytes_to_read;
@@ -806,6 +866,8 @@ void VolumeVerifier::Finish()
return;
m_done = true;
+ WaitForAsyncOperations();
+
ASSERT(m_content_index == m_content_offsets.size());
ASSERT(m_block_index == m_blocks.size());