early-access version 2814

This commit is contained in:
pineappleEA 2022-07-03 10:24:53 +02:00
parent dc2419801a
commit b45f33b6ff
35 changed files with 12094 additions and 8178 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access
=============
This is the source code for early-access 2813.
This is the source code for early-access 2814.
## Legal Notice

864
dist/languages/ca.ts vendored

File diff suppressed because it is too large Load diff

925
dist/languages/cs.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/da.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/de.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/el.ts vendored

File diff suppressed because it is too large Load diff

868
dist/languages/es.ts vendored

File diff suppressed because it is too large Load diff

868
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/id.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/it.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

864
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load diff

864
dist/languages/pl.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

864
dist/languages/sv.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

864
dist/languages/vi.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -20,10 +20,8 @@ struct Fiber::FiberImpl {
VirtualBuffer<u8> rewind_stack;
std::mutex guard;
std::function<void(void*)> entry_point;
std::function<void(void*)> rewind_point;
void* rewind_parameter{};
void* start_parameter{};
std::function<void()> entry_point;
std::function<void()> rewind_point;
std::shared_ptr<Fiber> previous_fiber;
bool is_thread_fiber{};
bool released{};
@ -34,13 +32,8 @@ struct Fiber::FiberImpl {
boost::context::detail::fcontext_t rewind_context{};
};
void Fiber::SetStartParameter(void* new_parameter) {
impl->start_parameter = new_parameter;
}
void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
void Fiber::SetRewindPoint(std::function<void()>&& rewind_func) {
impl->rewind_point = std::move(rewind_func);
impl->rewind_parameter = rewind_param;
}
void Fiber::Start(boost::context::detail::transfer_t& transfer) {
@ -48,7 +41,7 @@ void Fiber::Start(boost::context::detail::transfer_t& transfer) {
impl->previous_fiber->impl->context = transfer.fctx;
impl->previous_fiber->impl->guard.unlock();
impl->previous_fiber.reset();
impl->entry_point(impl->start_parameter);
impl->entry_point();
UNREACHABLE();
}
@ -59,7 +52,7 @@ 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;
impl->rewind_point(impl->rewind_parameter);
impl->rewind_point();
UNREACHABLE();
}
@ -73,10 +66,8 @@ void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
fiber->OnRewind(transfer);
}
Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter)
: impl{std::make_unique<FiberImpl>()} {
Fiber::Fiber(std::function<void()>&& entry_point_func) : 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;

View file

@ -29,7 +29,7 @@ namespace Common {
*/
class Fiber {
public:
Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter);
Fiber(std::function<void()>&& entry_point_func);
~Fiber();
Fiber(const Fiber&) = delete;
@ -43,16 +43,13 @@ public:
static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to);
[[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param);
void SetRewindPoint(std::function<void()>&& rewind_func);
void Rewind();
/// Only call from main thread's fiber
void Exit();
/// Changes the start parameter of the fiber. Has no effect if the fiber already started
void SetStartParameter(void* new_parameter);
private:
Fiber();

View file

@ -61,9 +61,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {};
ev_lost = CreateEvent("_lost_event", empty_timed_callback);
if (is_multicore) {
const auto hardware_concurrency = std::thread::hardware_concurrency();
size_t id = 0;
worker_threads.emplace_back(ThreadEntry, std::ref(*this), id++);
worker_threads.emplace_back(ThreadEntry, std::ref(*this), 0);
}
}

View file

@ -32,7 +32,6 @@ struct EventType {
TimedCallback callback;
/// A pointer to the name of the event.
const std::string name;
mutable std::mutex guard;
};
/**
@ -157,7 +156,6 @@ private:
std::condition_variable wait_pause_cv;
std::condition_variable wait_signal_cv;
mutable std::mutex event_mutex;
mutable std::mutex sequence_mutex;
std::atomic<bool> paused_state{};
bool is_paused{};

View file

@ -41,51 +41,32 @@ void CpuManager::Shutdown() {
}
}
std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() {
return GuestThreadFunction;
}
std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() {
return IdleThreadFunction;
}
std::function<void(void*)> CpuManager::GetShutdownThreadStartFunc() {
return ShutdownThreadFunction;
}
void CpuManager::GuestThreadFunction(void* cpu_manager_) {
CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_);
if (cpu_manager->is_multicore) {
cpu_manager->MultiCoreRunGuestThread();
void CpuManager::GuestThreadFunction() {
if (is_multicore) {
MultiCoreRunGuestThread();
} else {
cpu_manager->SingleCoreRunGuestThread();
SingleCoreRunGuestThread();
}
}
void CpuManager::GuestRewindFunction(void* cpu_manager_) {
CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_);
if (cpu_manager->is_multicore) {
cpu_manager->MultiCoreRunGuestLoop();
void CpuManager::GuestRewindFunction() {
if (is_multicore) {
MultiCoreRunGuestLoop();
} else {
cpu_manager->SingleCoreRunGuestLoop();
SingleCoreRunGuestLoop();
}
}
void CpuManager::IdleThreadFunction(void* cpu_manager_) {
CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_);
if (cpu_manager->is_multicore) {
cpu_manager->MultiCoreRunIdleThread();
void CpuManager::IdleThreadFunction() {
if (is_multicore) {
MultiCoreRunIdleThread();
} else {
cpu_manager->SingleCoreRunIdleThread();
SingleCoreRunIdleThread();
}
}
void CpuManager::ShutdownThreadFunction(void* cpu_manager) {
static_cast<CpuManager*>(cpu_manager)->ShutdownThread();
}
void* CpuManager::GetStartFuncParameter() {
return this;
void CpuManager::ShutdownThreadFunction() {
ShutdownThread();
}
///////////////////////////////////////////////////////////////////////////////
@ -97,7 +78,7 @@ void CpuManager::MultiCoreRunGuestThread() {
kernel.CurrentScheduler()->OnThreadStart();
auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread();
auto& host_context = thread->GetHostContext();
host_context->SetRewindPoint(GuestRewindFunction, this);
host_context->SetRewindPoint([this] { GuestRewindFunction(); });
MultiCoreRunGuestLoop();
}
@ -134,7 +115,7 @@ void CpuManager::SingleCoreRunGuestThread() {
kernel.CurrentScheduler()->OnThreadStart();
auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread();
auto& host_context = thread->GetHostContext();
host_context->SetRewindPoint(GuestRewindFunction, this);
host_context->SetRewindPoint([this] { GuestRewindFunction(); });
SingleCoreRunGuestLoop();
}

View file

@ -50,10 +50,15 @@ public:
void Initialize();
void Shutdown();
static std::function<void(void*)> GetGuestThreadStartFunc();
static std::function<void(void*)> GetIdleThreadStartFunc();
static std::function<void(void*)> GetShutdownThreadStartFunc();
void* GetStartFuncParameter();
std::function<void()> GetGuestThreadStartFunc() {
return [this] { GuestThreadFunction(); };
}
std::function<void()> GetIdleThreadStartFunc() {
return [this] { IdleThreadFunction(); };
}
std::function<void()> GetShutdownThreadStartFunc() {
return [this] { ShutdownThreadFunction(); };
}
void PreemptSingleCore(bool from_running_enviroment = true);
@ -62,10 +67,10 @@ public:
}
private:
static void GuestThreadFunction(void* cpu_manager);
static void GuestRewindFunction(void* cpu_manager);
static void IdleThreadFunction(void* cpu_manager);
static void ShutdownThreadFunction(void* cpu_manager);
void GuestThreadFunction();
void GuestRewindFunction();
void IdleThreadFunction();
void ShutdownThreadFunction();
void MultiCoreRunGuestThread();
void MultiCoreRunGuestLoop();

View file

@ -622,7 +622,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) {
}
KScheduler::KScheduler(Core::System& system_, s32 core_id_) : system{system_}, core_id{core_id_} {
switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this);
switch_fiber = std::make_shared<Common::Fiber>([this] { SwitchToCurrent(); });
state.needs_scheduling.store(true);
state.interrupt_task_thread_runnable = false;
state.should_count_idle = false;
@ -778,11 +778,6 @@ void KScheduler::ScheduleImpl() {
next_scheduler.SwitchContextStep2();
}
void KScheduler::OnSwitch(void* this_scheduler) {
KScheduler* sched = static_cast<KScheduler*>(this_scheduler);
sched->SwitchToCurrent();
}
void KScheduler::SwitchToCurrent() {
while (true) {
{

View file

@ -170,7 +170,6 @@ private:
*/
void UpdateLastContextSwitchTime(KThread* thread, KProcess* process);
static void OnSwitch(void* this_scheduler);
void SwitchToCurrent();
KThread* prev_thread{};

View file

@ -246,14 +246,12 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack
Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg,
VAddr user_stack_top, s32 prio, s32 core, KProcess* owner,
ThreadType type, std::function<void(void*)>&& init_func,
void* init_func_parameter) {
ThreadType type, std::function<void()>&& init_func) {
// Initialize the thread.
R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type));
// Initialize emulation parameters.
thread->host_context =
std::make_shared<Common::Fiber>(std::move(init_func), init_func_parameter);
thread->host_context = std::make_shared<Common::Fiber>(std::move(init_func));
thread->is_single_core = !Settings::values.use_multi_core.GetValue();
return ResultSuccess;
@ -265,15 +263,13 @@ Result KThread::InitializeDummyThread(KThread* thread) {
Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) {
return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main,
Core::CpuManager::GetIdleThreadStartFunc(),
system.GetCpuManager().GetStartFuncParameter());
system.GetCpuManager().GetIdleThreadStartFunc());
}
Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread,
KThreadFunction func, uintptr_t arg, s32 virt_core) {
return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority,
Core::CpuManager::GetShutdownThreadStartFunc(),
system.GetCpuManager().GetStartFuncParameter());
system.GetCpuManager().GetShutdownThreadStartFunc());
}
Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
@ -281,8 +277,7 @@ Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThr
KProcess* owner) {
system.Kernel().GlobalSchedulerContext().AddThread(thread);
return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner,
ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(),
system.GetCpuManager().GetStartFuncParameter());
ThreadType::User, system.GetCpuManager().GetGuestThreadStartFunc());
}
void KThread::PostDestroy(uintptr_t arg) {

View file

@ -729,8 +729,7 @@ private:
[[nodiscard]] static Result InitializeThread(KThread* thread, KThreadFunction func,
uintptr_t arg, VAddr user_stack_top, s32 prio,
s32 core, KProcess* owner, ThreadType type,
std::function<void(void*)>&& init_func,
void* init_func_parameter);
std::function<void()>&& init_func);
static void RestorePriority(KernelCore& kernel_ctx, KThread* thread);

