mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2024-12-26 00:25:34 +00:00
core: Implement multicore support.
This commit is contained in:
parent
9776ff9179
commit
a434fdcb10
|
@ -52,7 +52,7 @@ static void InterruptHook(uc_engine* uc, u32 intNo, void* user_data) {
|
||||||
static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value,
|
static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value,
|
||||||
void* user_data) {
|
void* user_data) {
|
||||||
ARM_Interface::ThreadContext ctx{};
|
ARM_Interface::ThreadContext ctx{};
|
||||||
Core::CPU().SaveContext(ctx);
|
Core::CurrentArmInterface().SaveContext(ctx);
|
||||||
ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
|
ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
|
||||||
ctx.pc, ctx.cpu_registers[30]);
|
ctx.pc, ctx.cpu_registers[30]);
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -108,20 +108,26 @@ public:
|
||||||
|
|
||||||
PerfStats::Results GetAndResetPerfStats();
|
PerfStats::Results GetAndResetPerfStats();
|
||||||
|
|
||||||
/**
|
ARM_Interface& CurrentArmInterface() {
|
||||||
* Gets a reference to the emulated CPU.
|
return CurrentCpuCore().ArmInterface();
|
||||||
* @returns A reference to the emulated CPU.
|
}
|
||||||
*/
|
|
||||||
ARM_Interface& CPU() {
|
ARM_Interface& ArmInterface(size_t core_index) {
|
||||||
return CurrentCpuCore().CPU();
|
ASSERT(core_index < NUM_CPU_CORES);
|
||||||
|
return cpu_cores[core_index]->ArmInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tegra::GPU& GPU() {
|
Tegra::GPU& GPU() {
|
||||||
return *gpu_core;
|
return *gpu_core;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::Scheduler& Scheduler() {
|
Kernel::Scheduler& CurrentScheduler() {
|
||||||
return CurrentCpuCore().Scheduler();
|
return *CurrentCpuCore().Scheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index) {
|
||||||
|
ASSERT(core_index < NUM_CPU_CORES);
|
||||||
|
return cpu_cores[core_index]->Scheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
|
Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
|
||||||
|
@ -198,8 +204,8 @@ private:
|
||||||
std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu;
|
std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline ARM_Interface& CPU() {
|
inline ARM_Interface& CurrentArmInterface() {
|
||||||
return System::GetInstance().CPU();
|
return System::GetInstance().CurrentArmInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TelemetrySession& Telemetry() {
|
inline TelemetrySession& Telemetry() {
|
||||||
|
|
|
@ -33,7 +33,7 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
|
||||||
arm_interface = std::make_shared<ARM_Unicorn>();
|
arm_interface = std::make_shared<ARM_Unicorn>();
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler = std::make_unique<Kernel::Scheduler>(arm_interface.get());
|
scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::RunLoop(bool tight_loop) {
|
void Cpu::RunLoop(bool tight_loop) {
|
||||||
|
|
|
@ -51,12 +51,16 @@ public:
|
||||||
|
|
||||||
void PrepareReschedule();
|
void PrepareReschedule();
|
||||||
|
|
||||||
ARM_Interface& CPU() {
|
ARM_Interface& ArmInterface() {
|
||||||
return *arm_interface;
|
return *arm_interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::Scheduler& Scheduler() {
|
const ARM_Interface& ArmInterface() const {
|
||||||
return *scheduler;
|
return *arm_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Kernel::Scheduler>& Scheduler() const {
|
||||||
|
return scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsMainCore() const {
|
bool IsMainCore() const {
|
||||||
|
@ -68,7 +72,7 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<ARM_Interface> arm_interface;
|
std::shared_ptr<ARM_Interface> arm_interface;
|
||||||
std::shared_ptr<CpuBarrier> cpu_barrier;
|
std::shared_ptr<CpuBarrier> cpu_barrier;
|
||||||
std::unique_ptr<Kernel::Scheduler> scheduler;
|
std::shared_ptr<Kernel::Scheduler> scheduler;
|
||||||
|
|
||||||
bool reschedule_pending{};
|
bool reschedule_pending{};
|
||||||
size_t core_index;
|
size_t core_index;
|
||||||
|
|
|
@ -598,11 +598,11 @@ static void ReadRegister() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id <= SP_REGISTER) {
|
if (id <= SP_REGISTER) {
|
||||||
LongToGdbHex(reply, Core::CPU().GetReg(static_cast<int>(id)));
|
LongToGdbHex(reply, Core::CurrentArmInterface().GetReg(static_cast<int>(id)));
|
||||||
} else if (id == PC_REGISTER) {
|
} else if (id == PC_REGISTER) {
|
||||||
LongToGdbHex(reply, Core::CPU().GetPC());
|
LongToGdbHex(reply, Core::CurrentArmInterface().GetPC());
|
||||||
} else if (id == CPSR_REGISTER) {
|
} else if (id == CPSR_REGISTER) {
|
||||||
IntToGdbHex(reply, Core::CPU().GetCPSR());
|
IntToGdbHex(reply, Core::CurrentArmInterface().GetCPSR());
|
||||||
} else {
|
} else {
|
||||||
return SendReply("E01");
|
return SendReply("E01");
|
||||||
}
|
}
|
||||||
|
@ -618,16 +618,16 @@ static void ReadRegisters() {
|
||||||
u8* bufptr = buffer;
|
u8* bufptr = buffer;
|
||||||
|
|
||||||
for (int reg = 0; reg <= SP_REGISTER; reg++) {
|
for (int reg = 0; reg <= SP_REGISTER; reg++) {
|
||||||
LongToGdbHex(bufptr + reg * 16, Core::CPU().GetReg(reg));
|
LongToGdbHex(bufptr + reg * 16, Core::CurrentArmInterface().GetReg(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
bufptr += (32 * 16);
|
bufptr += (32 * 16);
|
||||||
|
|
||||||
LongToGdbHex(bufptr, Core::CPU().GetPC());
|
LongToGdbHex(bufptr, Core::CurrentArmInterface().GetPC());
|
||||||
|
|
||||||
bufptr += 16;
|
bufptr += 16;
|
||||||
|
|
||||||
IntToGdbHex(bufptr, Core::CPU().GetCPSR());
|
IntToGdbHex(bufptr, Core::CurrentArmInterface().GetCPSR());
|
||||||
|
|
||||||
bufptr += 8;
|
bufptr += 8;
|
||||||
|
|
||||||
|
@ -646,11 +646,11 @@ static void WriteRegister() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id <= SP_REGISTER) {
|
if (id <= SP_REGISTER) {
|
||||||
Core::CPU().SetReg(id, GdbHexToLong(buffer_ptr));
|
Core::CurrentArmInterface().SetReg(id, GdbHexToLong(buffer_ptr));
|
||||||
} else if (id == PC_REGISTER) {
|
} else if (id == PC_REGISTER) {
|
||||||
Core::CPU().SetPC(GdbHexToLong(buffer_ptr));
|
Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr));
|
||||||
} else if (id == CPSR_REGISTER) {
|
} else if (id == CPSR_REGISTER) {
|
||||||
Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr));
|
Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr));
|
||||||
} else {
|
} else {
|
||||||
return SendReply("E01");
|
return SendReply("E01");
|
||||||
}
|
}
|
||||||
|
@ -667,11 +667,11 @@ static void WriteRegisters() {
|
||||||
|
|
||||||
for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) {
|
for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) {
|
||||||
if (reg <= SP_REGISTER) {
|
if (reg <= SP_REGISTER) {
|
||||||
Core::CPU().SetReg(reg, GdbHexToLong(buffer_ptr + i * 16));
|
Core::CurrentArmInterface().SetReg(reg, GdbHexToLong(buffer_ptr + i * 16));
|
||||||
} else if (reg == PC_REGISTER) {
|
} else if (reg == PC_REGISTER) {
|
||||||
Core::CPU().SetPC(GdbHexToLong(buffer_ptr + i * 16));
|
Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr + i * 16));
|
||||||
} else if (reg == CPSR_REGISTER) {
|
} else if (reg == CPSR_REGISTER) {
|
||||||
Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr + i * 16));
|
Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr + i * 16));
|
||||||
} else {
|
} else {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,22 +485,28 @@ static void ExitProcess() {
|
||||||
|
|
||||||
Core::CurrentProcess()->status = ProcessStatus::Exited;
|
Core::CurrentProcess()->status = ProcessStatus::Exited;
|
||||||
|
|
||||||
// Stop all the process threads that are currently waiting for objects.
|
auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) {
|
||||||
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
|
for (auto& thread : thread_list) {
|
||||||
for (auto& thread : thread_list) {
|
if (thread->owner_process != Core::CurrentProcess())
|
||||||
if (thread->owner_process != Core::CurrentProcess())
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (thread == GetCurrentThread())
|
if (thread == GetCurrentThread())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO(Subv): When are the other running/ready threads terminated?
|
// TODO(Subv): When are the other running/ready threads terminated?
|
||||||
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
|
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
|
||||||
thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
|
thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
|
||||||
"Exiting processes with non-waiting threads is currently unimplemented");
|
"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
|
// Kill the current thread
|
||||||
GetCurrentThread()->Stop();
|
GetCurrentThread()->Stop();
|
||||||
|
@ -530,14 +536,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
|
||||||
|
|
||||||
switch (processor_id) {
|
switch (processor_id) {
|
||||||
case THREADPROCESSORID_0:
|
case THREADPROCESSORID_0:
|
||||||
break;
|
|
||||||
case THREADPROCESSORID_1:
|
case THREADPROCESSORID_1:
|
||||||
case THREADPROCESSORID_2:
|
case THREADPROCESSORID_2:
|
||||||
case THREADPROCESSORID_3:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
|
ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
|
||||||
|
@ -576,7 +577,7 @@ static ResultCode StartThread(Handle thread_handle) {
|
||||||
|
|
||||||
/// Called when a thread exits
|
/// Called when a thread exits
|
||||||
static void ExitThread() {
|
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();
|
ExitCurrentThread();
|
||||||
Core::System::GetInstance().PrepareReschedule();
|
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,
|
// 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.
|
// 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;
|
return;
|
||||||
|
|
||||||
// Sleep current thread and check for next thread to schedule
|
// 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);
|
condition_variable_addr, target);
|
||||||
|
|
||||||
u32 processed = 0;
|
u32 processed = 0;
|
||||||
auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
|
auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList();
|
||||||
|
|
||||||
for (auto& thread : thread_list) {
|
for (auto& thread : thread_list) {
|
||||||
if (thread->condvar_wait_address != condition_variable_addr)
|
if (thread->condvar_wait_address != condition_variable_addr)
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
|
|
||||||
namespace Kernel {
|
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
|
* HLE a function return from the current ARM userland process
|
||||||
* @param res Result to return
|
* @param res Result to return
|
||||||
*/
|
*/
|
||||||
static inline void FuncReturn(u64 res) {
|
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() {
|
void SvcWrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, (u32)PARAM(1)).raw;
|
u32 retval = func(¶m_1, (u32)PARAM(1)).raw;
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ template <ResultCode func(u32*, u64)>
|
||||||
void SvcWrap() {
|
void SvcWrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1)).raw;
|
u32 retval = func(¶m_1, PARAM(1)).raw;
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ template <ResultCode func(u64*, u64)>
|
||||||
void SvcWrap() {
|
void SvcWrap() {
|
||||||
u64 param_1 = 0;
|
u64 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1)).raw;
|
u32 retval = func(¶m_1, PARAM(1)).raw;
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +85,8 @@ void SvcWrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u64 param_2 = 0;
|
u64 param_2 = 0;
|
||||||
ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), ¶m_1, ¶m_2);
|
ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), ¶m_1, ¶m_2);
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
Core::CPU().SetReg(2, param_2);
|
Core::CurrentArmInterface().SetReg(2, param_2);
|
||||||
FuncReturn(retval.raw);
|
FuncReturn(retval.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ template <ResultCode func(u32*, u64, u64, s64)>
|
||||||
void SvcWrap() {
|
void SvcWrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
ResultCode retval = func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3));
|
ResultCode retval = func(¶m_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);
|
FuncReturn(retval.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)>
|
||||||
void SvcWrap() {
|
void SvcWrap() {
|
||||||
u64 param_1 = 0;
|
u64 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3)).raw;
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ void SvcWrap() {
|
||||||
u32 retval =
|
u32 retval =
|
||||||
func(¶m_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))
|
func(¶m_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))
|
||||||
.raw;
|
.raw;
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ template <ResultCode func(u32*, u64, u64, u32)>
|
||||||
void SvcWrap() {
|
void SvcWrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval = func(¶m_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
|
u32 retval = func(¶m_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
|
||||||
Core::CPU().SetReg(1, param_1);
|
Core::CurrentArmInterface().SetReg(1, param_1);
|
||||||
FuncReturn(retval);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ void SvcWrap() {
|
||||||
u32 param_1 = 0;
|
u32 param_1 = 0;
|
||||||
u32 retval =
|
u32 retval =
|
||||||
func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
|
func(¶m_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);
|
FuncReturn(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ void Thread::Stop() {
|
||||||
// Clean up thread from ready queue
|
// Clean up thread from ready queue
|
||||||
// This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
|
// This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
|
||||||
if (status == THREADSTATUS_READY) {
|
if (status == THREADSTATUS_READY) {
|
||||||
Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority);
|
scheduler->UnscheduleThread(this, current_priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = THREADSTATUS_DEAD;
|
status = THREADSTATUS_DEAD;
|
||||||
|
@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() {
|
||||||
void ExitCurrentThread() {
|
void ExitCurrentThread() {
|
||||||
Thread* thread = GetCurrentThread();
|
Thread* thread = GetCurrentThread();
|
||||||
thread->Stop();
|
thread->Stop();
|
||||||
Core::System::GetInstance().Scheduler().RemoveThread(thread);
|
Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,7 +188,7 @@ void Thread::ResumeFromWait() {
|
||||||
wakeup_callback = nullptr;
|
wakeup_callback = nullptr;
|
||||||
|
|
||||||
status = THREADSTATUS_READY;
|
status = THREADSTATUS_READY;
|
||||||
Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority);
|
scheduler->ScheduleThread(this, current_priority);
|
||||||
Core::System::GetInstance().PrepareReschedule();
|
Core::System::GetInstance().PrepareReschedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,8 +259,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
|
||||||
|
|
||||||
SharedPtr<Thread> thread(new Thread);
|
SharedPtr<Thread> thread(new Thread);
|
||||||
|
|
||||||
Core::System::GetInstance().Scheduler().AddThread(thread, priority);
|
|
||||||
|
|
||||||
thread->thread_id = NewThreadId();
|
thread->thread_id = NewThreadId();
|
||||||
thread->status = THREADSTATUS_DORMANT;
|
thread->status = THREADSTATUS_DORMANT;
|
||||||
thread->entry_point = entry_point;
|
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->name = std::move(name);
|
||||||
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
|
thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
|
||||||
thread->owner_process = owner_process;
|
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
|
// Find the next available TLS index, and mark it as used
|
||||||
auto& tls_slots = owner_process->tls_slots;
|
auto& tls_slots = owner_process->tls_slots;
|
||||||
|
@ -337,7 +337,7 @@ void Thread::SetPriority(u32 priority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::BoostPriority(u32 priority) {
|
void Thread::BoostPriority(u32 priority) {
|
||||||
Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority);
|
scheduler->SetThreadPriority(this, priority);
|
||||||
current_priority = priority;
|
current_priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ void Thread::UpdatePriority() {
|
||||||
if (new_priority == current_priority)
|
if (new_priority == current_priority)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
|
scheduler->SetThreadPriority(this, new_priority);
|
||||||
|
|
||||||
current_priority = new_priority;
|
current_priority = new_priority;
|
||||||
|
|
||||||
|
@ -421,7 +421,7 @@ void Thread::UpdatePriority() {
|
||||||
* Gets the current thread
|
* Gets the current thread
|
||||||
*/
|
*/
|
||||||
Thread* GetCurrentThread() {
|
Thread* GetCurrentThread() {
|
||||||
return Core::System::GetInstance().Scheduler().GetCurrentThread();
|
return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadingInit() {
|
void ThreadingInit() {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -56,6 +57,7 @@ enum class ThreadWakeupReason {
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class Process;
|
class Process;
|
||||||
|
class Scheduler;
|
||||||
|
|
||||||
class Thread final : public WaitObject {
|
class Thread final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
|
@ -240,6 +242,8 @@ public:
|
||||||
// available. In case of a timeout, the object will be nullptr.
|
// available. In case of a timeout, the object will be nullptr.
|
||||||
std::function<WakeupCallback> wakeup_callback;
|
std::function<WakeupCallback> wakeup_callback;
|
||||||
|
|
||||||
|
std::shared_ptr<Scheduler> scheduler;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Thread();
|
Thread();
|
||||||
~Thread() override;
|
~Thread() override;
|
||||||
|
|
|
@ -104,8 +104,15 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
|
||||||
VirtualMemoryArea& final_vma = vma_handle->second;
|
VirtualMemoryArea& final_vma = vma_handle->second;
|
||||||
ASSERT(final_vma.size == size);
|
ASSERT(final_vma.size == size);
|
||||||
|
|
||||||
Core::CPU().MapBackingMemory(target, size, block->data() + offset,
|
auto& system = Core::System::GetInstance();
|
||||||
VMAPermission::ReadWriteExecute);
|
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.type = VMAType::AllocatedMemoryBlock;
|
||||||
final_vma.permissions = VMAPermission::ReadWrite;
|
final_vma.permissions = VMAPermission::ReadWrite;
|
||||||
|
@ -126,7 +133,11 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
|
||||||
VirtualMemoryArea& final_vma = vma_handle->second;
|
VirtualMemoryArea& final_vma = vma_handle->second;
|
||||||
ASSERT(final_vma.size == size);
|
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.type = VMAType::BackingMemory;
|
||||||
final_vma.permissions = VMAPermission::ReadWrite;
|
final_vma.permissions = VMAPermission::ReadWrite;
|
||||||
|
@ -184,7 +195,11 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
|
||||||
|
|
||||||
ASSERT(FindVMA(target)->second.size >= 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;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,13 @@ static PageTable* current_page_table = nullptr;
|
||||||
|
|
||||||
void SetCurrentPageTable(PageTable* page_table) {
|
void SetCurrentPageTable(PageTable* page_table) {
|
||||||
current_page_table = page_table;
|
current_page_table = page_table;
|
||||||
if (Core::System::GetInstance().IsPoweredOn()) {
|
|
||||||
Core::CPU().PageTableChanged();
|
auto& system = Core::System::GetInstance();
|
||||||
|
if (system.IsPoweredOn()) {
|
||||||
|
system.ArmInterface(0).PageTableChanged();
|
||||||
|
system.ArmInterface(1).PageTableChanged();
|
||||||
|
system.ArmInterface(2).PageTableChanged();
|
||||||
|
system.ArmInterface(3).PageTableChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ void RegistersWidget::OnDebugModeEntered() {
|
||||||
|
|
||||||
for (int i = 0; i < core_registers->childCount(); ++i)
|
for (int i = 0; i < core_registers->childCount(); ++i)
|
||||||
core_registers->child(i)->setText(
|
core_registers->child(i)->setText(
|
||||||
1, QString("0x%1").arg(Core::CPU().GetReg(i), 8, 16, QLatin1Char('0')));
|
1, QString("0x%1").arg(Core::CurrentArmInterface().GetReg(i), 8, 16, QLatin1Char('0')));
|
||||||
|
|
||||||
UpdateCPSRValues();
|
UpdateCPSRValues();
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ void RegistersWidget::CreateCPSRChildren() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegistersWidget::UpdateCPSRValues() {
|
void RegistersWidget::UpdateCPSRValues() {
|
||||||
const u32 cpsr_val = Core::CPU().GetCPSR();
|
const u32 cpsr_val = Core::CurrentArmInterface().GetCPSR();
|
||||||
|
|
||||||
cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
||||||
cpsr->child(0)->setText(
|
cpsr->child(0)->setText(
|
||||||
|
|
|
@ -51,7 +51,7 @@ std::size_t WaitTreeItem::Row() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
|
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
|
||||||
const auto& threads = Core::System::GetInstance().Scheduler().GetThreadList();
|
const auto& threads = Core::System::GetInstance().Scheduler(0)->GetThreadList();
|
||||||
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
|
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
|
||||||
item_list.reserve(threads.size());
|
item_list.reserve(threads.size());
|
||||||
for (std::size_t i = 0; i < threads.size(); ++i) {
|
for (std::size_t i = 0; i < threads.size(); ++i) {
|
||||||
|
|
Loading…
Reference in a new issue