summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-05-03 04:36:51 +0200
committerbunnei <bunneidev@gmail.com>2018-05-11 01:34:46 +0200
commita434fdcb102e96ddf564dc0973d7073d49bf19fc (patch)
treede758b0cc5ebcb67146397a74474fb898c0be51a /src/core/hle/kernel
parentcore: Create a thread for each CPU core, keep in lock-step with a barrier. (diff)
downloadyuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.gz
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.bz2
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.lz
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.xz
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.zst
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.zip
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/svc.cpp43
-rw-r--r--src/core/hle/kernel/svc_wrap.h24
-rw-r--r--src/core/hle/kernel/thread.cpp16
-rw-r--r--src/core/hle/kernel/thread.h4
-rw-r--r--src/core/hle/kernel/vm_manager.cpp23
5 files changed, 65 insertions, 45 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 72b5c05f2..520510b61 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -485,22 +485,28 @@ static void ExitProcess() {
Core::CurrentProcess()->status = ProcessStatus::Exited;
- // Stop all the process threads that are currently waiting for objects.
- auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
- for (auto& thread : thread_list) {
- if (thread->owner_process != Core::CurrentProcess())
- continue;
+ auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) {
+ for (auto& thread : thread_list) {
+ if (thread->owner_process != Core::CurrentProcess())
+ continue;
- if (thread == GetCurrentThread())
- continue;
+ if (thread == GetCurrentThread())
+ continue;
- // TODO(Subv): When are the other running/ready threads terminated?
- ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
- thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
- "Exiting processes with non-waiting threads is currently unimplemented");
+ // TODO(Subv): When are the other running/ready threads terminated?
+ ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
+ thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
+ "Exiting processes with non-waiting threads is currently unimplemented");
- thread->Stop();
- }
+ thread->Stop();
+ }
+ };
+
+ auto& system = Core::System::GetInstance();
+ stop_threads(system.Scheduler(0)->GetThreadList());
+ stop_threads(system.Scheduler(1)->GetThreadList());
+ stop_threads(system.Scheduler(2)->GetThreadList());
+ stop_threads(system.Scheduler(3)->GetThreadList());
// Kill the current thread
GetCurrentThread()->Stop();
@@ -530,14 +536,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
switch (processor_id) {
case THREADPROCESSORID_0:
- break;
case THREADPROCESSORID_1:
case THREADPROCESSORID_2:
case THREADPROCESSORID_3:
- // TODO(bunnei): Implement support for other processor IDs
- NGLOG_ERROR(Kernel_SVC,
- "Newly created thread must run in another thread ({}), unimplemented.",
- processor_id);
break;
default:
ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
@@ -576,7 +577,7 @@ static ResultCode StartThread(Handle thread_handle) {
/// Called when a thread exits
static void ExitThread() {
- NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CPU().GetPC());
+ NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CurrentArmInterface().GetPC());
ExitCurrentThread();
Core::System::GetInstance().PrepareReschedule();
@@ -588,7 +589,7 @@ static void SleepThread(s64 nanoseconds) {
// Don't attempt to yield execution if there are no available threads to run,
// this way we avoid a useless reschedule to the idle thread.
- if (nanoseconds == 0 && !Core::System::GetInstance().Scheduler().HaveReadyThreads())
+ if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads())
return;
// Sleep current thread and check for next thread to schedule
@@ -634,7 +635,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
condition_variable_addr, target);
u32 processed = 0;
- auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
+ auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList();
for (auto& thread : thread_list) {
if (thread->condvar_wait_address != condition_variable_addr)
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index c86ad3e04..40aa88cc1 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -13,14 +13,14 @@
namespace Kernel {
-#define PARAM(n) Core::CPU().GetReg(n)
+#define PARAM(n) Core::CurrentArmInterface().GetReg(n)
/**
* HLE a function return from the current ARM userland process
* @param res Result to return
*/
static inline void FuncReturn(u64 res) {
- Core::CPU().SetReg(0, res);
+ Core::CurrentArmInterface().SetReg(0, res);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -45,7 +45,7 @@ template <ResultCode func(u32*, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, (u32)PARAM(1)).raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -53,7 +53,7 @@ template <ResultCode func(u32*, u64)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(1)).raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -66,7 +66,7 @@ template <ResultCode func(u64*, u64)>
void SvcWrap() {
u64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1)).raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -85,8 +85,8 @@ void SvcWrap() {
u32 param_1 = 0;
u64 param_2 = 0;
ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2);
- Core::CPU().SetReg(1, param_1);
- Core::CPU().SetReg(2, param_2);
+ Core::CurrentArmInterface().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(2, param_2);
FuncReturn(retval.raw);
}
@@ -120,7 +120,7 @@ template <ResultCode func(u32*, u64, u64, s64)>
void SvcWrap() {
u32 param_1 = 0;
ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3));
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval.raw);
}
@@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)>
void SvcWrap() {
u64 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3)).raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -143,7 +143,7 @@ void SvcWrap() {
u32 retval =
func(&param_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))
.raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -166,7 +166,7 @@ template <ResultCode func(u32*, u64, u64, u32)>
void SvcWrap() {
u32 param_1 = 0;
u32 retval = func(&param_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
@@ -175,7 +175,7 @@ void SvcWrap() {
u32 param_1 = 0;
u32 retval =
func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
- Core::CPU().SetReg(1, param_1);
+ Core::CurrentArmInterface().SetReg(1, param_1);
FuncReturn(retval);
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1bd5d9ebf..0a5441684 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -64,7 +64,7 @@ void Thread::Stop() {
// Clean up thread from ready queue
// This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
if (status == THREADSTATUS_READY) {
- Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority);
+ scheduler->UnscheduleThread(this, current_priority);
}
status = THREADSTATUS_DEAD;
@@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() {
void ExitCurrentThread() {
Thread* thread = GetCurrentThread();
thread->Stop();
- Core::System::GetInstance().Scheduler().RemoveThread(thread);
+ Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
}
/**
@@ -188,7 +188,7 @@ void Thread::ResumeFromWait() {
wakeup_callback = nullptr;
status = THREADSTATUS_READY;
- Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority);
+ scheduler->ScheduleThread(this, current_priority);
Core::System::GetInstance().PrepareReschedule();
}
@@ -259,8 +259,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
SharedPtr<Thread> thread(new Thread);
- Core::System::GetInstance().Scheduler().AddThread(thread, priority);
-
thread->thread_id = NewThreadId();
thread->status = THREADSTATUS_DORMANT;
thread->entry_point = entry_point;
@@ -275,6 +273,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->name = std::move(name);
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
thread->owner_process = owner_process;
+ thread->scheduler = Core::System().GetInstance().Scheduler(static_cast<size_t>(processor_id));
+ thread->scheduler->AddThread(thread, priority);
// Find the next available TLS index, and mark it as used
auto& tls_slots = owner_process->tls_slots;
@@ -337,7 +337,7 @@ void Thread::SetPriority(u32 priority) {
}
void Thread::BoostPriority(u32 priority) {
- Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority);
+ scheduler->SetThreadPriority(this, priority);
current_priority = priority;
}
@@ -406,7 +406,7 @@ void Thread::UpdatePriority() {
if (new_priority == current_priority)
return;
- Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
+ scheduler->SetThreadPriority(this, new_priority);
current_priority = new_priority;
@@ -421,7 +421,7 @@ void Thread::UpdatePriority() {
* Gets the current thread
*/
Thread* GetCurrentThread() {
- return Core::System::GetInstance().Scheduler().GetCurrentThread();
+ return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
}
void ThreadingInit() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index e0a3c0934..0a3bb1183 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -4,6 +4,7 @@
#pragma once
+#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
@@ -56,6 +57,7 @@ enum class ThreadWakeupReason {
namespace Kernel {
class Process;
+class Scheduler;
class Thread final : public WaitObject {
public:
@@ -240,6 +242,8 @@ public:
// available. In case of a timeout, the object will be nullptr.
std::function<WakeupCallback> wakeup_callback;
+ std::shared_ptr<Scheduler> scheduler;
+
private:
Thread();
~Thread() override;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 2f0044c11..676e5b282 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -104,8 +104,15 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
- Core::CPU().MapBackingMemory(target, size, block->data() + offset,
- VMAPermission::ReadWriteExecute);
+ auto& system = Core::System::GetInstance();
+ system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset,
+ VMAPermission::ReadWriteExecute);
+ system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset,
+ VMAPermission::ReadWriteExecute);
+ system.ArmInterface(2).MapBackingMemory(target, size, block->data() + offset,
+ VMAPermission::ReadWriteExecute);
+ system.ArmInterface(3).MapBackingMemory(target, size, block->data() + offset,
+ VMAPermission::ReadWriteExecute);
final_vma.type = VMAType::AllocatedMemoryBlock;
final_vma.permissions = VMAPermission::ReadWrite;
@@ -126,7 +133,11 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
- Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
+ auto& system = Core::System::GetInstance();
+ system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
+ system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
+ system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
+ system.ArmInterface(3).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
final_vma.type = VMAType::BackingMemory;
final_vma.permissions = VMAPermission::ReadWrite;
@@ -184,7 +195,11 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
ASSERT(FindVMA(target)->second.size >= size);
- Core::CPU().UnmapMemory(target, size);
+ auto& system = Core::System::GetInstance();
+ system.ArmInterface(0).UnmapMemory(target, size);
+ system.ArmInterface(1).UnmapMemory(target, size);
+ system.ArmInterface(2).UnmapMemory(target, size);
+ system.ArmInterface(3).UnmapMemory(target, size);
return RESULT_SUCCESS;
}