General: Add better safety for JIT use.
This commit is contained in:
		@@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Common {
 | 
			
		||||
@@ -164,6 +165,14 @@ public:
 | 
			
		||||
        std::string name;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void Lock() {
 | 
			
		||||
        guard.lock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Unlock() {
 | 
			
		||||
        guard.unlock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<BacktraceEntry> GetBacktrace() const;
 | 
			
		||||
 | 
			
		||||
    /// fp (= r29) points to the last frame record.
 | 
			
		||||
@@ -178,6 +187,7 @@ protected:
 | 
			
		||||
    /// System context that this ARM interface is running under.
 | 
			
		||||
    System& system;
 | 
			
		||||
    CPUInterruptHandler& interrupt_handler;
 | 
			
		||||
    std::mutex guard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Core
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,11 @@ void CpuManager::GuestThreadFunction(void* cpu_manager_) {
 | 
			
		||||
    cpu_manager->RunGuestThread();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CpuManager::GuestRewindFunction(void* cpu_manager_) {
 | 
			
		||||
    CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_);
 | 
			
		||||
    cpu_manager->RunGuestLoop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CpuManager::IdleThreadFunction(void* cpu_manager_) {
 | 
			
		||||
    CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_);
 | 
			
		||||
    cpu_manager->RunIdleThread();
 | 
			
		||||
@@ -78,14 +83,22 @@ void CpuManager::RunGuestThread() {
 | 
			
		||||
        auto& sched = kernel.CurrentScheduler();
 | 
			
		||||
        sched.OnThreadStart();
 | 
			
		||||
    }
 | 
			
		||||
    RunGuestLoop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CpuManager::RunGuestLoop() {
 | 
			
		||||
    auto& kernel = system.Kernel();
 | 
			
		||||
    auto* thread = kernel.CurrentScheduler().GetCurrentThread();
 | 
			
		||||
    auto host_context = thread->GetHostContext();
 | 
			
		||||
    host_context->SetRewindPoint(std::function<void(void*)>(GuestRewindFunction), this);
 | 
			
		||||
    host_context.reset();
 | 
			
		||||
    while (true) {
 | 
			
		||||
        auto* physical_core = &kernel.CurrentPhysicalCore();
 | 
			
		||||
        while (!physical_core->IsInterrupted()) {
 | 
			
		||||
            physical_core->Run();
 | 
			
		||||
            physical_core = &kernel.CurrentPhysicalCore();
 | 
			
		||||
        auto& physical_core = kernel.CurrentPhysicalCore();
 | 
			
		||||
        while (!physical_core.IsInterrupted()) {
 | 
			
		||||
            physical_core.Run();
 | 
			
		||||
        }
 | 
			
		||||
        physical_core->ClearExclusive();
 | 
			
		||||
        auto& scheduler = physical_core->Scheduler();
 | 
			
		||||
        physical_core.ClearExclusive();
 | 
			
		||||
        auto& scheduler = physical_core.Scheduler();
 | 
			
		||||
        scheduler.TryDoContextSwitch();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,10 +42,12 @@ public:
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static void GuestThreadFunction(void* cpu_manager);
 | 
			
		||||
    static void GuestRewindFunction(void* cpu_manager);
 | 
			
		||||
    static void IdleThreadFunction(void* cpu_manager);
 | 
			
		||||
    static void SuspendThreadFunction(void* cpu_manager);
 | 
			
		||||
 | 
			
		||||
    void RunGuestThread();
 | 
			
		||||
    void RunGuestLoop();
 | 
			
		||||
    void RunIdleThread();
 | 
			
		||||
    void RunSuspendThread();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -581,6 +581,7 @@ void Scheduler::SwitchContextStep2() {
 | 
			
		||||
 | 
			
		||||
    if (new_thread) {
 | 
			
		||||
        new_thread->context_guard.lock();
 | 
			
		||||
        cpu_core.Lock();
 | 
			
		||||
        ASSERT_MSG(new_thread->GetProcessorID() == s32(this->core_id),
 | 
			
		||||
                   "Thread must be assigned to this core.");
 | 
			
		||||
        ASSERT_MSG(new_thread->GetStatus() == ThreadStatus::Ready,
 | 
			
		||||
@@ -601,6 +602,7 @@ void Scheduler::SwitchContextStep2() {
 | 
			
		||||
            cpu_core.LoadContext(new_thread->GetContext64());
 | 
			
		||||
            cpu_core.SetTlsAddress(new_thread->GetTLSAddress());
 | 
			
		||||
            cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
 | 
			
		||||
            cpu_core.ClearExclusiveState();
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        current_thread = nullptr;
 | 
			
		||||
@@ -639,6 +641,7 @@ void Scheduler::SwitchContext() {
 | 
			
		||||
        }
 | 
			
		||||
        previous_thread->SetIsRunning(false);
 | 
			
		||||
        previous_thread->context_guard.unlock();
 | 
			
		||||
        cpu_core.Unlock();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<Common::Fiber> old_context;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include "common/alignment.h"
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/fiber.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "common/microprofile.h"
 | 
			
		||||
#include "common/string_util.h"
 | 
			
		||||
@@ -2468,7 +2469,10 @@ void Call(Core::System& system, u32 immediate) {
 | 
			
		||||
    }
 | 
			
		||||
    auto& physical_core_2 = system.CurrentPhysicalCore();
 | 
			
		||||
    if (physical_core.CoreIndex() != physical_core_2.CoreIndex()) {
 | 
			
		||||
        physical_core.Stop();
 | 
			
		||||
        LOG_CRITICAL(Kernel_SVC, "Rewinding");
 | 
			
		||||
        auto* thread = physical_core_2.Scheduler().GetCurrentThread();
 | 
			
		||||
        auto* host_context = thread->GetHostContext().get();
 | 
			
		||||
        host_context->Rewind();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user