summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt34
-rw-r--r--src/common/bit_cast.h22
-rw-r--r--src/common/bit_set.h99
-rw-r--r--src/common/concepts.h4
-rw-r--r--src/common/div_ceil.h26
-rw-r--r--src/common/fiber.cpp194
-rw-r--r--src/common/fiber.h29
-rw-r--r--src/common/file_util.cpp31
-rw-r--r--src/common/file_util.h2
-rw-r--r--src/common/hex_util.h10
-rw-r--r--src/common/logging/backend.cpp17
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/common/math_util.h8
-rw-r--r--src/common/memory_hook.cpp11
-rw-r--r--src/common/memory_hook.h47
-rw-r--r--src/common/misc.cpp15
-rw-r--r--src/common/multi_level_queue.h345
-rw-r--r--src/common/page_table.cpp12
-rw-r--r--src/common/page_table.h100
-rw-r--r--src/common/scope_exit.h2
-rw-r--r--src/common/spin_lock.h8
-rw-r--r--src/common/stream.cpp47
-rw-r--r--src/common/stream.h56
-rw-r--r--src/common/string_util.cpp5
-rw-r--r--src/common/swap.h4
-rw-r--r--src/common/telemetry.h4
-rw-r--r--src/common/thread_worker.cpp58
-rw-r--r--src/common/thread_worker.h30
-rw-r--r--src/common/timer.cpp12
-rw-r--r--src/common/vector_math.h75
-rw-r--r--src/common/virtual_buffer.cpp4
-rw-r--r--src/common/virtual_buffer.h38
-rw-r--r--src/common/wall_clock.cpp8
-rw-r--r--src/common/wall_clock.h8
-rw-r--r--src/common/x64/native_clock.cpp8
-rw-r--r--src/common/x64/native_clock.h7
-rw-r--r--src/common/x64/xbyak_abi.h20
37 files changed, 700 insertions, 701 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 5d54516eb..2c2bd2ee8 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -102,7 +102,9 @@ add_library(common STATIC
atomic_ops.h
detached_tasks.cpp
detached_tasks.h
+ bit_cast.h
bit_field.h
+ bit_set.h
bit_util.h
cityhash.cpp
cityhash.h
@@ -111,6 +113,7 @@ add_library(common STATIC
common_paths.h
common_types.h
concepts.h
+ div_ceil.h
dynamic_library.cpp
dynamic_library.h
fiber.cpp
@@ -132,13 +135,10 @@ add_library(common STATIC
math_util.h
memory_detect.cpp
memory_detect.h
- memory_hook.cpp
- memory_hook.h
microprofile.cpp
microprofile.h
microprofileui.h
misc.cpp
- multi_level_queue.h
page_table.cpp
page_table.h
param_package.cpp
@@ -150,6 +150,8 @@ add_library(common STATIC
scope_exit.h
spin_lock.cpp
spin_lock.h
+ stream.cpp
+ stream.h
string_util.cpp
string_util.h
swap.h
@@ -158,6 +160,8 @@ add_library(common STATIC
thread.cpp
thread.h
thread_queue_list.h
+ thread_worker.cpp
+ thread_worker.h
threadsafe_queue.h
time_zone.cpp
time_zone.h
@@ -188,8 +192,28 @@ if(ARCHITECTURE_x86_64)
)
endif()
+if (MSVC)
+ target_compile_definitions(common PRIVATE
+ # The standard library doesn't provide any replacement for codecvt yet
+ # so we can disable this deprecation warning for the time being.
+ _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
+ )
+ target_compile_options(common PRIVATE
+ /W4
+ /WX
+ )
+else()
+ target_compile_options(common PRIVATE
+ -Werror
+ )
+endif()
+
create_target_directory_groups(common)
-find_package(Boost 1.71 COMPONENTS context headers REQUIRED)
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile)
-target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd xbyak)
+target_link_libraries(common PRIVATE lz4::lz4 xbyak)
+if (MSVC)
+ target_link_libraries(common PRIVATE zstd::zstd)
+else()
+ target_link_libraries(common PRIVATE zstd)
+endif()
diff --git a/src/common/bit_cast.h b/src/common/bit_cast.h
new file mode 100644
index 000000000..a32a063d1
--- /dev/null
+++ b/src/common/bit_cast.h
@@ -0,0 +1,22 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstring>
+#include <type_traits>
+
+namespace Common {
+
+template <typename To, typename From>
+[[nodiscard]] std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> &&
+ std::is_trivially_copyable_v<To>,
+ To>
+BitCast(const From& src) noexcept {
+ To dst;
+ std::memcpy(&dst, &src, sizeof(To));
+ return dst;
+}
+
+} // namespace Common
diff --git a/src/common/bit_set.h b/src/common/bit_set.h
new file mode 100644
index 000000000..9235ad412
--- /dev/null
+++ b/src/common/bit_set.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <array>
+#include <bit>
+
+#include "common/alignment.h"
+#include "common/bit_util.h"
+#include "common/common_types.h"
+
+namespace Common {
+
+namespace impl {
+
+template <typename Storage, size_t N>
+class BitSet {
+
+public:
+ constexpr BitSet() = default;
+
+ constexpr void SetBit(size_t i) {
+ this->words[i / FlagsPerWord] |= GetBitMask(i % FlagsPerWord);
+ }
+
+ constexpr void ClearBit(size_t i) {
+ this->words[i / FlagsPerWord] &= ~GetBitMask(i % FlagsPerWord);
+ }
+
+ constexpr size_t CountLeadingZero() const {
+ for (size_t i = 0; i < NumWords; i++) {
+ if (this->words[i]) {
+ return FlagsPerWord * i + CountLeadingZeroImpl(this->words[i]);
+ }
+ }
+ return FlagsPerWord * NumWords;
+ }
+
+ constexpr size_t GetNextSet(size_t n) const {
+ for (size_t i = (n + 1) / FlagsPerWord; i < NumWords; i++) {
+ Storage word = this->words[i];
+ if (!IsAligned(n + 1, FlagsPerWord)) {
+ word &= GetBitMask(n % FlagsPerWord) - 1;
+ }
+ if (word) {
+ return FlagsPerWord * i + CountLeadingZeroImpl(word);
+ }
+ }
+ return FlagsPerWord * NumWords;
+ }
+
+private:
+ static_assert(std::is_unsigned_v<Storage>);
+ static_assert(sizeof(Storage) <= sizeof(u64));
+
+ static constexpr size_t FlagsPerWord = BitSize<Storage>();
+ static constexpr size_t NumWords = AlignUp(N, FlagsPerWord) / FlagsPerWord;
+
+ static constexpr auto CountLeadingZeroImpl(Storage word) {
+ return std::countl_zero(static_cast<unsigned long long>(word)) -
+ (BitSize<unsigned long long>() - FlagsPerWord);
+ }
+
+ static constexpr Storage GetBitMask(size_t bit) {
+ return Storage(1) << (FlagsPerWord - 1 - bit);
+ }
+
+ std::array<Storage, NumWords> words{};
+};
+
+} // namespace impl
+
+template <size_t N>
+using BitSet8 = impl::BitSet<u8, N>;
+
+template <size_t N>
+using BitSet16 = impl::BitSet<u16, N>;
+
+template <size_t N>
+using BitSet32 = impl::BitSet<u32, N>;
+
+template <size_t N>
+using BitSet64 = impl::BitSet<u64, N>;
+
+} // namespace Common
diff --git a/src/common/concepts.h b/src/common/concepts.h
index 5bef3ad67..aa08065a7 100644
--- a/src/common/concepts.h
+++ b/src/common/concepts.h
@@ -31,4 +31,8 @@ concept DerivedFrom = requires {
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
};
+// TODO: Replace with std::convertible_to when libc++ implements it.
+template <typename From, typename To>
+concept ConvertibleTo = std::is_convertible_v<From, To>;
+
} // namespace Common
diff --git a/src/common/div_ceil.h b/src/common/div_ceil.h
new file mode 100644
index 000000000..95e1489a9
--- /dev/null
+++ b/src/common/div_ceil.h
@@ -0,0 +1,26 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <cstddef>
+#include <type_traits>
+
+namespace Common {
+
+/// Ceiled integer division.
+template <typename N, typename D>
+requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeil(N number,
+ D divisor) {
+ return static_cast<N>((static_cast<D>(number) + divisor - 1) / divisor);
+}
+
+/// Ceiled integer division with logarithmic divisor in base 2
+template <typename N, typename D>
+requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeilLog2(
+ N value, D alignment_log2) {
+ return static_cast<N>((static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2);
+}
+
+} // namespace Common
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 1c1d09ccb..3c1eefcb7 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -4,129 +4,51 @@
#include "common/assert.h"
#include "common/fiber.h"
-#if defined(_WIN32) || defined(WIN32)
-#include <windows.h>
-#else
+#include "common/spin_lock.h"
+#include "common/virtual_buffer.h"
+
#include <boost/context/detail/fcontext.hpp>
-#endif
namespace Common {
-constexpr std::size_t default_stack_size = 256 * 1024; // 256kb
-
-#if defined(_WIN32) || defined(WIN32)
+constexpr std::size_t default_stack_size = 256 * 1024;
struct Fiber::FiberImpl {
- LPVOID handle = nullptr;
- LPVOID rewind_handle = nullptr;
+ FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {}
+
+ VirtualBuffer<u8> stack;
+ VirtualBuffer<u8> rewind_stack;
+
+ SpinLock guard{};
+ std::function<void(void*)> entry_point;
+ std::function<void(void*)> rewind_point;
+ void* rewind_parameter{};
+ void* start_parameter{};
+ std::shared_ptr<Fiber> previous_fiber;
+ bool is_thread_fiber{};
+ bool released{};
+
+ u8* stack_limit{};
+ u8* rewind_stack_limit{};
+ boost::context::detail::fcontext_t context{};
+ boost::context::detail::fcontext_t rewind_context{};
};
-void Fiber::Start() {
- ASSERT(previous_fiber != nullptr);
- previous_fiber->guard.unlock();
- previous_fiber.reset();
- entry_point(start_parameter);
- UNREACHABLE();
-}
-
-void Fiber::OnRewind() {
- ASSERT(impl->handle != nullptr);
- DeleteFiber(impl->handle);
- impl->handle = impl->rewind_handle;
- impl->rewind_handle = nullptr;
- rewind_point(rewind_parameter);
- UNREACHABLE();
-}
-
-void Fiber::FiberStartFunc(void* fiber_parameter) {
- auto fiber = static_cast<Fiber*>(fiber_parameter);
- fiber->Start();
-}
-
-void Fiber::RewindStartFunc(void* fiber_parameter) {
- auto fiber = static_cast<Fiber*>(fiber_parameter);
- fiber->OnRewind();
-}
-
-Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
- : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} {
- impl = std::make_unique<FiberImpl>();
- impl->handle = CreateFiber(default_stack_size, &FiberStartFunc, this);
-}
-
-Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
-
-Fiber::~Fiber() {
- if (released) {
- return;
- }
- // Make sure the Fiber is not being used
- const bool locked = guard.try_lock();
- ASSERT_MSG(locked, "Destroying a fiber that's still running");
- if (locked) {
- guard.unlock();
- }
- DeleteFiber(impl->handle);
-}
-
-void Fiber::Exit() {
- ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber");
- if (!is_thread_fiber) {
- return;
- }
- ConvertFiberToThread();
- guard.unlock();
- released = true;
-}
-
-void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) {
- rewind_point = std::move(rewind_func);
- rewind_parameter = start_parameter;
-}
-
-void Fiber::Rewind() {
- ASSERT(rewind_point);
- ASSERT(impl->rewind_handle == nullptr);
- impl->rewind_handle = CreateFiber(default_stack_size, &RewindStartFunc, this);
- SwitchToFiber(impl->rewind_handle);
-}
-
-void Fiber::YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to) {
- ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
- ASSERT_MSG(to != nullptr, "Next fiber is null!");
- to->guard.lock();
- to->previous_fiber = from;
- SwitchToFiber(to->impl->handle);
- ASSERT(from->previous_fiber != nullptr);
- from->previous_fiber->guard.unlock();
- from->previous_fiber.reset();
+void Fiber::SetStartParameter(void* new_parameter) {
+ impl->start_parameter = new_parameter;
}
-std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
- std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
- fiber->guard.lock();
- fiber->impl->handle = ConvertThreadToFiber(nullptr);
- fiber->is_thread_fiber = true;
- return fiber;
+void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
+ impl->rewind_point = std::move(rewind_func);
+ impl->rewind_parameter = rewind_param;
}
-#else
-
-struct Fiber::FiberImpl {
- alignas(64) std::array<u8, default_stack_size> stack;
- alignas(64) std::array<u8, default_stack_size> rewind_stack;
- u8* stack_limit;
- u8* rewind_stack_limit;
- boost::context::detail::fcontext_t context;
- boost::context::detail::fcontext_t rewind_context;
-};
-
void Fiber::Start(boost::context::detail::transfer_t& transfer) {
- ASSERT(previous_fiber != nullptr);
- previous_fiber->impl->context = transfer.fctx;
- previous_fiber->guard.unlock();
- previous_fiber.reset();
- entry_point(start_parameter);
+ ASSERT(impl->previous_fiber != nullptr);
+ impl->previous_fiber->impl->context = transfer.fctx;
+ impl->previous_fiber->impl->guard.unlock();
+ impl->previous_fiber.reset();
+ impl->entry_point(impl->start_parameter);
UNREACHABLE();
}
@@ -137,23 +59,24 @@ void Fiber::OnRewind([[maybe_unused]] boost::context::detail::transfer_t& transf
u8* tmp = impl->stack_limit;
impl->stack_limit = impl->rewind_stack_limit;
impl->rewind_stack_limit = tmp;
- rewind_point(rewind_parameter);
+ impl->rewind_point(impl->rewind_parameter);
UNREACHABLE();
}
void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) {
- auto fiber = static_cast<Fiber*>(transfer.data);
+ auto* fiber = static_cast<Fiber*>(transfer.data);
fiber->Start(transfer);
}
void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
- auto fiber = static_cast<Fiber*>(transfer.data);
+ auto* fiber = static_cast<Fiber*>(transfer.data);
fiber->OnRewind(transfer);
}
Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
- : entry_point{std::move(entry_point_func)}, start_parameter{start_parameter} {
- impl = std::make_unique<FiberImpl>();
+ : impl{std::make_unique<FiberImpl>()} {
+ impl->entry_point = std::move(entry_point_func);
+ impl->start_parameter = start_parameter;
impl->stack_limit = impl->stack.data();
impl->rewind_stack_limit = impl->rewind_stack.data();
u8* stack_base = impl->stack_limit + default_stack_size;
@@ -161,37 +84,31 @@ Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_paramete
boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
}
-void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) {
- rewind_point = std::move(rewind_func);
- rewind_parameter = start_parameter;
-}
-
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
Fiber::~Fiber() {
- if (released) {
+ if (impl->released) {
return;
}
// Make sure the Fiber is not being used
- const bool locked = guard.try_lock();
+ const bool locked = impl->guard.try_lock();
ASSERT_MSG(locked, "Destroying a fiber that's still running");
if (locked) {
- guard.unlock();
+ impl->guard.unlock();
}
}
void Fiber::Exit() {
-
- ASSERT_MSG(is_thread_fiber, "Exitting non main thread fiber");
- if (!is_thread_fiber) {
+ ASSERT_MSG(impl->is_thread_fiber, "Exitting non main thread fiber");
+ if (!impl->is_thread_fiber) {
return;
}
- guard.unlock();
- released = true;
+ impl->guard.unlock();
+ impl->released = true;
}
void Fiber::Rewind() {
- ASSERT(rewind_point);
+ ASSERT(impl->rewind_point);
ASSERT(impl->rewind_context == nullptr);
u8* stack_base = impl->rewind_stack_limit + default_stack_size;
impl->rewind_context =
@@ -199,24 +116,23 @@ void Fiber::Rewind() {
boost::context::detail::jump_fcontext(impl->rewind_context, this);
}
-void Fiber::YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to) {
+void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) {
ASSERT_MSG(from != nullptr, "Yielding fiber is null!");
ASSERT_MSG(to != nullptr, "Next fiber is null!");
- to->guard.lock();
- to->previous_fiber = from;
+ to->impl->guard.lock();
+ to->impl->previous_fiber = from;
auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get());
- ASSERT(from->previous_fiber != nullptr);
- from->previous_fiber->impl->context = transfer.fctx;
- from->previous_fiber->guard.unlock();
- from->previous_fiber.reset();
+ ASSERT(from->impl->previous_fiber != nullptr);
+ from->impl->previous_fiber->impl->context = transfer.fctx;
+ from->impl->previous_fiber->impl->guard.unlock();
+ from->impl->previous_fiber.reset();
}
std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
- fiber->guard.lock();
- fiber->is_thread_fiber = true;
+ fiber->impl->guard.lock();
+ fiber->impl->is_thread_fiber = true;
return fiber;
}
-#endif
} // namespace Common
diff --git a/src/common/fiber.h b/src/common/fiber.h
index 89dde5e36..f7f587f8c 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -7,14 +7,9 @@
#include <functional>
#include <memory>
-#include "common/common_types.h"
-#include "common/spin_lock.h"
-
-#if !defined(_WIN32) && !defined(WIN32)
namespace boost::context::detail {
struct transfer_t;
}
-#endif
namespace Common {
@@ -46,10 +41,10 @@ public:
/// Yields control from Fiber 'from' to Fiber 'to'
/// Fiber 'from' must be the currently running fiber.
- static void YieldTo(std::shared_ptr<Fiber>& from, std::shared_ptr<Fiber>& to);
+ static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to);
[[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
- void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter);
+ void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param);
void Rewind();
@@ -57,36 +52,18 @@ public:
void Exit();
/// Changes the start parameter of the fiber. Has no effect if the fiber already started
- void SetStartParameter(void* new_parameter) {
- start_parameter = new_parameter;
- }
+ void SetStartParameter(void* new_parameter);
private:
Fiber();
-#if defined(_WIN32) || defined(WIN32)
- void OnRewind();
- void Start();
- static void FiberStartFunc(void* fiber_parameter);
- static void RewindStartFunc(void* fiber_parameter);
-#else
void OnRewind(boost::context::detail::transfer_t& transfer);
void Start(boost::context::detail::transfer_t& transfer);
static void FiberStartFunc(boost::context::detail::transfer_t transfer);
static void RewindStartFunc(boost::context::detail::transfer_t transfer);
-#endif
struct FiberImpl;
-
- SpinLock guard{};
- std::function<void(void*)> entry_point;
- std::function<void(void*)> rewind_point;
- void* rewind_parameter{};
- void* start_parameter{};
- std::shared_ptr<Fiber> previous_fiber;
std::unique_ptr<FiberImpl> impl;
- bool is_thread_fiber{};
- bool released{};
};
} // namespace Common
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 16c3713e0..18fbfa25b 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -472,13 +472,14 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
}
bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) {
- const auto callback = [recursion](u64* num_entries_out, const std::string& directory,
- const std::string& virtual_name) -> bool {
- std::string new_path = directory + DIR_SEP_CHR + virtual_name;
+ const auto callback = [recursion](u64*, const std::string& directory,
+ const std::string& virtual_name) {
+ const std::string new_path = directory + DIR_SEP_CHR + virtual_name;
if (IsDirectory(new_path)) {
- if (recursion == 0)
+ if (recursion == 0) {
return false;
+ }
return DeleteDirRecursively(new_path, recursion - 1);
}
return Delete(new_path);
@@ -492,7 +493,8 @@ bool DeleteDirRecursively(const std::string& directory, unsigned int recursion)
return true;
}
-void CopyDir(const std::string& source_path, const std::string& dest_path) {
+void CopyDir([[maybe_unused]] const std::string& source_path,
+ [[maybe_unused]] const std::string& dest_path) {
#ifndef _WIN32
if (source_path == dest_path) {
return;
@@ -553,7 +555,7 @@ std::optional<std::string> GetCurrentDir() {
std::string strDir = dir;
#endif
free(dir);
- return std::move(strDir);
+ return strDir;
}
bool SetCurrentDir(const std::string& directory) {
@@ -772,21 +774,23 @@ std::size_t ReadFileToString(bool text_file, const std::string& filename, std::s
void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name,
std::array<char, 4>& extension) {
- const std::string forbidden_characters = ".\"/\\[]:;=, ";
+ static constexpr std::string_view forbidden_characters = ".\"/\\[]:;=, ";
// On a FAT32 partition, 8.3 names are stored as a 11 bytes array, filled with spaces.
short_name = {{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\0'}};
extension = {{' ', ' ', ' ', '\0'}};
- std::string::size_type point = filename.rfind('.');
- if (point == filename.size() - 1)
+ auto point = filename.rfind('.');
+ if (point == filename.size() - 1) {
point = filename.rfind('.', point);
+ }
// Get short name.
int j = 0;
for (char letter : filename.substr(0, point)) {
- if (forbidden_characters.find(letter, 0) != std::string::npos)
+ if (forbidden_characters.find(letter, 0) != std::string::npos) {
continue;
+ }
if (j == 8) {
// TODO(Link Mauve): also do that for filenames containing a space.
// TODO(Link Mauve): handle multiple files having the same short name.
@@ -794,14 +798,15 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
short_name[7] = '1';
break;
}
- short_name[j++] = toupper(letter);
+ short_name[j++] = static_cast<char>(std::toupper(letter));
}
// Get extension.
if (point != std::string::npos) {
j = 0;
- for (char letter : filename.substr(point + 1, 3))
- extension[j++] = toupper(letter);
+ for (char letter : filename.substr(point + 1, 3)) {
+ extension[j++] = static_cast<char>(std::toupper(letter));
+ }
}
}
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 8b587320f..840cde2a6 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -232,7 +232,7 @@ public:
void Swap(IOFile& other) noexcept;
- [[nodiscard]] bool Open(const std::string& filename, const char openmode[], int flags = 0);
+ bool Open(const std::string& filename, const char openmode[], int flags = 0);
bool Close();
template <typename T>
diff --git a/src/common/hex_util.h b/src/common/hex_util.h
index 120f1a5e6..a8d414fb8 100644
--- a/src/common/hex_util.h
+++ b/src/common/hex_util.h
@@ -16,14 +16,14 @@ namespace Common {
[[nodiscard]] constexpr u8 ToHexNibble(char c) {
if (c >= 65 && c <= 70) {
- return c - 55;
+ return static_cast<u8>(c - 55);
}
if (c >= 97 && c <= 102) {
- return c - 87;
+ return static_cast<u8>(c - 87);
}
- return c - 48;
+ return static_cast<u8>(c - 48);
}
[[nodiscard]] std::vector<u8> HexStringToVector(std::string_view str, bool little_endian);
@@ -33,11 +33,11 @@ template <std::size_t Size, bool le = false>
std::array<u8, Size> out{};
if constexpr (le) {
for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) {
- out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
+ out[i / 2] = static_cast<u8>((ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]));
}
} else {
for (std::size_t i = 0; i < 2 * Size; i += 2) {
- out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
+ out[i / 2] = static_cast<u8>((ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]));
}
}
return out;
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 62cfde397..631f64d05 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -23,6 +23,7 @@
#include "common/logging/text_formatter.h"
#include "common/string_util.h"
#include "common/threadsafe_queue.h"
+#include "core/settings.h"
namespace Log {
@@ -152,10 +153,19 @@ FileBackend::FileBackend(const std::string& filename)
void FileBackend::Write(const Entry& entry) {
// prevent logs from going over the maximum size (in case its spamming and the user doesn't
// know)
- constexpr std::size_t MAX_BYTES_WRITTEN = 50 * 1024L * 1024L;
- if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) {
+ constexpr std::size_t MAX_BYTES_WRITTEN = 100 * 1024 * 1024;
+ constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1024 * 1024 * 1024;
+
+ if (!file.IsOpen()) {
+ return;
+ }
+
+ if (Settings::values.extended_logging && bytes_written > MAX_BYTES_WRITTEN_EXTENDED) {
+ return;
+ } else if (!Settings::values.extended_logging && bytes_written > MAX_BYTES_WRITTEN) {
return;
}
+
bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n'));
if (entry.log_level >= Level::Error) {
file.Flush();
@@ -222,6 +232,7 @@ void DebuggerBackend::Write(const Entry& entry) {
SUB(Service, NPNS) \
SUB(Service, NS) \
SUB(Service, NVDRV) \
+ SUB(Service, OLSC) \
SUB(Service, PCIE) \
SUB(Service, PCTL) \
SUB(Service, PCV) \
@@ -274,7 +285,6 @@ const char* GetLogClassName(Class log_class) {
case Class::Count:
break;
}
- UNREACHABLE();
return "Invalid";
}
@@ -293,7 +303,6 @@ const char* GetLevelName(Level log_level) {
break;
}
#undef LVL
- UNREACHABLE();
return "Invalid";
}
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 13a4f1e30..835894918 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -95,6 +95,7 @@ enum class Class : ClassType {
Service_NPNS, ///< The NPNS service
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
+ Service_OLSC, ///< The OLSC service
Service_PCIE, ///< The PCIe service
Service_PCTL, ///< The PCTL (Parental control) service
Service_PCV, ///< The PCV service
diff --git a/src/common/math_util.h b/src/common/math_util.h
index b35ad8507..4c38d8040 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -20,14 +20,14 @@ struct Rectangle {
constexpr Rectangle() = default;
- constexpr Rectangle(T left, T top, T right, T bottom)
- : left(left), top(top), right(right), bottom(bottom) {}
+ constexpr Rectangle(T left_, T top_, T right_, T bottom_)
+ : left(left_), top(top_), right(right_), bottom(bottom_) {}
[[nodiscard]] T GetWidth() const {
if constexpr (std::is_floating_point_v<T>) {
return std::abs(right - left);
} else {
- return std::abs(static_cast<std::make_signed_t<T>>(right - left));
+ return static_cast<T>(std::abs(static_cast<std::make_signed_t<T>>(right - left)));
}
}
@@ -35,7 +35,7 @@ struct Rectangle {
if constexpr (std::is_floating_point_v<T>) {
return std::abs(bottom - top);
} else {
- return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
+ return static_cast<T>(std::abs(static_cast<std::make_signed_t<T>>(bottom - top)));
}
}
diff --git a/src/common/memory_hook.cpp b/src/common/memory_hook.cpp
deleted file mode 100644
index 3986986d6..000000000
--- a/src/common/memory_hook.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "common/memory_hook.h"
-
-namespace Common {
-
-MemoryHook::~MemoryHook() = default;
-
-} // namespace Common
diff --git a/src/common/memory_hook.h b/src/common/memory_hook.h
deleted file mode 100644
index adaa4c2c5..000000000
--- a/src/common/memory_hook.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include <optional>
-
-#include "common/common_types.h"
-
-namespace Common {
-
-/**
- * Memory hooks have two purposes:
- * 1. To allow reads and writes to a region of memory to be intercepted. This is used to implement
- * texture forwarding and memory breakpoints for debugging.
- * 2. To allow for the implementation of MMIO devices.
- *
- * A hook may be mapped to multiple regions of memory.
- *
- * If a std::nullopt or false is returned from a function, the read/write request is passed through
- * to the underlying memory region.
- */
-class MemoryHook {
-public:
- virtual ~MemoryHook();
-
- virtual std::optional<bool> IsValidAddress(VAddr addr) = 0;
-
- virtual std::optional<u8> Read8(VAddr addr) = 0;
- virtual std::optional<u16> Read16(VAddr addr) = 0;
- virtual std::optional<u32> Read32(VAddr addr) = 0;
- virtual std::optional<u64> Read64(VAddr addr) = 0;
-
- virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) = 0;
-
- virtual bool Write8(VAddr addr, u8 data) = 0;
- virtual bool Write16(VAddr addr, u16 data) = 0;
- virtual bool Write32(VAddr addr, u32 data) = 0;
- virtual bool Write64(VAddr addr, u64 data) = 0;
-
- virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size) = 0;
-};
-
-using MemoryHookPointer = std::shared_ptr<MemoryHook>;
-} // namespace Common
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index 68cb86cd1..1d5393597 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -16,16 +16,23 @@
// Call directly after the command or use the error num.
// This function might change the error code.
std::string GetLastErrorMsg() {
- static const std::size_t buff_size = 255;
+ static constexpr std::size_t buff_size = 255;
char err_str[buff_size];
#ifdef _WIN32
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr);
+ return std::string(err_str, buff_size);
+#elif defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
+ // Thread safe (GNU-specific)
+ const char* str = strerror_r(errno, err_str, buff_size);
+ return std::string(str);
#else
// Thread safe (XSI-compliant)
- strerror_r(errno, err_str, buff_size);
+ const int success = strerror_r(errno, err_str, buff_size);
+ if (success != 0) {
+ return {};
+ }
+ return std::string(err_str);
#endif
-
- return std::string(err_str, buff_size);
}
diff --git a/src/common/multi_level_queue.h b/src/common/multi_level_queue.h
deleted file mode 100644
index 4b305bf40..000000000
--- a/src/common/multi_level_queue.h
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2019 TuxSH
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <iterator>
-#include <list>
-#include <utility>
-
-#include "common/bit_util.h"
-#include "common/common_types.h"
-
-namespace Common {
-
-/**
- * A MultiLevelQueue is a type of priority queue which has the following characteristics:
- * - iteratable through each of its elements.
- * - back can be obtained.
- * - O(1) add, lookup (both front and back)
- * - discrete priorities and a max of 64 priorities (limited domain)
- * This type of priority queue is normaly used for managing threads within an scheduler
- */
-template <typename T, std::size_t Depth>
-class MultiLevelQueue {
-public:
- using value_type = T;
- using reference = value_type&;
- using const_reference = const value_type&;
- using pointer = value_type*;
- using const_pointer = const value_type*;
-
- using difference_type = typename std::pointer_traits<pointer>::difference_type;
- using size_type = std::size_t;
-
- template <bool is_constant>
- class iterator_impl {
- public:
- using iterator_category = std::bidirectional_iterator_tag;
- using value_type = T;
- using pointer = std::conditional_t<is_constant, T*, const T*>;
- using reference = std::conditional_t<is_constant, const T&, T&>;
- using difference_type = typename std::pointer_traits<pointer>::difference_type;
-
- friend bool operator==(const iterator_impl& lhs, const iterator_impl& rhs) {
- if (lhs.IsEnd() && rhs.IsEnd())
- return true;
- return std::tie(lhs.current_priority, lhs.it) == std::tie(rhs.current_priority, rhs.it);
- }
-
- friend bool operator!=(const iterator_impl& lhs, const iterator_impl& rhs) {
- return !operator==(lhs, rhs);
- }
-
- reference operator*() const {
- return *it;
- }
-
- pointer operator->() const {
- return it.operator->();
- }
-
- iterator_impl& operator++() {
- if (IsEnd()) {
- return *this;
- }
-
- ++it;
-
- if (it == GetEndItForPrio()) {
- u64 prios = mlq.used_priorities;
- prios &= ~((1ULL << (current_priority + 1)) - 1);
- if (prios == 0) {
- current_priority = static_cast<u32>(mlq.depth());
- } else {
- current_priority = CountTrailingZeroes64(prios);
- it = GetBeginItForPrio();
- }
- }
- return *this;
- }
-
- iterator_impl& operator--() {
- if (IsEnd()) {
- if (mlq.used_priorities != 0) {
- current_priority = 63 - CountLeadingZeroes64(mlq.used_priorities);
- it = GetEndItForPrio();
- --it;
- }
- } else if (it == GetBeginItForPrio()) {
- u64 prios = mlq.used_priorities;
- prios &= (1ULL << current_priority) - 1;
- if (prios != 0) {
- current_priority = CountTrailingZeroes64(prios);
- it = GetEndItForPrio();
- --it;
- }
- } else {
- --it;
- }
- return *this;
- }
-
- iterator_impl operator++(int) {
- const iterator_impl v{*this};
- ++(*this);
- return v;
- }
-
- iterator_impl operator--(int) {
- const iterator_impl v{*this};
- --(*this);
- return v;
- }
-
- // allow implicit const->non-const
- iterator_impl(const iterator_impl<false>& other)
- : mlq(other.mlq), it(other.it), current_priority(other.current_priority) {}
-
- iterator_impl(const iterator_impl<true>& other)
- : mlq(other.mlq), it(other.it), current_priority(other.current_priority) {}
-
- iterator_impl& operator=(const iterator_impl<false>& other) {
- mlq = other.mlq;
- it = other.it;
- current_priority = other.current_priority;
- return *this;
- }
-
- friend class iterator_impl<true>;
- iterator_impl() = default;
-
- private:
- friend class MultiLevelQueue;
- using container_ref =
- std::conditional_t<is_constant, const MultiLevelQueue&, MultiLevelQueue&>;
- using list_iterator = std::conditional_t<is_constant, typename std::list<T>::const_iterator,
- typename std::list<T>::iterator>;
-
- explicit iterator_impl(container_ref mlq, list_iterator it, u32 current_priority)
- : mlq(mlq), it(it), current_priority(current_priority) {}
- explicit iterator_impl(container_ref mlq, u32 current_priority)
- : mlq(mlq), it(), current_priority(current_priority) {}
-
- bool IsEnd() const {
- return current_priority == mlq.depth();
- }
-
- list_iterator GetBeginItForPrio() const {
- return mlq.levels[current_priority].begin();
- }
-
- list_iterator GetEndItForPrio() const {
- return mlq.levels[current_priority].end();
- }
-
- container_ref mlq;
- list_iterator it;
- u32 current_priority;
- };
-
- using iterator = iterator_impl<false>;
- using const_iterator = iterator_impl<true>;
-
- void add(const T& element, u32 priority, bool send_back = true) {
- if (send_back)
- levels[priority].push_back(element);
- else
- levels[priority].push_front(element);
- used_priorities |= 1ULL << priority;
- }
-
- void remove(const T& element, u32 priority) {
- auto it = ListIterateTo(levels[priority], element);
- if (it == levels[priority].end())
- return;
- levels[priority].erase(it);
- if (levels[priority].empty()) {
- used_priorities &= ~(1ULL << priority);
- }
- }
-
- void adjust(const T& element, u32 old_priority, u32 new_priority, bool adjust_front = false) {
- remove(element, old_priority);
- add(element, new_priority, !adjust_front);
- }
- void adjust(const_iterator it, u32 old_priority, u32 new_priority, bool adjust_front = false) {
- adjust(*it, old_priority, new_priority, adjust_front);
- }
-
- void transfer_to_front(const T& element, u32 priority, MultiLevelQueue& other) {
- ListSplice(other.levels[priority], other.levels[priority].begin(), levels[priority],
- ListIterateTo(levels[priority], element));
-
- other.used_priorities |= 1ULL << priority;
-
- if (levels[priority].empty()) {
- used_priorities &= ~(1ULL << priority);
- }
- }
-
- void transfer_to_front(const_iterator it, u32 priority, MultiLevelQueue& other) {
- transfer_to_front(*it, priority, other);
- }
-
- void transfer_to_back(const T& element, u32 priority, MultiLevelQueue& other) {
- ListSplice(other.levels[priority], other.levels[priority].end(), levels[priority],
- ListIterateTo(levels[priority], element));
-
- other.used_priorities |= 1ULL << priority;
-
- if (levels[priority].empty()) {
- used_priorities &= ~(1ULL << priority);
- }
- }
-
- void transfer_to_back(const_iterator it, u32 priority, MultiLevelQueue& other) {
- transfer_to_back(*it, priority, other);
- }
-
- void yield(u32 priority, std::size_t n = 1) {
- ListShiftForward(levels[priority], n);
- }
-
- [[nodiscard]] std::size_t depth() const {
- return Depth;
- }
-
- [[nodiscard]] std::size_t size(u32 priority) const {
- return levels[priority].size();
- }
-
- [[nodiscard]] std::size_t size() const {
- u64 priorities = used_priorities;
- std::size_t size = 0;
- while (priorities != 0) {
- const u64 current_priority = CountTrailingZeroes64(priorities);
- size += levels[current_priority].size();
- priorities &= ~(1ULL << current_priority);
- }
- return size;
- }
-
- [[nodiscard]] bool empty() const {
- return used_priorities == 0;
- }
-
- [[nodiscard]] bool empty(u32 priority) const {
- return (used_priorities & (1ULL << priority)) == 0;
- }
-
- [[nodiscard]] u32 highest_priority_set(u32 max_priority = 0) const {
- const u64 priorities =
- max_priority == 0 ? used_priorities : (used_priorities & ~((1ULL << max_priority) - 1));
- return priorities == 0 ? Depth : static_cast<u32>(CountTrailingZeroes64(priorities));
- }
-
- [[nodiscard]] u32 lowest_priority_set(u32 min_priority = Depth - 1) const {
- const u64 priorities = min_priority >= Depth - 1
- ? used_priorities
- : (used_priorities & ((1ULL << (min_priority + 1)) - 1));
- return priorities == 0 ? Depth : 63 - CountLeadingZeroes64(priorities);
- }
-
- [[nodiscard]] const_iterator cbegin(u32 max_prio = 0) const {
- const u32 priority = highest_priority_set(max_prio);
- return priority == Depth ? cend()
- : const_iterator{*this, levels[priority].cbegin(), priority};
- }
- [[nodiscard]] const_iterator begin(u32 max_prio = 0) const {
- return cbegin(max_prio);
- }
- [[nodiscard]] iterator begin(u32 max_prio = 0) {
- const u32 priority = highest_priority_set(max_prio);
- return priority == Depth ? end() : iterator{*this, levels[priority].begin(), priority};
- }
-
- [[nodiscard]] const_iterator cend(u32 min_prio = Depth - 1) const {
- return min_prio == Depth - 1 ? const_iterator{*this, Depth} : cbegin(min_prio + 1);
- }
- [[nodiscard]] const_iterator end(u32 min_prio = Depth - 1) const {
- return cend(min_prio);
- }
- [[nodiscard]] iterator end(u32 min_prio = Depth - 1) {
- return min_prio == Depth - 1 ? iterator{*this, Depth} : begin(min_prio + 1);
- }
-
- [[nodiscard]] T& front(u32 max_priority = 0) {
- const u32 priority = highest_priority_set(max_priority);
- return levels[priority == Depth ? 0 : priority].front();
- }
- [[nodiscard]] const T& front(u32 max_priority = 0) const {
- const u32 priority = highest_priority_set(max_priority);
- return levels[priority == Depth ? 0 : priority].front();
- }
-
- [[nodiscard]] T& back(u32 min_priority = Depth - 1) {
- const u32 priority = lowest_priority_set(min_priority); // intended
- return levels[priority == Depth ? 63 : priority].back();
- }
- [[nodiscard]] const T& back(u32 min_priority = Depth - 1) const {
- const u32 priority = lowest_priority_set(min_priority); // intended
- return levels[priority == Depth ? 63 : priority].back();
- }
-
- void clear() {
- used_priorities = 0;
- for (std::size_t i = 0; i < Depth; i++) {
- levels[i].clear();
- }
- }
-
-private:
- using const_list_iterator = typename std::list<T>::const_iterator;
-
- static void ListShiftForward(std::list<T>& list, const std::size_t shift = 1) {
- if (shift >= list.size()) {
- return;
- }
-
- const auto begin_range = list.begin();
- const auto end_range = std::next(begin_range, shift);
- list.splice(list.end(), list, begin_range, end_range);
- }
-
- static void ListSplice(std::list<T>& in_list, const_list_iterator position,
- std::list<T>& out_list, const_list_iterator element) {
- in_list.splice(position, out_list, element);
- }
-
- [[nodiscard]] static const_list_iterator ListIterateTo(const std::list<T>& list,
- const T& element) {
- auto it = list.cbegin();
- while (it != list.cend() && *it != element) {
- ++it;
- }
- return it;
- }
-
- std::array<std::list<T>, Depth> levels;
- u64 used_priorities = 0;
-};
-
-} // namespace Common
diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp
index e5d3090d5..8fd8620fd 100644
--- a/src/common/page_table.cpp
+++ b/src/common/page_table.cpp
@@ -8,18 +8,12 @@ namespace Common {
PageTable::PageTable() = default;
-PageTable::~PageTable() = default;
+PageTable::~PageTable() noexcept = default;
-void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
- bool has_attribute) {
- const std::size_t num_page_table_entries{1ULL
- << (address_space_width_in_bits - page_size_in_bits)};
+void PageTable::Resize(size_t address_space_width_in_bits, size_t page_size_in_bits) {
+ const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)};
pointers.resize(num_page_table_entries);
backing_addr.resize(num_page_table_entries);
-
- if (has_attribute) {
- attributes.resize(num_page_table_entries);
- }
}
} // namespace Common
diff --git a/src/common/page_table.h b/src/common/page_table.h
index cf5eed780..61c5552e0 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -4,12 +4,10 @@
#pragma once
-#include <vector>
-
-#include <boost/icl/interval_map.hpp>
+#include <atomic>
+#include <tuple>
#include "common/common_types.h"
-#include "common/memory_hook.h"
#include "common/virtual_buffer.h"
namespace Common {
@@ -22,27 +20,6 @@ enum class PageType : u8 {
/// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
/// invalidation
RasterizerCachedMemory,
- /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
- Special,
- /// Page is allocated for use.
- Allocated,
-};
-
-struct SpecialRegion {
- enum class Type {
- DebugHook,
- IODevice,
- } type;
-
- MemoryHookPointer handler;
-
- [[nodiscard]] bool operator<(const SpecialRegion& other) const {
- return std::tie(type, handler) < std::tie(other.type, other.handler);
- }
-
- [[nodiscard]] bool operator==(const SpecialRegion& other) const {
- return std::tie(type, handler) == std::tie(other.type, other.handler);
- }
};
/**
@@ -50,27 +27,84 @@ struct SpecialRegion {
* mimics the way a real CPU page table works.
*/
struct PageTable {
+ /// Number of bits reserved for attribute tagging.
+ /// This can be at most the guaranteed alignment of the pointers in the page table.
+ static constexpr int ATTRIBUTE_BITS = 2;
+
+ /**
+ * Pair of host pointer and page type attribute.
+ * This uses the lower bits of a given pointer to store the attribute tag.
+ * Writing and reading the pointer attribute pair is guaranteed to be atomic for the same method
+ * call. In other words, they are guaranteed to be synchronized at all times.
+ */
+ class PageInfo {
+ public:
+ /// Returns the page pointer
+ [[nodiscard]] u8* Pointer() const noexcept {
+ return ExtractPointer(raw.load(std::memory_order_relaxed));
+ }
+
+ /// Returns the page type attribute
+ [[nodiscard]] PageType Type() const noexcept {
+ return ExtractType(raw.load(std::memory_order_relaxed));
+ }
+
+ /// Returns the page pointer and attribute pair, extracted from the same atomic read
+ [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept {
+ const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
+ return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
+ }
+
+ /// Returns the raw representation of the page information.
+ /// Use ExtractPointer and ExtractType to unpack the value.
+ [[nodiscard]] uintptr_t Raw() const noexcept {
+ return raw.load(std::memory_order_relaxed);
+ }
+
+ /// Write a page pointer and type pair atomically
+ void Store(u8* pointer, PageType type) noexcept {
+ raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type));
+ }
+
+ /// Unpack a pointer from a page info raw representation
+ [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept {
+ return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS));
+ }
+
+ /// Unpack a page type from a page info raw representation
+ [[nodiscard]] static PageType ExtractType(uintptr_t raw) noexcept {
+ return static_cast<PageType>(raw & ((uintptr_t{1} << ATTRIBUTE_BITS) - 1));
+ }
+
+ private:
+ std::atomic<uintptr_t> raw;
+ };
+
PageTable();
- ~PageTable();
+ ~PageTable() noexcept;
+
+ PageTable(const PageTable&) = delete;
+ PageTable& operator=(const PageTable&) = delete;
+
+ PageTable(PageTable&&) noexcept = default;
+ PageTable& operator=(PageTable&&) noexcept = default;
/**
- * Resizes the page table to be able to accomodate enough pages within
+ * Resizes the page table to be able to accommodate enough pages within
* a given address space.
*
* @param address_space_width_in_bits The address size width in bits.
+ * @param page_size_in_bits The page size in bits.
*/
- void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
- bool has_attribute);
+ void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits);
/**
* Vector of memory pointers backing each page. An entry can only be non-null if the
- * corresponding entry in the `attributes` vector is of type `Memory`.
+ * corresponding attribute element is of type `Memory`.
*/
- VirtualBuffer<u8*> pointers;
+ VirtualBuffer<PageInfo> pointers;
VirtualBuffer<u64> backing_addr;
-
- VirtualBuffer<PageType> attributes;
};
} // namespace Common
diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index 68ef5f197..fa46cb394 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -10,7 +10,7 @@
namespace detail {
template <typename Func>
struct ScopeExitHelper {
- explicit ScopeExitHelper(Func&& func) : func(std::move(func)) {}
+ explicit ScopeExitHelper(Func&& func_) : func(std::move(func_)) {}
~ScopeExitHelper() {
if (active) {
func();
diff --git a/src/common/spin_lock.h b/src/common/spin_lock.h
index 4f946a258..06ac2f5bb 100644
--- a/src/common/spin_lock.h
+++ b/src/common/spin_lock.h
@@ -15,6 +15,14 @@ namespace Common {
*/
class SpinLock {
public:
+ SpinLock() = default;
+
+ SpinLock(const SpinLock&) = delete;
+ SpinLock& operator=(const SpinLock&) = delete;
+
+ SpinLock(SpinLock&&) = delete;
+ SpinLock& operator=(SpinLock&&) = delete;
+
void lock();
void unlock();
[[nodiscard]] bool try_lock();
diff --git a/src/common/stream.cpp b/src/common/stream.cpp
new file mode 100644
index 000000000..bf0496c26
--- /dev/null
+++ b/src/common/stream.cpp
@@ -0,0 +1,47 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <stdexcept>
+#include "common/common_types.h"
+#include "common/stream.h"
+
+namespace Common {
+
+Stream::Stream() = default;
+Stream::~Stream() = default;
+
+void Stream::Seek(s32 offset, SeekOrigin origin) {
+ if (origin == SeekOrigin::SetOrigin) {
+ if (offset < 0) {
+ position = 0;
+ } else if (position >= buffer.size()) {
+ position = buffer.size();
+ } else {
+ position = offset;
+ }
+ } else if (origin == SeekOrigin::FromCurrentPos) {
+ Seek(static_cast<s32>(position) + offset, SeekOrigin::SetOrigin);
+ } else if (origin == SeekOrigin::FromEnd) {
+ Seek(static_cast<s32>(buffer.size()) - offset, SeekOrigin::SetOrigin);
+ }
+}
+
+u8 Stream::ReadByte() {
+ if (position < buffer.size()) {
+ return buffer[position++];
+ } else {
+ throw std::out_of_range("Attempting to read a byte not within the buffer range");
+ }
+}
+
+void Stream::WriteByte(u8 byte) {
+ if (position == buffer.size()) {
+ buffer.push_back(byte);
+ position++;
+ } else {
+ buffer.insert(buffer.begin() + position, byte);
+ }
+}
+
+} // namespace Common
diff --git a/src/common/stream.h b/src/common/stream.h
new file mode 100644
index 000000000..0e40692de
--- /dev/null
+++ b/src/common/stream.h
@@ -0,0 +1,56 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include "common/common_types.h"
+
+namespace Common {
+
+enum class SeekOrigin {
+ SetOrigin,
+ FromCurrentPos,
+ FromEnd,
+};
+
+class Stream {
+public:
+ /// Stream creates a bitstream and provides common functionality on the stream.
+ explicit Stream();
+ ~Stream();
+
+ Stream(const Stream&) = delete;
+ Stream& operator=(const Stream&) = delete;
+
+ Stream(Stream&&) = default;
+ Stream& operator=(Stream&&) = default;
+
+ /// Reposition bitstream "cursor" to the specified offset from origin
+ void Seek(s32 offset, SeekOrigin origin);
+
+ /// Reads next byte in the stream buffer and increments position
+ u8 ReadByte();
+
+ /// Writes byte at current position
+ void WriteByte(u8 byte);
+
+ [[nodiscard]] std::size_t GetPosition() const {
+ return position;
+ }
+
+ [[nodiscard]] std::vector<u8>& GetBuffer() {
+ return buffer;
+ }
+
+ [[nodiscard]] const std::vector<u8>& GetBuffer() const {
+ return buffer;
+ }
+
+private:
+ std::vector<u8> buffer;
+ std::size_t position{0};
+};
+
+} // namespace Common
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 84883a1d3..4cba2aaa4 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -8,6 +8,7 @@
#include <cstdlib>
#include <locale>
#include <sstream>
+
#include "common/common_paths.h"
#include "common/logging/log.h"
#include "common/string_util.h"
@@ -21,14 +22,14 @@ namespace Common {
/// Make a string lowercase
std::string ToLower(std::string str) {
std::transform(str.begin(), str.end(), str.begin(),
- [](unsigned char c) { return std::tolower(c); });
+ [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
return str;
}
/// Make a string uppercase
std::string ToUpper(std::string str) {
std::transform(str.begin(), str.end(), str.begin(),
- [](unsigned char c) { return std::toupper(c); });
+ [](unsigned char c) { return static_cast<char>(std::toupper(c)); });
return str;
}
diff --git a/src/common/swap.h b/src/common/swap.h
index 7665942a2..a80e191dc 100644
--- a/src/common/swap.h
+++ b/src/common/swap.h
@@ -394,7 +394,7 @@ public:
template <typename S, typename T2, typename F2>
friend S operator%(const S& p, const swapped_t v);
- // Arithmetics + assignements
+ // Arithmetics + assignments
template <typename S, typename T2, typename F2>
friend S operator+=(const S& p, const swapped_t v);
@@ -451,7 +451,7 @@ S operator%(const S& i, const swap_struct_t<T, F> v) {
return i % v.swap();
}
-// Arithmetics + assignements
+// Arithmetics + assignments
template <typename S, typename T, typename F>
S& operator+=(S& i, const swap_struct_t<T, F> v) {
i += v.swap();
diff --git a/src/common/telemetry.h b/src/common/telemetry.h
index a50c5d1de..49186e848 100644
--- a/src/common/telemetry.h
+++ b/src/common/telemetry.h
@@ -52,8 +52,8 @@ public:
template <typename T>
class Field : public FieldInterface {
public:
- Field(FieldType type, std::string name, T value)
- : name(std::move(name)), type(type), value(std::move(value)) {}
+ Field(FieldType type_, std::string name_, T value_)
+ : name(std::move(name_)), type(type_), value(std::move(value_)) {}
Field(const Field&) = default;
Field& operator=(const Field&) = default;
diff --git a/src/common/thread_worker.cpp b/src/common/thread_worker.cpp
new file mode 100644
index 000000000..8f9bf447a
--- /dev/null
+++ b/src/common/thread_worker.cpp
@@ -0,0 +1,58 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/thread.h"
+#include "common/thread_worker.h"
+
+namespace Common {
+
+ThreadWorker::ThreadWorker(std::size_t num_workers, const std::string& name) {
+ for (std::size_t i = 0; i < num_workers; ++i)
+ threads.emplace_back([this, thread_name{std::string{name}}] {
+ Common::SetCurrentThreadName(thread_name.c_str());
+
+ // Wait for first request
+ {
+ std::unique_lock lock{queue_mutex};
+ condition.wait(lock, [this] { return stop || !requests.empty(); });
+ }
+
+ while (true) {
+ std::function<void()> task;
+
+ {
+ std::unique_lock lock{queue_mutex};
+ condition.wait(lock, [this] { return stop || !requests.empty(); });
+ if (stop || requests.empty()) {
+ return;
+ }
+ task = std::move(requests.front());
+ requests.pop();
+ }
+
+ task();
+ }
+ });
+}
+
+ThreadWorker::~ThreadWorker() {
+ {
+ std::unique_lock lock{queue_mutex};
+ stop = true;
+ }
+ condition.notify_all();
+ for (std::thread& thread : threads) {
+ thread.join();
+ }
+}
+
+void ThreadWorker::QueueWork(std::function<void()>&& work) {
+ {
+ std::unique_lock lock{queue_mutex};
+ requests.emplace(work);
+ }
+ condition.notify_one();
+}
+
+} // namespace Common
diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h
new file mode 100644
index 000000000..f1859971f
--- /dev/null
+++ b/src/common/thread_worker.h
@@ -0,0 +1,30 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+#include <functional>
+#include <mutex>
+#include <string>
+#include <vector>
+#include <queue>
+
+namespace Common {
+
+class ThreadWorker final {
+public:
+ explicit ThreadWorker(std::size_t num_workers, const std::string& name);
+ ~ThreadWorker();
+ void QueueWork(std::function<void()>&& work);
+
+private:
+ std::vector<std::thread> threads;
+ std::queue<std::function<void()>> requests;
+ std::mutex queue_mutex;
+ std::condition_variable condition;
+ std::atomic_bool stop{};
+};
+
+} // namespace Common
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index 2dc15e434..d17dc2a50 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -142,20 +142,18 @@ std::string Timer::GetTimeFormatted() {
// ----------------
double Timer::GetDoubleTime() {
// Get continuous timestamp
- u64 TmpSeconds = static_cast<u64>(Common::Timer::GetTimeSinceJan1970().count());
- double ms = static_cast<u64>(GetTimeMs().count()) % 1000;
+ auto tmp_seconds = static_cast<u64>(GetTimeSinceJan1970().count());
+ const auto ms = static_cast<double>(static_cast<u64>(GetTimeMs().count()) % 1000);
// Remove a few years. We only really want enough seconds to make
// sure that we are detecting actual actions, perhaps 60 seconds is
// enough really, but I leave a year of seconds anyway, in case the
// user's clock is incorrect or something like that.
- TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
+ tmp_seconds = tmp_seconds - (38 * 365 * 24 * 60 * 60);
// Make a smaller integer that fits in the double
- u32 Seconds = static_cast<u32>(TmpSeconds);
- double TmpTime = Seconds + ms;
-
- return TmpTime;
+ const auto seconds = static_cast<u32>(tmp_seconds);
+ return seconds + ms;
}
} // Namespace Common
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index 2a0fcf541..22dba3c2d 100644
--- a/src/common/vector_math.h
+++ b/src/common/vector_math.h
@@ -87,7 +87,13 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec2<decltype(T{} * V{})> operator*(const V& f) const {
- return {x * f, y * f};
+ using TV = decltype(T{} * V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
+ };
}
template <typename V>
@@ -98,7 +104,13 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec2<decltype(T{} / V{})> operator/(const V& f) const {
- return {x / f, y / f};
+ using TV = decltype(T{} / V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
+ };
}
template <typename V>
@@ -168,7 +180,10 @@ public:
template <typename T, typename V>
[[nodiscard]] constexpr Vec2<T> operator*(const V& f, const Vec2<T>& vec) {
- return Vec2<T>(f * vec.x, f * vec.y);
+ using C = std::common_type_t<T, V>;
+
+ return Vec2<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
+ static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)));
}
using Vec2f = Vec2<float>;
@@ -237,7 +252,14 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec3<decltype(T{} * V{})> operator*(const V& f) const {
- return {x * f, y * f, z * f};
+ using TV = decltype(T{} * V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
+ };
}
template <typename V>
@@ -247,7 +269,14 @@ public:
}
template <typename V>
[[nodiscard]] constexpr Vec3<decltype(T{} / V{})> operator/(const V& f) const {
- return {x / f, y / f, z / f};
+ using TV = decltype(T{} / V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
+ };
}
template <typename V>
@@ -367,7 +396,11 @@ public:
template <typename T, typename V>
[[nodiscard]] constexpr Vec3<T> operator*(const V& f, const Vec3<T>& vec) {
- return Vec3<T>(f * vec.x, f * vec.y, f * vec.z);
+ using C = std::common_type_t<T, V>;
+
+ return Vec3<T>(static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.x)),
+ static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.y)),
+ static_cast<T>(static_cast<C>(f) * static_cast<C>(vec.z)));
}
template <>
@@ -446,7 +479,15 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec4<decltype(T{} * V{})> operator*(const V& f) const {
- return {x * f, y * f, z * f, w * f};
+ using TV = decltype(T{} * V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) * static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(w) * static_cast<C>(f)),
+ };
}
template <typename V>
@@ -457,7 +498,15 @@ public:
template <typename V>
[[nodiscard]] constexpr Vec4<decltype(T{} / V{})> operator/(const V& f) const {
- return {x / f, y / f, z / f, w / f};
+ using TV = decltype(T{} / V{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(x) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(y) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(z) / static_cast<C>(f)),
+ static_cast<TV>(static_cast<C>(w) / static_cast<C>(f)),
+ };
}
template <typename V>
@@ -582,7 +631,15 @@ public:
template <typename T, typename V>
[[nodiscard]] constexpr Vec4<decltype(V{} * T{})> operator*(const V& f, const Vec4<T>& vec) {
- return {f * vec.x, f * vec.y, f * vec.z, f * vec.w};
+ using TV = decltype(V{} * T{});
+ using C = std::common_type_t<T, V>;
+
+ return {
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.x)),
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.y)),
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.z)),
+ static_cast<TV>(static_cast<C>(f) * static_cast<C>(vec.w)),
+ };
}
using Vec4f = Vec4<float>;
diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp
index b009cb500..e3ca29258 100644
--- a/src/common/virtual_buffer.cpp
+++ b/src/common/virtual_buffer.cpp
@@ -13,7 +13,7 @@
namespace Common {
-void* AllocateMemoryPages(std::size_t size) {
+void* AllocateMemoryPages(std::size_t size) noexcept {
#ifdef _WIN32
void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)};
#else
@@ -29,7 +29,7 @@ void* AllocateMemoryPages(std::size_t size) {
return base;
}
-void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) {
+void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) noexcept {
if (!base) {
return;
}
diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h
index 125cb42f0..fb1a6f81f 100644
--- a/src/common/virtual_buffer.h
+++ b/src/common/virtual_buffer.h
@@ -4,29 +4,55 @@
#pragma once
-#include "common/common_funcs.h"
+#include <type_traits>
+#include <utility>
namespace Common {
-void* AllocateMemoryPages(std::size_t size);
-void FreeMemoryPages(void* base, std::size_t size);
+void* AllocateMemoryPages(std::size_t size) noexcept;
+void FreeMemoryPages(void* base, std::size_t size) noexcept;
template <typename T>
-class VirtualBuffer final : NonCopyable {
+class VirtualBuffer final {
public:
+ // TODO: Uncomment this and change Common::PageTable::PageInfo to be trivially constructible
+ // using std::atomic_ref once libc++ has support for it
+ // static_assert(
+ // std::is_trivially_constructible_v<T>,
+ // "T must be trivially constructible, as non-trivial constructors will not be executed "
+ // "with the current allocator");
+
constexpr VirtualBuffer() = default;
explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} {
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
}
- ~VirtualBuffer() {
+ ~VirtualBuffer() noexcept {
FreeMemoryPages(base_ptr, alloc_size);
}
+ VirtualBuffer(const VirtualBuffer&) = delete;
+ VirtualBuffer& operator=(const VirtualBuffer&) = delete;
+
+ VirtualBuffer(VirtualBuffer&& other) noexcept
+ : alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr),
+ nullptr} {}
+
+ VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
+ alloc_size = std::exchange(other.alloc_size, 0);
+ base_ptr = std::exchange(other.base_ptr, nullptr);
+ return *this;
+ }
+
void resize(std::size_t count) {
+ const auto new_size = count * sizeof(T);
+ if (new_size == alloc_size) {
+ return;
+ }
+
FreeMemoryPages(base_ptr, alloc_size);
- alloc_size = count * sizeof(T);
+ alloc_size = new_size;
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
}
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 3afbdb898..a8c143f85 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -15,10 +15,10 @@ namespace Common {
using base_timer = std::chrono::steady_clock;
using base_time_point = std::chrono::time_point<base_timer>;
-class StandardWallClock : public WallClock {
+class StandardWallClock final : public WallClock {
public:
- StandardWallClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency)
- : WallClock(emulated_cpu_frequency, emulated_clock_frequency, false) {
+ explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_)
+ : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, false) {
start_time = base_timer::now();
}
@@ -53,7 +53,7 @@ public:
return Common::Divide128On32(temporary, 1000000000).first;
}
- void Pause(bool is_paused) override {
+ void Pause([[maybe_unused]] bool is_paused) override {
// Do nothing in this clock type.
}
diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h
index 5db30083d..cef3e9499 100644
--- a/src/common/wall_clock.h
+++ b/src/common/wall_clock.h
@@ -13,6 +13,8 @@ namespace Common {
class WallClock {
public:
+ virtual ~WallClock() = default;
+
/// Returns current wall time in nanoseconds
[[nodiscard]] virtual std::chrono::nanoseconds GetTimeNS() = 0;
@@ -36,9 +38,9 @@ public:
}
protected:
- WallClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency, bool is_native)
- : emulated_cpu_frequency{emulated_cpu_frequency},
- emulated_clock_frequency{emulated_clock_frequency}, is_native{is_native} {}
+ explicit WallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_, bool is_native_)
+ : emulated_cpu_frequency{emulated_cpu_frequency_},
+ emulated_clock_frequency{emulated_clock_frequency_}, is_native{is_native_} {}
u64 emulated_cpu_frequency;
u64 emulated_clock_frequency;
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 424b39b1f..eb8a7782f 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -43,10 +43,10 @@ u64 EstimateRDTSCFrequency() {
}
namespace X64 {
-NativeClock::NativeClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency,
- u64 rtsc_frequency)
- : WallClock(emulated_cpu_frequency, emulated_clock_frequency, true), rtsc_frequency{
- rtsc_frequency} {
+NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_,
+ u64 rtsc_frequency_)
+ : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{
+ rtsc_frequency_} {
_mm_mfence();
last_measure = __rdtsc();
accumulated_ticks = 0U;
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index 891a3bbfd..6d1e32ac8 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -12,9 +12,10 @@
namespace Common {
namespace X64 {
-class NativeClock : public WallClock {
+class NativeClock final : public WallClock {
public:
- NativeClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequency, u64 rtsc_frequency);
+ explicit NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_,
+ u64 rtsc_frequency_);
std::chrono::nanoseconds GetTimeNS() override;
@@ -34,7 +35,7 @@ private:
/// value used to reduce the native clocks accuracy as some apss rely on
/// undefined behavior where the level of accuracy in the clock shouldn't
/// be higher.
- static constexpr u64 inaccuracy_mask = ~(0x400 - 1);
+ static constexpr u64 inaccuracy_mask = ~(UINT64_C(0x400) - 1);
SpinLock rtsc_serialize{};
u64 last_measure{};
diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h
index 26e4bfda5..c2c9b6134 100644
--- a/src/common/x64/xbyak_abi.h
+++ b/src/common/x64/xbyak_abi.h
@@ -11,25 +11,25 @@
namespace Common::X64 {
-constexpr std::size_t RegToIndex(const Xbyak::Reg& reg) {
+constexpr size_t RegToIndex(const Xbyak::Reg& reg) {
using Kind = Xbyak::Reg::Kind;
ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0,
"RegSet only support GPRs and XMM registers.");
ASSERT_MSG(reg.getIdx() < 16, "RegSet only supports XXM0-15.");
- return reg.getIdx() + (reg.getKind() == Kind::REG ? 0 : 16);
+ return static_cast<size_t>(reg.getIdx()) + (reg.getKind() == Kind::REG ? 0 : 16);
}
-constexpr Xbyak::Reg64 IndexToReg64(std::size_t reg_index) {
+constexpr Xbyak::Reg64 IndexToReg64(size_t reg_index) {
ASSERT(reg_index < 16);
return Xbyak::Reg64(static_cast<int>(reg_index));
}
-constexpr Xbyak::Xmm IndexToXmm(std::size_t reg_index) {
+constexpr Xbyak::Xmm IndexToXmm(size_t reg_index) {
ASSERT(reg_index >= 16 && reg_index < 32);
return Xbyak::Xmm(static_cast<int>(reg_index - 16));
}
-constexpr Xbyak::Reg IndexToReg(std::size_t reg_index) {
+constexpr Xbyak::Reg IndexToReg(size_t reg_index) {
if (reg_index < 16) {
return IndexToReg64(reg_index);
} else {
@@ -182,7 +182,7 @@ inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::b
size_t rsp_alignment, size_t needed_frame_size = 0) {
auto frame_info = ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size);
- for (std::size_t i = 0; i < regs.size(); ++i) {
+ for (size_t i = 0; i < regs.size(); ++i) {
if (regs[i] && ABI_ALL_GPRS[i]) {
code.push(IndexToReg64(i));
}
@@ -192,7 +192,7 @@ inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::b
code.sub(code.rsp, frame_info.subtraction);
}
- for (std::size_t i = 0; i < regs.size(); ++i) {
+ for (size_t i = 0; i < regs.size(); ++i) {
if (regs[i] && ABI_ALL_XMMS[i]) {
code.movaps(code.xword[code.rsp + frame_info.xmm_offset], IndexToXmm(i));
frame_info.xmm_offset += 0x10;
@@ -206,7 +206,7 @@ inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bits
size_t rsp_alignment, size_t needed_frame_size = 0) {
auto frame_info = ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size);
- for (std::size_t i = 0; i < regs.size(); ++i) {
+ for (size_t i = 0; i < regs.size(); ++i) {
if (regs[i] && ABI_ALL_XMMS[i]) {
code.movaps(IndexToXmm(i), code.xword[code.rsp + frame_info.xmm_offset]);
frame_info.xmm_offset += 0x10;
@@ -218,8 +218,8 @@ inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bits
}
// GPRs need to be popped in reverse order
- for (std::size_t j = 0; j < regs.size(); ++j) {
- const std::size_t i = regs.size() - j - 1;
+ for (size_t j = 0; j < regs.size(); ++j) {
+ const size_t i = regs.size() - j - 1;
if (regs[i] && ABI_ALL_GPRS[i]) {
code.pop(IndexToReg64(i));
}