summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp67
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h30
-rw-r--r--src/core/arm/exclusive_monitor.cpp7
-rw-r--r--src/core/arm/exclusive_monitor.h23
-rw-r--r--src/core/core.cpp3
-rw-r--r--src/core/core.h12
-rw-r--r--src/core/core_cpu.cpp19
-rw-r--r--src/core/core_cpu.h10
-rw-r--r--src/core/file_sys/vfs.cpp111
-rw-r--r--src/core/file_sys/vfs.h57
-rw-r--r--src/core/file_sys/vfs_offset.cpp2
-rw-r--r--src/core/file_sys/vfs_offset.h5
-rw-r--r--src/core/file_sys/vfs_real.cpp57
-rw-r--r--src/core/file_sys/vfs_real.h14
-rw-r--r--src/core/hle/kernel/svc.cpp38
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp2
-rw-r--r--src/core/loader/loader.cpp3
18 files changed, 349 insertions, 113 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0a5d58eea..27a5de7fd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,5 +1,7 @@
add_library(core STATIC
arm/arm_interface.h
+ arm/exclusive_monitor.cpp
+ arm/exclusive_monitor.h
arm/unicorn/arm_unicorn.cpp
arm/unicorn/arm_unicorn.h
core.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 5d7efc9b6..83c09db2b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -102,18 +102,28 @@ public:
u64 tpidr_el0 = 0;
};
-std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) {
+std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() {
const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
Dynarmic::A64::UserConfig config;
+
+ // Callbacks
config.callbacks = cb.get();
+
+ // Memory
+ config.page_table = reinterpret_cast<void**>(page_table);
+ config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
+ config.silently_mirror_page_table = false;
+
+ // Multi-process state
+ config.processor_id = core_index;
+ config.global_monitor = &exclusive_monitor->monitor;
+
+ // System registers
config.tpidrro_el0 = &cb->tpidrro_el0;
config.tpidr_el0 = &cb->tpidr_el0;
config.dczid_el0 = 4;
config.ctr_el0 = 0x8444c004;
- config.page_table = reinterpret_cast<void**>(page_table);
- config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
- config.silently_mirror_page_table = false;
return std::make_unique<Dynarmic::A64::Jit>(config);
}
@@ -128,8 +138,11 @@ void ARM_Dynarmic::Step() {
cb->InterpreterFallback(jit->GetPC(), 1);
}
-ARM_Dynarmic::ARM_Dynarmic()
- : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) {
+ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index)
+ : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
+ jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(
+ exclusive_monitor)},
+ core_index{core_index} {
ARM_Interface::ThreadContext ctx;
inner_unicorn.SaveContext(ctx);
LoadContext(ctx);
@@ -237,6 +250,46 @@ void ARM_Dynarmic::ClearExclusiveState() {
}
void ARM_Dynarmic::PageTableChanged() {
- jit = MakeJit(cb);
+ jit = MakeJit();
current_page_table = Memory::GetCurrentPageTable();
}
+
+DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(size_t core_count) : monitor(core_count) {}
+DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
+
+void DynarmicExclusiveMonitor::SetExclusive(size_t core_index, u64 addr) {
+ // Size doesn't actually matter.
+ monitor.Mark(core_index, addr, 16);
+}
+
+void DynarmicExclusiveMonitor::ClearExclusive() {
+ monitor.Clear();
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 1,
+ [&] { Memory::Write8(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 2,
+ [&] { Memory::Write16(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 4,
+ [&] { Memory::Write32(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 8,
+ [&] { Memory::Write64(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
+ Memory::Write64(vaddr, value[0]);
+ Memory::Write64(vaddr, value[1]);
+ });
+}
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index a9891ac4f..0fa8b417c 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -6,15 +6,18 @@
#include <memory>
#include <dynarmic/A64/a64.h>
+#include <dynarmic/A64/exclusive_monitor.h>
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
+#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
class ARM_Dynarmic_Callbacks;
+class DynarmicExclusiveMonitor;
class ARM_Dynarmic final : public ARM_Interface {
public:
- ARM_Dynarmic();
+ ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index);
~ARM_Dynarmic();
void MapBackingMemory(VAddr address, size_t size, u8* memory,
@@ -47,10 +50,35 @@ public:
void PageTableChanged() override;
private:
+ std::unique_ptr<Dynarmic::A64::Jit> MakeJit();
+
friend class ARM_Dynarmic_Callbacks;
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
std::unique_ptr<Dynarmic::A64::Jit> jit;
ARM_Unicorn inner_unicorn;
+ size_t core_index;
+ std::shared_ptr<DynarmicExclusiveMonitor> exclusive_monitor;
+
Memory::PageTable* current_page_table = nullptr;
};
+
+class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
+public:
+ explicit DynarmicExclusiveMonitor(size_t core_count);
+ ~DynarmicExclusiveMonitor();
+
+ void SetExclusive(size_t core_index, u64 addr) override;
+ void ClearExclusive() override;
+
+ bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) override;
+ bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) override;
+ bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) override;
+ bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) override;
+ bool ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) override;
+
+private:
+ friend class ARM_Dynarmic;
+ Dynarmic::A64::ExclusiveMonitor monitor;
+};
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
new file mode 100644
index 000000000..cb8c81d80
--- /dev/null
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -0,0 +1,7 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/arm/exclusive_monitor.h"
+
+ExclusiveMonitor::~ExclusiveMonitor() = default;
diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h
new file mode 100644
index 000000000..acfcdb94c
--- /dev/null
+++ b/src/core/arm/exclusive_monitor.h
@@ -0,0 +1,23 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include "common/common_types.h"
+
+class ExclusiveMonitor {
+public:
+ virtual ~ExclusiveMonitor();
+
+ virtual void SetExclusive(size_t core_index, u64 addr) = 0;
+ virtual void ClearExclusive() = 0;
+
+ virtual bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) = 0;
+ virtual bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) = 0;
+ virtual bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) = 0;
+ virtual bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) = 0;
+ virtual bool ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) = 0;
+};
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9bd9f4bd9..b7f4b4532 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -171,8 +171,9 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
current_process = Kernel::Process::Create("main");
cpu_barrier = std::make_shared<CpuBarrier>();
+ cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size());
for (size_t index = 0; index < cpu_cores.size(); ++index) {
- cpu_cores[index] = std::make_shared<Cpu>(cpu_barrier, index);
+ cpu_cores[index] = std::make_shared<Cpu>(cpu_exclusive_monitor, cpu_barrier, index);
}
gpu_core = std::make_unique<Tegra::GPU>();
diff --git a/src/core/core.h b/src/core/core.h
index c6f69f001..c123fe401 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -9,6 +9,7 @@
#include <string>
#include <thread>
#include "common/common_types.h"
+#include "core/arm/exclusive_monitor.h"
#include "core/core_cpu.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/scheduler.h"
@@ -114,6 +115,11 @@ public:
return CurrentCpuCore().ArmInterface();
}
+ /// Gets the index of the currently running CPU core
+ size_t CurrentCoreIndex() {
+ return CurrentCpuCore().CoreIndex();
+ }
+
/// Gets an ARM interface to the CPU core with the specified index
ARM_Interface& ArmInterface(size_t core_index);
@@ -130,6 +136,11 @@ public:
return *CurrentCpuCore().Scheduler();
}
+ /// Gets the exclusive monitor
+ ExclusiveMonitor& Monitor() {
+ return *cpu_exclusive_monitor;
+ }
+
/// Gets the scheduler for the CPU core with the specified index
const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
@@ -186,6 +197,7 @@ private:
std::unique_ptr<Tegra::GPU> gpu_core;
std::shared_ptr<Tegra::DebugContext> debug_context;
Kernel::SharedPtr<Kernel::Process> current_process;
+ std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor;
std::shared_ptr<CpuBarrier> cpu_barrier;
std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores;
std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads;
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index f22d6a9d0..54e15a701 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -48,14 +48,15 @@ bool CpuBarrier::Rendezvous() {
return false;
}
-Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
+Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
+ std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
: cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} {
if (Settings::values.use_cpu_jit) {
#ifdef ARCHITECTURE_x86_64
- arm_interface = std::make_shared<ARM_Dynarmic>();
+ arm_interface = std::make_shared<ARM_Dynarmic>(exclusive_monitor, core_index);
#else
- cpu_core = std::make_shared<ARM_Unicorn>();
+ arm_interface = std::make_shared<ARM_Unicorn>();
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
#endif
} else {
@@ -65,6 +66,18 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
}
+std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(size_t num_cores) {
+ if (Settings::values.use_cpu_jit) {
+#ifdef ARCHITECTURE_x86_64
+ return std::make_shared<DynarmicExclusiveMonitor>(num_cores);
+#else
+ return nullptr; // TODO(merry): Passthrough exclusive monitor
+#endif
+ } else {
+ return nullptr; // TODO(merry): Passthrough exclusive monitor
+ }
+}
+
void Cpu::RunLoop(bool tight_loop) {
// Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
if (!cpu_barrier->Rendezvous()) {
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 243f0b5e7..976952903 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -10,6 +10,7 @@
#include <mutex>
#include <string>
#include "common/common_types.h"
+#include "core/arm/exclusive_monitor.h"
class ARM_Interface;
@@ -40,7 +41,8 @@ private:
class Cpu {
public:
- Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index);
+ Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
+ std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index);
void RunLoop(bool tight_loop = true);
@@ -64,6 +66,12 @@ public:
return core_index == 0;
}
+ size_t CoreIndex() const {
+ return core_index;
+ }
+
+ static std::shared_ptr<ExclusiveMonitor> MakeExclusiveMonitor(size_t num_cores);
+
private:
void Reschedule();
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 3f690f12a..b99a4fd5b 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -13,7 +13,7 @@ namespace FileSys {
VfsFile::~VfsFile() = default;
std::string VfsFile::GetExtension() const {
- return FileUtil::GetExtensionFromFilename(GetName());
+ return std::string(FileUtil::GetExtensionFromFilename(GetName()));
}
VfsDirectory::~VfsDirectory() = default;
@@ -46,64 +46,80 @@ size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) {
return Write(data.data(), data.size(), offset);
}
-std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(const std::string& path) const {
+std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const {
auto vec = FileUtil::SplitPathComponents(path);
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
vec.end());
- if (vec.empty())
+ if (vec.empty()) {
return nullptr;
- if (vec.size() == 1)
+ }
+
+ if (vec.size() == 1) {
return GetFile(vec[0]);
+ }
+
auto dir = GetSubdirectory(vec[0]);
for (size_t component = 1; component < vec.size() - 1; ++component) {
- if (dir == nullptr)
+ if (dir == nullptr) {
return nullptr;
+ }
+
dir = dir->GetSubdirectory(vec[component]);
}
- if (dir == nullptr)
+
+ if (dir == nullptr) {
return nullptr;
+ }
+
return dir->GetFile(vec.back());
}
-std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(const std::string& path) const {
- if (IsRoot())
+std::shared_ptr<VfsFile> VfsDirectory::GetFileAbsolute(std::string_view path) const {
+ if (IsRoot()) {
return GetFileRelative(path);
+ }
return GetParentDirectory()->GetFileAbsolute(path);
}
-std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(const std::string& path) const {
+std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryRelative(std::string_view path) const {
auto vec = FileUtil::SplitPathComponents(path);
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
vec.end());
- if (vec.empty())
+ if (vec.empty()) {
// TODO(DarkLordZach): Return this directory if path is '/' or similar. Can't currently
// because of const-ness
return nullptr;
+ }
+
auto dir = GetSubdirectory(vec[0]);
for (size_t component = 1; component < vec.size(); ++component) {
- if (dir == nullptr)
+ if (dir == nullptr) {
return nullptr;
+ }
+
dir = dir->GetSubdirectory(vec[component]);
}
+
return dir;
}
-std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(const std::string& path) const {
- if (IsRoot())
+std::shared_ptr<VfsDirectory> VfsDirectory::GetDirectoryAbsolute(std::string_view path) const {
+ if (IsRoot()) {
return GetDirectoryRelative(path);
+ }
return GetParentDirectory()->GetDirectoryAbsolute(path);
}
-std::shared_ptr<VfsFile> VfsDirectory::GetFile(const std::string& name) const {
+std::shared_ptr<VfsFile> VfsDirectory::GetFile(std::string_view name) const {
const auto& files = GetFiles();
const auto iter = std::find_if(files.begin(), files.end(),
[&name](const auto& file1) { return name == file1->GetName(); });
return iter == files.end() ? nullptr : *iter;
}
-std::shared_ptr<VfsDirectory> VfsDirectory::GetSubdirectory(const std::string& name) const {
+std::shared_ptr<VfsDirectory> VfsDirectory::GetSubdirectory(std::string_view name) const {
const auto& subs = GetSubdirectories();
const auto iter = std::find_if(subs.begin(), subs.end(),
[&name](const auto& file1) { return name == file1->GetName(); });
@@ -128,77 +144,96 @@ size_t VfsDirectory::GetSize() const {
return file_total + subdir_total;
}
-std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(const std::string& path) {
+std::shared_ptr<VfsFile> VfsDirectory::CreateFileRelative(std::string_view path) {
auto vec = FileUtil::SplitPathComponents(path);
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
vec.end());
- if (vec.empty())
+ if (vec.empty()) {
return nullptr;
- if (vec.size() == 1)
+ }
+
+ if (vec.size() == 1) {
return CreateFile(vec[0]);
+ }
+
auto dir = GetSubdirectory(vec[0]);
if (dir == nullptr) {
dir = CreateSubdirectory(vec[0]);
- if (dir == nullptr)
+ if (dir == nullptr) {
return nullptr;
+ }
}
return dir->CreateFileRelative(FileUtil::GetPathWithoutTop(path));
}
-std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(const std::string& path) {
- if (IsRoot())
+std::shared_ptr<VfsFile> VfsDirectory::CreateFileAbsolute(std::string_view path) {
+ if (IsRoot()) {
return CreateFileRelative(path);
+ }
+
return GetParentDirectory()->CreateFileAbsolute(path);
}
-std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(const std::string& path) {
+std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryRelative(std::string_view path) {
auto vec = FileUtil::SplitPathComponents(path);
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
vec.end());
- if (vec.empty())
+ if (vec.empty()) {
return nullptr;
- if (vec.size() == 1)
+ }
+
+ if (vec.size() == 1) {
return CreateSubdirectory(vec[0]);
+ }
+
auto dir = GetSubdirectory(vec[0]);
if (dir == nullptr) {
dir = CreateSubdirectory(vec[0]);
- if (dir == nullptr)
+ if (dir == nullptr) {
return nullptr;
+ }
}
+
return dir->CreateDirectoryRelative(FileUtil::GetPathWithoutTop(path));
}
-std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryAbsolute(const std::string& path) {
- if (IsRoot())
+std::shared_ptr<VfsDirectory> VfsDirectory::CreateDirectoryAbsolute(std::string_view path) {
+ if (IsRoot()) {
return CreateDirectoryRelative(path);
+ }
+
return GetParentDirectory()->CreateDirectoryAbsolute(path);
}
-bool VfsDirectory::DeleteSubdirectoryRecursive(const std::string& name) {
+bool VfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) {
auto dir = GetSubdirectory(name);
- if (dir == nullptr)
+ if (dir == nullptr) {
return false;
+ }
bool success = true;
for (const auto& file : dir->GetFiles()) {
- if (!DeleteFile(file->GetName()))
+ if (!DeleteFile(file->GetName())) {
success = false;
+ }
}
for (const auto& sdir : dir->GetSubdirectories()) {
- if (!dir->DeleteSubdirectoryRecursive(sdir->GetName()))
+ if (!dir->DeleteSubdirectoryRecursive(sdir->GetName())) {
success = false;
+ }
}
return success;
}
-bool VfsDirectory::Copy(const std::string& src, const std::string& dest) {
+bool VfsDirectory::Copy(std::string_view src, std::string_view dest) {
const auto f1 = GetFile(src);
auto f2 = CreateFile(dest);
- if (f1 == nullptr || f2 == nullptr)
+ if (f1 == nullptr || f2 == nullptr) {
return false;
+ }
if (!f2->Resize(f1->GetSize())) {
DeleteFile(dest);
@@ -216,23 +251,23 @@ bool ReadOnlyVfsDirectory::IsReadable() const {
return true;
}
-std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateSubdirectory(const std::string& name) {
+std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateSubdirectory(std::string_view name) {
return nullptr;
}
-std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFile(const std::string& name) {
+std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFile(std::string_view name) {
return nullptr;
}
-bool ReadOnlyVfsDirectory::DeleteSubdirectory(const std::string& name) {
+bool ReadOnlyVfsDirectory::DeleteSubdirectory(std::string_view name) {
return false;
}
-bool ReadOnlyVfsDirectory::DeleteFile(const std::string& name) {
+bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) {
return false;
}
-bool ReadOnlyVfsDirectory::Rename(const std::string& name) {
+bool ReadOnlyVfsDirectory::Rename(std::string_view name) {
return false;
}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index db3c77eac..4a13b8378 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -6,11 +6,11 @@
#include <memory>
#include <string>
+#include <string_view>
#include <type_traits>
#include <vector>
#include "boost/optional.hpp"
#include "common/common_types.h"
-#include "common/file_util.h"
namespace FileSys {
struct VfsFile;
@@ -112,7 +112,7 @@ struct VfsFile : NonCopyable {
}
// Renames the file to name. Returns whether or not the operation was successsful.
- virtual bool Rename(const std::string& name) = 0;
+ virtual bool Rename(std::string_view name) = 0;
};
// A class representing a directory in an abstract filesystem.
@@ -121,27 +121,27 @@ struct VfsDirectory : NonCopyable {
// Retrives the file located at path as if the current directory was root. Returns nullptr if
// not found.
- virtual std::shared_ptr<VfsFile> GetFileRelative(const std::string& path) const;
+ virtual std::shared_ptr<VfsFile> GetFileRelative(std::string_view path) const;
// Calls GetFileRelative(path) on the root of the current directory.
- virtual std::shared_ptr<VfsFile> GetFileAbsolute(const std::string& path) const;
+ virtual std::shared_ptr<VfsFile> GetFileAbsolute(std::string_view path) const;
// Retrives the directory located at path as if the current directory was root. Returns nullptr
// if not found.
- virtual std::shared_ptr<VfsDirectory> GetDirectoryRelative(const std::string& path) const;
+ virtual std::shared_ptr<VfsDirectory> GetDirectoryRelative(std::string_view path) const;
// Calls GetDirectoryRelative(path) on the root of the current directory.
- virtual std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(const std::string& path) const;
+ virtual std::shared_ptr<VfsDirectory> GetDirectoryAbsolute(std::string_view path) const;
// Returns a vector containing all of the files in this directory.
virtual std::vector<std::shared_ptr<VfsFile>> GetFiles() const = 0;
// Returns the file with filename matching name. Returns nullptr if directory dosen't have a
// file with name.
- virtual std::shared_ptr<VfsFile> GetFile(const std::string& name) const;
+ virtual std::shared_ptr<VfsFile> GetFile(std::string_view name) const;
// Returns a vector containing all of the subdirectories in this directory.
virtual std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const = 0;
// Returns the directory with name matching name. Returns nullptr if directory dosen't have a
// directory with name.
- virtual std::shared_ptr<VfsDirectory> GetSubdirectory(const std::string& name) const;
+ virtual std::shared_ptr<VfsDirectory> GetSubdirectory(std::string_view name) const;
// Returns whether or not the directory can be written to.
virtual bool IsWritable() const = 0;
@@ -161,53 +161,56 @@ struct VfsDirectory : NonCopyable {
// Creates a new subdirectory with name name. Returns a pointer to the new directory or nullptr
// if the operation failed.
- virtual std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) = 0;
+ virtual std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) = 0;
// Creates a new file with name name. Returns a pointer to the new file or nullptr if the
// operation failed.
- virtual std::shared_ptr<VfsFile> CreateFile(const std::string& name) = 0;
+ virtual std::shared_ptr<VfsFile> CreateFile(std::string_view name) = 0;
// Creates a new file at the path relative to this directory. Also creates directories if
// they do not exist and is supported by this implementation. Returns nullptr on any failure.
- virtual std::shared_ptr<VfsFile> CreateFileRelative(const std::string& path);
+ virtual std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path);
// Creates a new file at the path relative to root of this directory. Also creates directories
// if they do not exist and is supported by this implementation. Returns nullptr on any failure.
- virtual std::shared_ptr<VfsFile> CreateFileAbsolute(const std::string& path);
+ virtual std::shared_ptr<VfsFile> CreateFileAbsolute(std::string_view path);
// Creates a new directory at the path relative to this directory. Also creates directories if
// they do not exist and is supported by this implementation. Returns nullptr on any failure.
- virtual std::shared_ptr<VfsDirectory> CreateDirectoryRelative(const std::string& path);
+ virtual std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path);
// Creates a new directory at the path relative to root of this directory. Also creates
// directories if they do not exist and is supported by this implementation. Returns nullptr on
// any failure.
- virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(const std::string& path);
+ virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path);
// Deletes the subdirectory with name and returns true on success.
- virtual bool DeleteSubdirectory(const std::string& name) = 0;
+ virtual bool DeleteSubdirectory(std::string_view name) = 0;
// Deletes all subdirectories and files of subdirectory with name recirsively and then deletes
// the subdirectory. Returns true on success.
- virtual bool DeleteSubdirectoryRecursive(const std::string& name);
+ virtual bool DeleteSubdirectoryRecursive(std::string_view name);
// Returnes whether or not the file with name name was deleted successfully.
- virtual bool DeleteFile(const std::string& name) = 0;
+ virtual bool DeleteFile(std::string_view name) = 0;
// Returns whether or not this directory was renamed to name.
- virtual bool Rename(const std::string& name) = 0;
+ virtual bool Rename(std::string_view name) = 0;
// Returns whether or not the file with name src was successfully copied to a new file with name
// dest.
- virtual bool Copy(const std::string& src, const std::string& dest);
+ virtual bool Copy(std::string_view src, std::string_view dest);
// Interprets the file with name file instead as a directory of type directory.
// The directory must have a constructor that takes a single argument of type
// std::shared_ptr<VfsFile>. Allows to reinterpret container files (i.e NCA, zip, XCI, etc) as a
// subdirectory in one call.
template <typename Directory>
- bool InterpretAsDirectory(const std::string& file) {
+ bool InterpretAsDirectory(std::string_view file) {
auto file_p = GetFile(file);
- if (file_p == nullptr)
+
+ if (file_p == nullptr) {
return false;
- return ReplaceFileWithSubdirectory(file, std::make_shared<Directory>(file_p));
+ }
+
+ return ReplaceFileWithSubdirectory(file_p, std::make_shared<Directory>(file_p));
}
protected:
@@ -221,10 +224,10 @@ protected:
struct ReadOnlyVfsDirectory : public VfsDirectory {
bool IsWritable() const override;
bool IsReadable() const override;
- std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) override;
- std::shared_ptr<VfsFile> CreateFile(const std::string& name) override;
- bool DeleteSubdirectory(const std::string& name) override;
- bool DeleteFile(const std::string& name) override;
- bool Rename(const std::string& name) override;
+ std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
+ std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
+ bool DeleteSubdirectory(std::string_view name) override;
+ bool DeleteFile(std::string_view name) override;
+ bool Rename(std::string_view name) override;
};
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp
index 217e02235..a40331cef 100644
--- a/src/core/file_sys/vfs_offset.cpp
+++ b/src/core/file_sys/vfs_offset.cpp
@@ -80,7 +80,7 @@ size_t OffsetVfsFile::WriteBytes(const std::vector<u8>& data, size_t r_offset) {
return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset);
}
-bool OffsetVfsFile::Rename(const std::string& name) {
+bool OffsetVfsFile::Rename(std::string_view name) {
return file->Rename(name);
}
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h
index ded4827f5..4f471e3ba 100644
--- a/src/core/file_sys/vfs_offset.h
+++ b/src/core/file_sys/vfs_offset.h
@@ -4,6 +4,9 @@
#pragma once
+#include <memory>
+#include <string_view>
+
#include "core/file_sys/vfs.h"
namespace FileSys {
@@ -30,7 +33,7 @@ struct OffsetVfsFile : public VfsFile {
bool WriteByte(u8 data, size_t offset) override;
size_t WriteBytes(const std::vector<u8>& data, size_t offset) override;
- bool Rename(const std::string& name) override;
+ bool Rename(std::string_view name) override;
size_t GetOffset() const;
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 27fd464ae..095fec77e 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -72,12 +72,15 @@ size_t RealVfsFile::Write(const u8* data, size_t length, size_t offset) {
return backing.WriteBytes(data, length);
}
-bool RealVfsFile::Rename(const std::string& name) {
- const auto out = FileUtil::Rename(GetName(), name);
- path = parent_path + DIR_SEP + name;
+bool RealVfsFile::Rename(std::string_view name) {
+ std::string name_str(name.begin(), name.end());
+ const auto out = FileUtil::Rename(GetName(), name_str);
+
+ path = (parent_path + DIR_SEP).append(name);
path_components = parent_components;
- path_components.push_back(name);
+ path_components.push_back(std::move(name_str));
backing = FileUtil::IOFile(path, PermissionsToCharArray(perms).c_str());
+
return out;
}
@@ -135,36 +138,54 @@ std::shared_ptr<VfsDirectory> RealVfsDirectory::GetParentDirectory() const {
return std::make_shared<RealVfsDirectory>(parent_path, perms);
}
-std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(const std::string& name) {
- if (!FileUtil::CreateDir(path + DIR_SEP + name))
+std::shared_ptr<VfsDirectory> RealVfsDirectory::CreateSubdirectory(std::string_view name) {
+ const std::string subdir_path = (path + DIR_SEP).append(name);
+
+ if (!FileUtil::CreateDir(subdir_path)) {
return nullptr;
- subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(path + DIR_SEP + name, perms));
+ }
+
+ subdirectories.emplace_back(std::make_shared<RealVfsDirectory>(subdir_path, perms));
return subdirectories.back();
}
-std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(const std::string& name) {
- if (!FileUtil::CreateEmptyFile(path + DIR_SEP + name))
+std::shared_ptr<VfsFile> RealVfsDirectory::CreateFile(std::string_view name) {
+ const std::string file_path = (path + DIR_SEP).append(name);
+
+ if (!FileUtil::CreateEmptyFile(file_path)) {
return nullptr;
- files.emplace_back(std::make_shared<RealVfsFile>(path + DIR_SEP + name, perms));
+ }
+
+ files.emplace_back(std::make_shared<RealVfsFile>(file_path, perms));
return files.back();
}
-bool RealVfsDirectory::DeleteSubdirectory(const std::string& name) {
- return FileUtil::DeleteDirRecursively(path + DIR_SEP + name);
+bool RealVfsDirectory::DeleteSubdirectory(std::string_view name) {
+ const std::string subdir_path = (path + DIR_SEP).append(name);
+
+ return FileUtil::DeleteDirRecursively(subdir_path);
}
-bool RealVfsDirectory::DeleteFile(const std::string& name) {
- auto file = GetFile(name);
- if (file == nullptr)
+bool RealVfsDirectory::DeleteFile(std::string_view name) {
+ const auto file = GetFile(name);
+
+ if (file == nullptr) {
return false;
+ }
+
files.erase(std::find(files.begin(), files.end(), file));
+
auto real_file = std::static_pointer_cast<RealVfsFile>(file);
real_file->Close();
- return FileUtil::Delete(path + DIR_SEP + name);
+
+ const std::string file_path = (path + DIR_SEP).append(name);
+ return FileUtil::Delete(file_path);
}
-bool RealVfsDirectory::Rename(const std::string& name) {
- return FileUtil::Rename(path, parent_path + DIR_SEP + name);
+bool RealVfsDirectory::Rename(std::string_view name) {
+ const std::string new_name = (parent_path + DIR_SEP).append(name);
+
+ return FileUtil::Rename(path, new_name);
}
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index 5b765a552..2151211c9 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -4,6 +4,8 @@
#pragma once
+#include <string_view>
+
#include "common/file_util.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/vfs.h"
@@ -24,7 +26,7 @@ struct RealVfsFile : public VfsFile {
bool IsReadable() const override;
size_t Read(u8* data, size_t length, size_t offset) const override;
size_t Write(const u8* data, size_t length, size_t offset) override;
- bool Rename(const std::string& name) override;
+ bool Rename(std::string_view name) override;
private:
bool Close();
@@ -47,11 +49,11 @@ struct RealVfsDirectory : public VfsDirectory {
bool IsReadable() const override;
std::string GetName() const override;
std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
- std::shared_ptr<VfsDirectory> CreateSubdirectory(const std::string& name) override;
- std::shared_ptr<VfsFile> CreateFile(const std::string& name) override;
- bool DeleteSubdirectory(const std::string& name) override;
- bool DeleteFile(const std::string& name) override;
- bool Rename(const std::string& name) override;
+ std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
+ std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
+ bool DeleteSubdirectory(std::string_view name) override;
+ bool DeleteFile(std::string_view name) override;
+ bool Rename(std::string_view name) override;
protected:
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 6b2995fe2..7b41c9cfd 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -650,12 +650,27 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
ASSERT(thread->condvar_wait_address == condition_variable_addr);
- // If the mutex is not yet acquired, acquire it.
- u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
+ size_t current_core = Core::System::GetInstance().CurrentCoreIndex();
+
+ auto& monitor = Core::System::GetInstance().Monitor();
+
+ // Atomically read the value of the mutex.
+ u32 mutex_val = 0;
+ do {
+ monitor.SetExclusive(current_core, thread->mutex_wait_address);
+
+ // If the mutex is not yet acquired, acquire it.
+ mutex_val = Memory::Read32(thread->mutex_wait_address);
+
+ if (mutex_val != 0) {
+ monitor.ClearExclusive();
+ break;
+ }
+ } while (!monitor.ExclusiveWrite32(current_core, thread->mutex_wait_address,
+ thread->wait_handle));
if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread.
- Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == ThreadStatus::WaitMutex);
thread->ResumeFromWait();
@@ -668,7 +683,19 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
} else {
- // Couldn't acquire the mutex, block the thread.
+ // Atomically signal that the mutex now has a waiting thread.
+ do {
+ monitor.SetExclusive(current_core, thread->mutex_wait_address);
+
+ // Ensure that the mutex value is still what we expect.
+ u32 value = Memory::Read32(thread->mutex_wait_address);
+ // TODO(Subv): When this happens, the kernel just clears the exclusive state and
+ // retries the initial read for this thread.
+ ASSERT_MSG(mutex_val == value, "Unhandled synchronization primitive case");
+ } while (!monitor.ExclusiveWrite32(current_core, thread->mutex_wait_address,
+ mutex_val | Mutex::MutexHasWaitersFlag));
+
+ // The mutex is already owned by some other thread, make this thread wait on it.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
@@ -676,9 +703,6 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
thread->status = ThreadStatus::WaitMutex;
thread->wakeup_callback = nullptr;
- // Signal that the mutex now has a waiting thread.
- Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
-
owner->AddMutexWaiter(thread);
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 671e0b8d0..dbfe06cbc 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -24,7 +24,7 @@ namespace Service::FileSystem {
constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
- const std::string& dir_name) {
+ std::string_view dir_name) {
if (dir_name.empty() || dir_name == "." || dir_name == "/" || dir_name == "\\")
return base;
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index e70f37677..4cbd9e285 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -49,7 +49,8 @@ FileType GuessFromFilename(const std::string& name) {
if (name == "main")
return FileType::DeconstructedRomDirectory;
- const std::string extension = Common::ToLower(FileUtil::GetExtensionFromFilename(name));
+ const std::string extension =
+ Common::ToLower(std::string(FileUtil::GetExtensionFromFilename(name)));
if (extension == "elf")
return FileType::ELF;