General: Add better safety for JIT use.

master
Fernando Sahmkow 2020-02-27 19:12:41 +07:00
parent bd36eaf15d
commit 04e0f8776c
5 changed files with 39 additions and 7 deletions

@ -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();
}
}