mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +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,
 | 
			
		||||
                               void* user_data) {
 | 
			
		||||
    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,
 | 
			
		||||
               ctx.pc, ctx.cpu_registers[30]);
 | 
			
		||||
    return {};
 | 
			
		||||
 | 
			
		||||
@ -108,20 +108,26 @@ public:
 | 
			
		||||
 | 
			
		||||
    PerfStats::Results GetAndResetPerfStats();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets a reference to the emulated CPU.
 | 
			
		||||
     * @returns A reference to the emulated CPU.
 | 
			
		||||
     */
 | 
			
		||||
    ARM_Interface& CPU() {
 | 
			
		||||
        return CurrentCpuCore().CPU();
 | 
			
		||||
    ARM_Interface& CurrentArmInterface() {
 | 
			
		||||
        return CurrentCpuCore().ArmInterface();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ARM_Interface& ArmInterface(size_t core_index) {
 | 
			
		||||
        ASSERT(core_index < NUM_CPU_CORES);
 | 
			
		||||
        return cpu_cores[core_index]->ArmInterface();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Tegra::GPU& GPU() {
 | 
			
		||||
        return *gpu_core;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Kernel::Scheduler& Scheduler() {
 | 
			
		||||
        return CurrentCpuCore().Scheduler();
 | 
			
		||||
    Kernel::Scheduler& CurrentScheduler() {
 | 
			
		||||
        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() {
 | 
			
		||||
@ -198,8 +204,8 @@ private:
 | 
			
		||||
    std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline ARM_Interface& CPU() {
 | 
			
		||||
    return System::GetInstance().CPU();
 | 
			
		||||
inline ARM_Interface& CurrentArmInterface() {
 | 
			
		||||
    return System::GetInstance().CurrentArmInterface();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scheduler = std::make_unique<Kernel::Scheduler>(arm_interface.get());
 | 
			
		||||
    scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Cpu::RunLoop(bool tight_loop) {
 | 
			
		||||
 | 
			
		||||
@ -51,12 +51,16 @@ public:
 | 
			
		||||
 | 
			
		||||
    void PrepareReschedule();
 | 
			
		||||
 | 
			
		||||
    ARM_Interface& CPU() {
 | 
			
		||||
    ARM_Interface& ArmInterface() {
 | 
			
		||||
        return *arm_interface;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Kernel::Scheduler& Scheduler() {
 | 
			
		||||
        return *scheduler;
 | 
			
		||||
    const ARM_Interface& ArmInterface() const {
 | 
			
		||||
        return *arm_interface;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const std::shared_ptr<Kernel::Scheduler>& Scheduler() const {
 | 
			
		||||
        return scheduler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsMainCore() const {
 | 
			
		||||
@ -68,7 +72,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<ARM_Interface> arm_interface;
 | 
			
		||||
    std::shared_ptr<CpuBarrier> cpu_barrier;
 | 
			
		||||
    std::unique_ptr<Kernel::Scheduler> scheduler;
 | 
			
		||||
    std::shared_ptr<Kernel::Scheduler> scheduler;
 | 
			
		||||
 | 
			
		||||
    bool reschedule_pending{};
 | 
			
		||||
    size_t core_index;
 | 
			
		||||
 | 
			
		||||
@ -598,11 +598,11 @@ static void ReadRegister() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
        LongToGdbHex(reply, Core::CPU().GetPC());
 | 
			
		||||
        LongToGdbHex(reply, Core::CurrentArmInterface().GetPC());
 | 
			
		||||
    } else if (id == CPSR_REGISTER) {
 | 
			
		||||
        IntToGdbHex(reply, Core::CPU().GetCPSR());
 | 
			
		||||
        IntToGdbHex(reply, Core::CurrentArmInterface().GetCPSR());
 | 
			
		||||
    } else {
 | 
			
		||||
        return SendReply("E01");
 | 
			
		||||
    }
 | 
			
		||||
@ -618,16 +618,16 @@ static void ReadRegisters() {
 | 
			
		||||
    u8* bufptr = buffer;
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    LongToGdbHex(bufptr, Core::CPU().GetPC());
 | 
			
		||||
    LongToGdbHex(bufptr, Core::CurrentArmInterface().GetPC());
 | 
			
		||||
 | 
			
		||||
    bufptr += 16;
 | 
			
		||||
 | 
			
		||||
    IntToGdbHex(bufptr, Core::CPU().GetCPSR());
 | 
			
		||||
    IntToGdbHex(bufptr, Core::CurrentArmInterface().GetCPSR());
 | 
			
		||||
 | 
			
		||||
    bufptr += 8;
 | 
			
		||||
 | 
			
		||||
@ -646,11 +646,11 @@ static void WriteRegister() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (id <= SP_REGISTER) {
 | 
			
		||||
        Core::CPU().SetReg(id, GdbHexToLong(buffer_ptr));
 | 
			
		||||
        Core::CurrentArmInterface().SetReg(id, GdbHexToLong(buffer_ptr));
 | 
			
		||||
    } else if (id == PC_REGISTER) {
 | 
			
		||||
        Core::CPU().SetPC(GdbHexToLong(buffer_ptr));
 | 
			
		||||
        Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr));
 | 
			
		||||
    } else if (id == CPSR_REGISTER) {
 | 
			
		||||
        Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr));
 | 
			
		||||
        Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr));
 | 
			
		||||
    } else {
 | 
			
		||||
        return SendReply("E01");
 | 
			
		||||
    }
 | 
			
		||||
@ -667,11 +667,11 @@ static void WriteRegisters() {
 | 
			
		||||
 | 
			
		||||
    for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) {
 | 
			
		||||
        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) {
 | 
			
		||||
            Core::CPU().SetPC(GdbHexToLong(buffer_ptr + i * 16));
 | 
			
		||||
            Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr + i * 16));
 | 
			
		||||
        } else if (reg == CPSR_REGISTER) {
 | 
			
		||||
            Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr + i * 16));
 | 
			
		||||
            Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr + i * 16));
 | 
			
		||||
        } else {
 | 
			
		||||
            UNIMPLEMENTED();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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(¶m_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(¶m_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(¶m_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), ¶m_1, ¶m_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(¶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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)>
 | 
			
		||||
void SvcWrap() {
 | 
			
		||||
    u64 param_1 = 0;
 | 
			
		||||
    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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -143,7 +143,7 @@ void SvcWrap() {
 | 
			
		||||
    u32 retval =
 | 
			
		||||
        func(¶m_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(¶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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -175,7 +175,7 @@ void SvcWrap() {
 | 
			
		||||
    u32 param_1 = 0;
 | 
			
		||||
    u32 retval =
 | 
			
		||||
        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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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() {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -28,8 +28,13 @@ static PageTable* current_page_table = nullptr;
 | 
			
		||||
 | 
			
		||||
void SetCurrentPageTable(PageTable* 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)
 | 
			
		||||
        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();
 | 
			
		||||
}
 | 
			
		||||
@ -122,7 +122,7 @@ void RegistersWidget::CreateCPSRChildren() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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->child(0)->setText(
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ std::size_t WaitTreeItem::Row() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    item_list.reserve(threads.size());
 | 
			
		||||
    for (std::size_t i = 0; i < threads.size(); ++i) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user