View file

@ -43,7 +43,15 @@ class TestControl1 {
public:
TestControl1() = default;
void DoWork();
void DoWork() {
const u32 id = thread_ids.Get();
u32 value = items[id];
for (u32 i = 0; i < id; i++) {
value++;
}
results[id] = value;
Fiber::YieldTo(work_fibers[id], *thread_fibers[id]);
}
void ExecuteThread(u32 id);
@ -54,35 +62,16 @@ public:
std::vector<u32> results;
};
static void WorkControl1(void* control) {
auto* test_control = static_cast<TestControl1*>(control);
test_control->DoWork();
}
void TestControl1::DoWork() {
const u32 id = thread_ids.Get();
u32 value = items[id];
for (u32 i = 0; i < id; i++) {
value++;
}
results[id] = value;
Fiber::YieldTo(work_fibers[id], *thread_fibers[id]);
}
void TestControl1::ExecuteThread(u32 id) {
thread_ids.Register(id);
auto thread_fiber = Fiber::ThreadToFiber();
thread_fibers[id] = thread_fiber;
work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this);
work_fibers[id] = std::make_shared<Fiber>([this] { DoWork(); });
items[id] = rand() % 256;
Fiber::YieldTo(thread_fibers[id], *work_fibers[id]);
thread_fibers[id]->Exit();
}
static void ThreadStart1(u32 id, TestControl1& test_control) {
test_control.ExecuteThread(id);
}
/** This test checks for fiber setup configuration and validates that fibers are
* doing all the work required.
*/
@ -95,7 +84,7 @@ TEST_CASE("Fibers::Setup", "[common]") {
test_control.results.resize(num_threads, 0);
std::vector<std::thread> threads;
for (u32 i = 0; i < num_threads; i++) {
threads.emplace_back(ThreadStart1, i, std::ref(test_control));
threads.emplace_back([&test_control, i] { test_control.ExecuteThread(i); });
}
for (u32 i = 0; i < num_threads; i++) {
threads[i].join();
@ -167,21 +156,6 @@ public:
std::shared_ptr<Common::Fiber> fiber3;
};
static void WorkControl2_1(void* control) {
auto* test_control = static_cast<TestControl2*>(control);
test_control->DoWork1();
}
static void WorkControl2_2(void* control) {
auto* test_control = static_cast<TestControl2*>(control);
test_control->DoWork2();
}
static void WorkControl2_3(void* control) {
auto* test_control = static_cast<TestControl2*>(control);
test_control->DoWork3();
}
void TestControl2::ExecuteThread(u32 id) {
thread_ids.Register(id);
auto thread_fiber = Fiber::ThreadToFiber();
@ -193,18 +167,6 @@ void TestControl2::Exit() {
thread_fibers[id]->Exit();
}
static void ThreadStart2_1(u32 id, TestControl2& test_control) {
test_control.ExecuteThread(id);
test_control.CallFiber1();
test_control.Exit();
}
static void ThreadStart2_2(u32 id, TestControl2& test_control) {
test_control.ExecuteThread(id);
test_control.CallFiber2();
test_control.Exit();
}
/** This test checks for fiber thread exchange configuration and validates that fibers are
* that a fiber has been successfully transferred from one thread to another and that the TLS
* region of the thread is kept while changing fibers.
@ -212,14 +174,19 @@ static void ThreadStart2_2(u32 id, TestControl2& test_control) {
TEST_CASE("Fibers::InterExchange", "[common]") {
TestControl2 test_control{};
test_control.thread_fibers.resize(2);
test_control.fiber1 =
std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_1}, &test_control);
test_control.fiber2 =
std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_2}, &test_control);
test_control.fiber3 =
std::make_shared<Fiber>(std::function<void(void*)>{WorkControl2_3}, &test_control);
std::thread thread1(ThreadStart2_1, 0, std::ref(test_control));
std::thread thread2(ThreadStart2_2, 1, std::ref(test_control));
test_control.fiber1 = std::make_shared<Fiber>([&test_control] { test_control.DoWork1(); });
test_control.fiber2 = std::make_shared<Fiber>([&test_control] { test_control.DoWork2(); });
test_control.fiber3 = std::make_shared<Fiber>([&test_control] { test_control.DoWork3(); });
std::thread thread1{[&test_control] {
test_control.ExecuteThread(0);
test_control.CallFiber1();
test_control.Exit();
}};
std::thread thread2{[&test_control] {
test_control.ExecuteThread(1);
test_control.CallFiber2();
test_control.Exit();
}};
thread1.join();
thread2.join();
REQUIRE(test_control.assert1);
@ -270,16 +237,6 @@ public:
std::shared_ptr<Common::Fiber> fiber2;
};
static void WorkControl3_1(void* control) {
auto* test_control = static_cast<TestControl3*>(control);
test_control->DoWork1();
}
static void WorkControl3_2(void* control) {
auto* test_control = static_cast<TestControl3*>(control);
test_control->DoWork2();
}
void TestControl3::ExecuteThread(u32 id) {
thread_ids.Register(id);
auto thread_fiber = Fiber::ThreadToFiber();
@ -291,12 +248,6 @@ void TestControl3::Exit() {
thread_fibers[id]->Exit();
}
static void ThreadStart3(u32 id, TestControl3& test_control) {
test_control.ExecuteThread(id);
test_control.CallFiber1();
test_control.Exit();
}
/** This test checks for one two threads racing for starting the same fiber.
* It checks execution occurred in an ordered manner and by no time there were
* two contexts at the same time.
@ -304,12 +255,15 @@ static void ThreadStart3(u32 id, TestControl3& test_control) {
TEST_CASE("Fibers::StartRace", "[common]") {
TestControl3 test_control{};
test_control.thread_fibers.resize(2);
test_control.fiber1 =
std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_1}, &test_control);
test_control.fiber2 =
std::make_shared<Fiber>(std::function<void(void*)>{WorkControl3_2}, &test_control);
std::thread thread1(ThreadStart3, 0, std::ref(test_control));
std::thread thread2(ThreadStart3, 1, std::ref(test_control));
test_control.fiber1 = std::make_shared<Fiber>([&test_control] { test_control.DoWork1(); });
test_control.fiber2 = std::make_shared<Fiber>([&test_control] { test_control.DoWork2(); });
const auto race_function{[&test_control](u32 id) {
test_control.ExecuteThread(id);
test_control.CallFiber1();
test_control.Exit();
}};
std::thread thread1([&] { race_function(0); });
std::thread thread2([&] { race_function(1); });
thread1.join();
thread2.join();
REQUIRE(test_control.value1 == 1);
@ -319,12 +273,10 @@ TEST_CASE("Fibers::StartRace", "[common]") {
class TestControl4;
static void WorkControl4(void* control);
class TestControl4 {
public:
TestControl4() {
fiber1 = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl4}, this);
fiber1 = std::make_shared<Fiber>([this] { DoWork(); });
goal_reached = false;
rewinded = false;
}
@ -336,7 +288,7 @@ public:
}
void DoWork() {
fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this);
fiber1->SetRewindPoint([this] { DoWork(); });
if (rewinded) {
goal_reached = true;
Fiber::YieldTo(fiber1, *thread_fiber);
@ -351,11 +303,6 @@ public:
bool rewinded;
};
static void WorkControl4(void* control) {
auto* test_control = static_cast<TestControl4*>(control);
test_control->DoWork();
}
TEST_CASE("Fibers::Rewind", "[common]") {
TestControl4 test_control{};
test_control.Execute();