summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_thread.cpp')
-rw-r--r--src/core/hle/kernel/k_thread.cpp44
1 files changed, 41 insertions, 3 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index b8c993748..71e029a3f 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <atomic>
#include <cinttypes>
#include <optional>
#include <vector>
@@ -33,6 +34,7 @@
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/result.h"
+#include "core/memory.h"
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic_32.h"
@@ -63,6 +65,13 @@ namespace Kernel {
namespace {
+struct ThreadLocalRegion {
+ static constexpr std::size_t MessageBufferSize = 0x100;
+ std::array<u32, MessageBufferSize / sizeof(u32)> message_buffer;
+ std::atomic_uint16_t disable_count;
+ std::atomic_uint16_t interrupt_flag;
+};
+
class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait {
public:
explicit ThreadQueueImplForKThreadSleep(KernelCore& kernel_)
@@ -346,7 +355,7 @@ void KThread::StartTermination() {
if (parent != nullptr) {
parent->ReleaseUserException(this);
if (parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) {
- parent->UnpinCurrentThread();
+ parent->UnpinCurrentThread(core_id);
}
}
@@ -372,7 +381,7 @@ void KThread::StartTermination() {
this->Close();
}
-void KThread::Pin() {
+void KThread::Pin(s32 current_core) {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Set ourselves as pinned.
@@ -389,7 +398,6 @@ void KThread::Pin() {
// Bind ourselves to this core.
const s32 active_core = GetActiveCore();
- const s32 current_core = GetCurrentCoreId(kernel);
SetActiveCore(current_core);
physical_ideal_core_id = current_core;
@@ -482,6 +490,36 @@ void KThread::Unpin() {
}
}
+u16 KThread::GetUserDisableCount() const {
+ if (!IsUserThread()) {
+ // We only emulate TLS for user threads
+ return {};
+ }
+
+ auto& memory = kernel.System().Memory();
+ return memory.Read16(tls_address + offsetof(ThreadLocalRegion, disable_count));
+}
+
+void KThread::SetInterruptFlag() {
+ if (!IsUserThread()) {
+ // We only emulate TLS for user threads
+ return;
+ }
+
+ auto& memory = kernel.System().Memory();
+ memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1);
+}
+
+void KThread::ClearInterruptFlag() {
+ if (!IsUserThread()) {
+ // We only emulate TLS for user threads
+ return;
+ }
+
+ auto& memory = kernel.System().Memory();
+ memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
+}
+
ResultCode KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
KScopedSchedulerLock sl{kernel};