mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-31 06:48:22 -04:00
kern: unify all waiting semantics to use single api
This commit is contained in:
parent
f6fb5f2c8d
commit
90732ff311
22 changed files with 904 additions and 683 deletions
|
@ -27,59 +27,9 @@ namespace ams::kern {
|
|||
KThread::WaiterList m_wait_list;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KLightConditionVariable() : m_wait_list() { /* ... */ }
|
||||
private:
|
||||
void WaitImpl(KLightLock *lock, s64 timeout, bool allow_terminating_thread) {
|
||||
KThread *owner = GetCurrentThreadPointer();
|
||||
KHardwareTimer *timer;
|
||||
|
||||
/* Sleep the thread. */
|
||||
{
|
||||
KScopedSchedulerLockAndSleep lk(&timer, owner, timeout);
|
||||
|
||||
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
||||
lk.CancelSleep();
|
||||
return;
|
||||
}
|
||||
|
||||
lock->Unlock();
|
||||
|
||||
|
||||
/* Set the thread as waiting. */
|
||||
GetCurrentThread().SetState(KThread::ThreadState_Waiting);
|
||||
|
||||
/* Add the thread to the queue. */
|
||||
m_wait_list.push_back(GetCurrentThread());
|
||||
}
|
||||
|
||||
/* Remove the thread from the wait list. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
m_wait_list.erase(m_wait_list.iterator_to(GetCurrentThread()));
|
||||
}
|
||||
|
||||
/* Cancel the task that the sleep setup. */
|
||||
if (timer != nullptr) {
|
||||
timer->CancelTask(owner);
|
||||
}
|
||||
|
||||
/* Re-acquire the lock. */
|
||||
lock->Lock();
|
||||
}
|
||||
public:
|
||||
void Wait(KLightLock *lock, s64 timeout = -1ll, bool allow_terminating_thread = true) {
|
||||
this->WaitImpl(lock, timeout, allow_terminating_thread);
|
||||
}
|
||||
|
||||
void Broadcast() {
|
||||
KScopedSchedulerLock lk;
|
||||
|
||||
/* Signal all threads. */
|
||||
for (auto &thread : m_wait_list) {
|
||||
thread.SetState(KThread::ThreadState_Runnable);
|
||||
}
|
||||
}
|
||||
|
||||
void Wait(KLightLock *lock, s64 timeout = -1ll, bool allow_terminating_thread = true);
|
||||
void Broadcast();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -27,12 +27,12 @@ namespace ams::kern {
|
|||
MESOSPHERE_AUTOOBJECT_TRAITS(KLightServerSession, KAutoObject);
|
||||
private:
|
||||
KLightSession *m_parent;
|
||||
KThreadQueue m_request_queue;
|
||||
KThreadQueue m_server_queue;
|
||||
KThread::WaiterList m_request_list;
|
||||
KThread *m_current_request;
|
||||
u64 m_server_thread_id;
|
||||
KThread *m_server_thread;
|
||||
public:
|
||||
constexpr KLightServerSession() : m_parent(), m_request_queue(), m_server_queue(), m_current_request(), m_server_thread() { /* ... */ }
|
||||
constexpr KLightServerSession() : m_parent(), m_request_list(), m_current_request(), m_server_thread_id(), m_server_thread() { /* ... */ }
|
||||
|
||||
void Initialize(KLightSession *parent) {
|
||||
/* Set member variables. */
|
||||
|
|
|
@ -45,7 +45,39 @@ namespace ams::kern {
|
|||
public:
|
||||
virtual void Finalize() override;
|
||||
virtual bool IsSignaled() const { AMS_INFINITE_LOOP(); }
|
||||
virtual void DumpWaiters();
|
||||
|
||||
void DumpWaiters();
|
||||
|
||||
ALWAYS_INLINE void LinkNode(ThreadListNode *node) {
|
||||
/* Link the node to the list. */
|
||||
if (m_thread_list_tail == nullptr) {
|
||||
m_thread_list_head = node;
|
||||
} else {
|
||||
m_thread_list_tail->next = node;
|
||||
}
|
||||
|
||||
m_thread_list_tail = node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void UnlinkNode(ThreadListNode *node) {
|
||||
/* Unlink the node from the list. */
|
||||
ThreadListNode *prev_ptr = reinterpret_cast<ThreadListNode *>(std::addressof(m_thread_list_head));
|
||||
ThreadListNode *prev_val = nullptr;
|
||||
ThreadListNode *prev, *tail_prev;
|
||||
|
||||
do {
|
||||
prev = prev_ptr;
|
||||
prev_ptr = prev_ptr->next;
|
||||
tail_prev = prev_val;
|
||||
prev_val = prev_ptr;
|
||||
} while (prev_ptr != node);
|
||||
|
||||
if (m_thread_list_tail == node) {
|
||||
m_thread_list_tail = tail_prev;
|
||||
}
|
||||
|
||||
prev->next = node->next;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace ams::kern {
|
|||
friend class KProcess;
|
||||
friend class KConditionVariable;
|
||||
friend class KAddressArbiter;
|
||||
friend class KThreadQueue;
|
||||
public:
|
||||
static constexpr s32 MainThreadPriority = 1;
|
||||
static constexpr s32 IdleThreadPriority = 64;
|
||||
|
@ -191,7 +192,6 @@ namespace ams::kern {
|
|||
KAffinityMask m_physical_affinity_mask{};
|
||||
u64 m_thread_id{};
|
||||
std::atomic<s64> m_cpu_time{};
|
||||
KSynchronizationObject *m_synced_object{};
|
||||
KProcessAddress m_address_key{};
|
||||
KProcess *m_parent{};
|
||||
void *m_kernel_stack_top{};
|
||||
|
@ -204,9 +204,7 @@ namespace ams::kern {
|
|||
s64 m_last_scheduled_tick{};
|
||||
QueueEntry m_per_core_priority_queue_entry[cpu::NumCores]{};
|
||||
KLightLock *m_waiting_lock{};
|
||||
|
||||
KThreadQueue *m_sleeping_queue{};
|
||||
|
||||
KThreadQueue *m_wait_queue{};
|
||||
WaiterList m_waiter_list{};
|
||||
WaiterList m_pinned_waiter_list{};
|
||||
KThread *m_lock_owner{};
|
||||
|
@ -215,6 +213,7 @@ namespace ams::kern {
|
|||
u32 m_address_key_value{};
|
||||
u32 m_suspend_request_flags{};
|
||||
u32 m_suspend_allowed_flags{};
|
||||
s32 m_synced_index{};
|
||||
Result m_wait_result;
|
||||
Result m_debug_exception_result;
|
||||
s32 m_base_priority{};
|
||||
|
@ -374,6 +373,8 @@ namespace ams::kern {
|
|||
void FinishTermination();
|
||||
|
||||
void IncreaseBasePriority(s32 priority);
|
||||
|
||||
NOINLINE void SetState(ThreadState state);
|
||||
public:
|
||||
constexpr u64 GetThreadId() const { return m_thread_id; }
|
||||
|
||||
|
@ -390,7 +391,6 @@ namespace ams::kern {
|
|||
|
||||
constexpr ThreadState GetState() const { return static_cast<ThreadState>(m_thread_state & ThreadState_Mask); }
|
||||
constexpr ThreadState GetRawState() const { return m_thread_state; }
|
||||
NOINLINE void SetState(ThreadState state);
|
||||
|
||||
NOINLINE KThreadContext *GetContextForSchedulerLoop();
|
||||
|
||||
|
@ -442,8 +442,6 @@ namespace ams::kern {
|
|||
constexpr QueueEntry &GetPriorityQueueEntry(s32 core) { return m_per_core_priority_queue_entry[core]; }
|
||||
constexpr const QueueEntry &GetPriorityQueueEntry(s32 core) const { return m_per_core_priority_queue_entry[core]; }
|
||||
|
||||
constexpr void SetSleepingQueue(KThreadQueue *q) { m_sleeping_queue = q; }
|
||||
|
||||
constexpr ConditionVariableThreadTree *GetConditionVariableTree() const { return m_condvar_tree; }
|
||||
|
||||
constexpr s32 GetNumKernelWaiters() const { return m_num_kernel_waiters; }
|
||||
|
@ -460,29 +458,22 @@ namespace ams::kern {
|
|||
constexpr void SetLockOwner(KThread *owner) { m_lock_owner = owner; }
|
||||
constexpr KThread *GetLockOwner() const { return m_lock_owner; }
|
||||
|
||||
constexpr void SetSyncedObject(KSynchronizationObject *obj, Result wait_res) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
constexpr void ClearWaitQueue() { m_wait_queue = nullptr; }
|
||||
|
||||
m_synced_object = obj;
|
||||
m_wait_result = wait_res;
|
||||
}
|
||||
void BeginWait(KThreadQueue *queue);
|
||||
void NotifyAvailable(KSynchronizationObject *signaled_object, Result wait_result);
|
||||
void EndWait(Result wait_result);
|
||||
void CancelWait(Result wait_result, bool cancel_timer_task);
|
||||
|
||||
constexpr Result GetWaitResult(KSynchronizationObject **out) const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
constexpr void SetSyncedIndex(s32 index) { m_synced_index = index; }
|
||||
constexpr s32 GetSyncedIndex() const { return m_synced_index; }
|
||||
|
||||
*out = m_synced_object;
|
||||
return m_wait_result;
|
||||
}
|
||||
constexpr void SetWaitResult(Result wait_res) { m_wait_result = wait_res; }
|
||||
constexpr Result GetWaitResult() const { return m_wait_result; }
|
||||
|
||||
constexpr void SetDebugExceptionResult(Result result) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
m_debug_exception_result = result;
|
||||
}
|
||||
constexpr void SetDebugExceptionResult(Result result) { m_debug_exception_result = result; }
|
||||
|
||||
constexpr Result GetDebugExceptionResult() const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
return m_debug_exception_result;
|
||||
}
|
||||
constexpr Result GetDebugExceptionResult() const { return m_debug_exception_result; }
|
||||
|
||||
void WaitCancel();
|
||||
|
||||
|
@ -585,8 +576,6 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
void Wakeup();
|
||||
|
||||
void SetBasePriority(s32 priority);
|
||||
Result SetPriorityToIdle();
|
||||
|
||||
|
|
|
@ -16,69 +16,28 @@
|
|||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_thread.hpp>
|
||||
#include <mesosphere/kern_select_hardware_timer.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KThreadQueue {
|
||||
private:
|
||||
KThread::WaiterList m_wait_list;
|
||||
KHardwareTimer *m_hardware_timer;
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KThreadQueue() : m_wait_list() { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KThreadQueue() : m_hardware_timer(nullptr) { /* ... */ }
|
||||
|
||||
bool IsEmpty() const { return m_wait_list.empty(); }
|
||||
constexpr void SetHardwareTimer(KHardwareTimer *timer) { m_hardware_timer = timer; }
|
||||
|
||||
KThread::WaiterList::iterator begin() { return m_wait_list.begin(); }
|
||||
KThread::WaiterList::iterator end() { return m_wait_list.end(); }
|
||||
virtual void NotifyAvailable(KThread *waiting_thread, KSynchronizationObject *signaled_object, Result wait_result);
|
||||
virtual void EndWait(KThread *waiting_thread, Result wait_result);
|
||||
virtual void CancelWait(KThread *waiting_thread, Result wait_result, bool cancel_timer_task);
|
||||
};
|
||||
|
||||
bool SleepThread(KThread *t) {
|
||||
KScopedSchedulerLock sl;
|
||||
class KThreadQueueWithoutEndWait : public KThreadQueue {
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KThreadQueueWithoutEndWait() : KThreadQueue() { /* ... */ }
|
||||
|
||||
/* If the thread needs terminating, don't enqueue it. */
|
||||
if (t->IsTerminationRequested()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the thread's queue and mark it as waiting. */
|
||||
t->SetSleepingQueue(this);
|
||||
t->SetState(KThread::ThreadState_Waiting);
|
||||
|
||||
/* Add the thread to the queue. */
|
||||
m_wait_list.push_back(*t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WakeupThread(KThread *t) {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Remove the thread from the queue. */
|
||||
m_wait_list.erase(m_wait_list.iterator_to(*t));
|
||||
|
||||
/* Mark the thread as no longer sleeping. */
|
||||
t->SetState(KThread::ThreadState_Runnable);
|
||||
t->SetSleepingQueue(nullptr);
|
||||
}
|
||||
|
||||
KThread *WakeupFrontThread() {
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (m_wait_list.empty()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
/* Remove the thread from the queue. */
|
||||
auto it = m_wait_list.begin();
|
||||
KThread *thread = std::addressof(*it);
|
||||
m_wait_list.erase(it);
|
||||
|
||||
MESOSPHERE_ASSERT(thread->GetState() == KThread::ThreadState_Waiting);
|
||||
|
||||
/* Mark the thread as no longer sleeping. */
|
||||
thread->SetState(KThread::ThreadState_Runnable);
|
||||
thread->SetSleepingQueue(nullptr);
|
||||
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
virtual void EndWait(KThread *waiting_thread, Result wait_result) override final;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -20,14 +20,13 @@
|
|||
|
||||
namespace ams::kern {
|
||||
|
||||
class KWaitObject : public KTimerTask {
|
||||
class KWaitObject {
|
||||
private:
|
||||
KThread::WaiterList m_wait_list;
|
||||
bool m_timer_used;
|
||||
KThread *m_next_thread;
|
||||
public:
|
||||
constexpr KWaitObject() : m_wait_list(), m_timer_used() { /* ... */ }
|
||||
constexpr KWaitObject() : m_wait_list(), m_next_thread() { /* ... */ }
|
||||
|
||||
virtual void OnTimer() override;
|
||||
Result Synchronize(s64 timeout);
|
||||
};
|
||||
|
||||
|
|
|
@ -32,8 +32,7 @@ namespace ams::kern {
|
|||
private:
|
||||
KWorkerTask *m_head_task;
|
||||
KWorkerTask *m_tail_task;
|
||||
KThread *m_thread;
|
||||
bool m_active;
|
||||
KThread *m_waiting_thread;
|
||||
private:
|
||||
static void ThreadFunction(uintptr_t arg);
|
||||
void ThreadFunctionImpl();
|
||||
|
@ -41,7 +40,7 @@ namespace ams::kern {
|
|||
KWorkerTask *GetTask();
|
||||
void AddTask(KWorkerTask *task);
|
||||
public:
|
||||
constexpr KWorkerTaskManager() : m_head_task(), m_tail_task(), m_thread(), m_active() { /* ... */ }
|
||||
constexpr KWorkerTaskManager() : m_head_task(), m_tail_task(), m_waiting_thread() { /* ... */ }
|
||||
|
||||
NOINLINE void Initialize(s32 priority);
|
||||
static void AddTask(WorkerType type, KWorkerTask *task);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue