summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-01-21 22:00:16 +0100
committerbunnei <bunneidev@gmail.com>2021-01-29 06:42:26 +0100
commit6e953f7f0294d945ba9d6f08350d5dccb0d76075 (patch)
tree92a498827c4de7dd372731eff83c66aa3f57f060
parenthle: kernel: k_scheduler: Use atomics for current_thread, etc. (diff)
downloadyuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.tar
yuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.tar.gz
yuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.tar.bz2
yuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.tar.lz
yuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.tar.xz
yuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.tar.zst
yuzu-6e953f7f0294d945ba9d6f08350d5dccb0d76075.zip
-rw-r--r--src/core/hle/kernel/k_light_lock.cpp12
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp6
-rw-r--r--src/core/hle/kernel/k_scheduler.h4
-rw-r--r--src/core/hle/kernel/k_scheduler_lock.h27
-rw-r--r--src/core/hle/kernel/k_thread.cpp6
-rw-r--r--src/core/hle/kernel/kernel.cpp27
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/yuzu/main.cpp2
8 files changed, 45 insertions, 43 deletions
diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp
index 1d54ba5df..08fa65fd5 100644
--- a/src/core/hle/kernel/k_light_lock.cpp
+++ b/src/core/hle/kernel/k_light_lock.cpp
@@ -9,12 +9,6 @@
namespace Kernel {
-static KThread* ToThread(uintptr_t thread_) {
- ASSERT((thread_ & EmuThreadHandleReserved) == 0);
- ASSERT((thread_ & 1) == 0);
- return reinterpret_cast<KThread*>(thread_);
-}
-
void KLightLock::Lock() {
const uintptr_t cur_thread = reinterpret_cast<uintptr_t>(GetCurrentThreadPointer(kernel));
const uintptr_t cur_thread_tag = (cur_thread | 1);
@@ -48,7 +42,7 @@ void KLightLock::Unlock() {
}
void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {
- KThread* cur_thread = ToThread(_cur_thread);
+ KThread* cur_thread = reinterpret_cast<KThread*>(_cur_thread);
// Pend the current thread waiting on the owner thread.
{
@@ -60,7 +54,7 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {
}
// Add the current thread as a waiter on the owner.
- KThread* owner_thread = ToThread(_owner & ~1ul);
+ KThread* owner_thread = reinterpret_cast<KThread*>(_owner & ~1ul);
cur_thread->SetAddressKey(reinterpret_cast<uintptr_t>(std::addressof(tag)));
owner_thread->AddWaiter(cur_thread);
@@ -88,7 +82,7 @@ void KLightLock::LockSlowPath(uintptr_t _owner, uintptr_t _cur_thread) {
}
void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) {
- KThread* owner_thread = ToThread(_cur_thread);
+ KThread* owner_thread = reinterpret_cast<KThread*>(_cur_thread);
// Unlock.
{
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index fbdc061df..bb5f43b53 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -623,7 +623,7 @@ KThread* KScheduler::GetCurrentThread() const {
if (auto result = current_thread.load(); result) {
return result;
}
- return idle_thread.get();
+ return idle_thread;
}
u64 KScheduler::GetLastContextSwitchTicks() const {
@@ -708,7 +708,7 @@ void KScheduler::ScheduleImpl() {
// We never want to schedule a null thread, so use the idle thread if we don't have a next.
if (next_thread == nullptr) {
- next_thread = idle_thread.get();
+ next_thread = idle_thread;
}
// If we're not actually switching thread, there's nothing to do.
@@ -803,7 +803,7 @@ void KScheduler::Initialize() {
auto thread_res = KThread::Create(system, ThreadType::Main, name, 0,
KThread::IdleThreadPriority, 0, static_cast<u32>(core_id), 0,
nullptr, std::move(init_func), init_func_parameter);
- idle_thread = thread_res.Unwrap();
+ idle_thread = thread_res.Unwrap().get();
}
KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel)
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index e0d052593..f595b9a5c 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -54,7 +54,7 @@ public:
/// Returns true if the scheduler is idle
[[nodiscard]] bool IsIdle() const {
- return GetCurrentThread() == idle_thread.get();
+ return GetCurrentThread() == idle_thread;
}
/// Gets the timestamp for the last context switch in ticks.
@@ -176,7 +176,7 @@ private:
KThread* prev_thread{};
std::atomic<KThread*> current_thread{};
- std::shared_ptr<KThread> idle_thread;
+ KThread* idle_thread;
std::shared_ptr<Common::Fiber> switch_fiber{};
diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h
index 5d48dcf38..3b38f8f3e 100644
--- a/src/core/hle/kernel/k_scheduler_lock.h
+++ b/src/core/hle/kernel/k_scheduler_lock.h
@@ -10,6 +10,7 @@
#include "common/assert.h"
#include "common/spin_lock.h"
#include "core/hardware_properties.h"
+#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel {
@@ -22,42 +23,42 @@ public:
explicit KAbstractSchedulerLock(KernelCore& kernel_) : kernel{kernel_} {}
bool IsLockedByCurrentThread() const {
- return this->owner_thread == kernel.GetCurrentEmuThreadID();
+ return this->owner_thread == GetCurrentThreadPointer(kernel);
}
void Lock() {
if (this->IsLockedByCurrentThread()) {
// If we already own the lock, we can just increment the count.
- ASSERT(this->lock_count > 0);
- this->lock_count++;
+ ASSERT(lock_count > 0);
+ lock_count++;
} else {
// Otherwise, we want to disable scheduling and acquire the spinlock.
SchedulerType::DisableScheduling(kernel);
- this->spin_lock.lock();
+ spin_lock.lock();
// For debug, ensure that our state is valid.
- ASSERT(this->lock_count == 0);
- ASSERT(this->owner_thread == EmuThreadHandleInvalid);
+ ASSERT(lock_count == 0);
+ ASSERT(owner_thread == nullptr);
// Increment count, take ownership.
- this->lock_count = 1;
- this->owner_thread = kernel.GetCurrentEmuThreadID();
+ lock_count = 1;
+ owner_thread = GetCurrentThreadPointer(kernel);
}
}
void Unlock() {
ASSERT(this->IsLockedByCurrentThread());
- ASSERT(this->lock_count > 0);
+ ASSERT(lock_count > 0);
// Release an instance of the lock.
- if ((--this->lock_count) == 0) {
+ if ((--lock_count) == 0) {
// We're no longer going to hold the lock. Take note of what cores need scheduling.
const u64 cores_needing_scheduling =
SchedulerType::UpdateHighestPriorityThreads(kernel);
// Note that we no longer hold the lock, and unlock the spinlock.
- this->owner_thread = EmuThreadHandleInvalid;
- this->spin_lock.unlock();
+ owner_thread = nullptr;
+ spin_lock.unlock();
// Enable scheduling, and perform a rescheduling operation.
SchedulerType::EnableScheduling(kernel, cores_needing_scheduling);
@@ -68,7 +69,7 @@ private:
KernelCore& kernel;
Common::SpinLock spin_lock{};
s32 lock_count{};
- EmuThreadHandle owner_thread{EmuThreadHandleInvalid};
+ KThread* owner_thread{};
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 62ce2fbd5..f57e98047 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -1034,11 +1034,7 @@ ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, Thread
}
KThread* GetCurrentThreadPointer(KernelCore& kernel) {
- if (!kernel.CurrentScheduler()) {
- // We are not called from a core thread
- return {};
- }
- return kernel.CurrentScheduler()->GetCurrentThread();
+ return kernel.GetCurrentEmuThread();
}
KThread& GetCurrentThread(KernelCore& kernel) {
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 6142496b6..093886b7c 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -57,9 +57,10 @@ struct KernelCore::Impl {
}
void Initialize(KernelCore& kernel) {
+ global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
+
RegisterHostThread();
- global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
service_thread_manager =
std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager");
is_phantom_mode_for_singlecore = false;
@@ -206,6 +207,18 @@ struct KernelCore::Impl {
return host_thread_id;
}
+ // Gets the dummy KThread for the caller, allocating a new one if this is the first time
+ KThread* GetHostDummyThread() {
+ const thread_local auto thread =
+ KThread::Create(
+ system, ThreadType::Main,
+ std::string{"DummyThread:" + GetHostThreadId()}, 0, KThread::DefaultThreadPriority,
+ 0, static_cast<u32>(3), 0, nullptr,
+ []([[maybe_unused]] void* arg) { UNREACHABLE(); }, nullptr)
+ .Unwrap();
+ return thread.get();
+ }
+
/// Registers a CPU core thread by allocating a host thread ID for it
void RegisterCoreThread(std::size_t core_id) {
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
@@ -218,6 +231,7 @@ struct KernelCore::Impl {
/// Registers a new host thread by allocating a host thread ID for it
void RegisterHostThread() {
[[maybe_unused]] const auto this_id = GetHostThreadId();
+ [[maybe_unused]] const auto dummy_thread = GetHostDummyThread();
}
[[nodiscard]] u32 GetCurrentHostThreadID() {
@@ -237,13 +251,12 @@ struct KernelCore::Impl {
is_phantom_mode_for_singlecore = value;
}
- [[nodiscard]] EmuThreadHandle GetCurrentEmuThreadID() {
+ KThread* GetCurrentEmuThread() {
const auto thread_id = GetCurrentHostThreadID();
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
- // Reserved value for HLE threads
- return EmuThreadHandleReserved + (static_cast<u64>(thread_id) << 1);
+ return GetHostDummyThread();
}
- return reinterpret_cast<uintptr_t>(schedulers[thread_id].get());
+ return schedulers[thread_id]->GetCurrentThread();
}
void InitializeMemoryLayout() {
@@ -548,8 +561,8 @@ u32 KernelCore::GetCurrentHostThreadID() const {
return impl->GetCurrentHostThreadID();
}
-EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
- return impl->GetCurrentEmuThreadID();
+KThread* KernelCore::GetCurrentEmuThread() const {
+ return impl->GetCurrentEmuThread();
}
Memory::MemoryManager& KernelCore::MemoryManager() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index b92c017f6..e7c77727b 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -165,8 +165,8 @@ public:
/// Determines whether or not the given port is a valid named port.
bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
- /// Gets the current host_thread/guest_thread handle.
- EmuThreadHandle GetCurrentEmuThreadID() const;
+ /// Gets the current host_thread/guest_thread pointer.
+ KThread* GetCurrentEmuThread() const;
/// Gets the current host_thread handle.
u32 GetCurrentHostThreadID() const;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e76141125..886e6e9d2 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1039,8 +1039,6 @@ bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) {
std::make_unique<QtWebBrowser>(*this), // Web Browser
});
- system.RegisterHostThread();
-
const Core::System::ResultStatus result{
system.Load(*render_window, filename.toStdString(), program_index)};