summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_condition_variable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_condition_variable.cpp')
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp37
1 files changed, 21 insertions, 16 deletions
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index 170d8fa0d..f51cf3e7b 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -7,12 +7,13 @@
#include "core/arm/exclusive_monitor.h"
#include "core/core.h"
#include "core/hle/kernel/k_condition_variable.h"
+#include "core/hle/kernel/k_linked_list.h"
+#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/process.h"
#include "core/hle/kernel/svc_common.h"
#include "core/hle/kernel/svc_results.h"
#include "core/memory.h"
@@ -107,8 +108,8 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val
// Wait for the address.
{
- std::shared_ptr<KThread> owner_thread;
- ASSERT(!owner_thread);
+ KScopedAutoObject<KThread> owner_thread;
+ ASSERT(owner_thread.IsNull());
{
KScopedSchedulerLock sl(kernel);
cur_thread->SetSyncedObject(nullptr, RESULT_SUCCESS);
@@ -126,8 +127,10 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val
R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), RESULT_SUCCESS);
// Get the lock owner thread.
- owner_thread = kernel.CurrentProcess()->GetHandleTable().Get<KThread>(handle);
- R_UNLESS(owner_thread, ResultInvalidHandle);
+ owner_thread =
+ kernel.CurrentProcess()->GetHandleTable().GetObjectWithoutPseudoHandle<KThread>(
+ handle);
+ R_UNLESS(owner_thread.IsNotNull(), ResultInvalidHandle);
// Update the lock.
cur_thread->SetAddressKey(addr, value);
@@ -137,7 +140,7 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val
cur_thread->SetMutexWaitAddressForDebugging(addr);
}
}
- ASSERT(owner_thread);
+ ASSERT(owner_thread.IsNotNull());
}
// Remove the thread as a waiter from the lock owner.
@@ -176,19 +179,22 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) {
KThread* thread_to_close = nullptr;
if (can_access) {
- if (prev_tag == InvalidHandle) {
+ if (prev_tag == Svc::InvalidHandle) {
// If nobody held the lock previously, we're all good.
thread->SetSyncedObject(nullptr, RESULT_SUCCESS);
thread->Wakeup();
} else {
// Get the previous owner.
- auto owner_thread = kernel.CurrentProcess()->GetHandleTable().Get<KThread>(
- prev_tag & ~Svc::HandleWaitMask);
+ KThread* owner_thread = kernel.CurrentProcess()
+ ->GetHandleTable()
+ .GetObjectWithoutPseudoHandle<KThread>(
+ static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask))
+ .ReleasePointerUnsafe();
if (owner_thread) {
// Add the thread as a waiter on the owner.
owner_thread->AddWaiter(thread);
- thread_to_close = owner_thread.get();
+ thread_to_close = owner_thread;
} else {
// The lock was tagged with a thread that doesn't exist.
thread->SetSyncedObject(nullptr, ResultInvalidState);
@@ -208,9 +214,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
// Prepare for signaling.
constexpr int MaxThreads = 16;
- // TODO(bunnei): This should just be Thread once we implement KAutoObject instead of using
- // std::shared_ptr.
- std::vector<std::shared_ptr<KThread>> thread_list;
+ KLinkedList<KThread> thread_list{kernel};
std::array<KThread*, MaxThreads> thread_array;
s32 num_to_close{};
@@ -228,7 +232,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
if (num_to_close < MaxThreads) {
thread_array[num_to_close++] = thread;
} else {
- thread_list.push_back(SharedFrom(thread));
+ thread_list.push_back(*thread);
}
}
@@ -250,8 +254,9 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
}
// Close threads in the list.
- for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
- (*it)->Close();
+ for (auto it = thread_list.begin(); it != thread_list.end();
+ it = thread_list.erase(kernel, it)) {
+ (*it).Close();
}
}