kern: devirtualize KReadableEvent::Reset, KWorkerTask::DoWorkerTask

This commit is contained in:
Michael Scire 2021-10-24 20:41:38 -07:00
parent fd187f952e
commit 54dde406bc
12 changed files with 62 additions and 24 deletions

View file

@ -96,7 +96,7 @@ namespace ams::kern {
size_t count = 0; size_t count = 0;
for (const auto &obj : list) { for (const auto &obj : list) {
AMS_AUDIT(obj.DynamicCast<const U *>() != nullptr); MESOSPHERE_AUDIT(obj.DynamicCast<const U *>() != nullptr);
if (static_cast<const U &>(obj).GetOwner() == owner) { if (static_cast<const U &>(obj).GetOwner() == owner) {
++count; ++count;
} }

View file

@ -38,7 +38,16 @@ namespace ams::kern {
Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type); Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type);
void Finalize(); void Finalize();
virtual Result Reset() override; Result Reset();
Result Clear() {
MESOSPHERE_ASSERT_THIS();
/* Try to perform a reset, succeeding unconditionally. */
this->Reset();
return ResultSuccess();
}
bool IsInitialized() const { return m_is_initialized; } bool IsInitialized() const { return m_is_initialized; }

View file

@ -34,7 +34,7 @@
namespace ams::kern { namespace ams::kern {
class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>, public KWorkerTask { class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
MESOSPHERE_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); MESOSPHERE_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
public: public:
enum State { enum State {
@ -399,7 +399,7 @@ namespace ams::kern {
return m_is_signaled; return m_is_signaled;
} }
virtual void DoWorkerTask() override; void DoWorkerTaskImpl();
private: private:
void ChangeState(State new_state) { void ChangeState(State new_state) {
if (m_state != new_state) { if (m_state != new_state) {

View file

@ -36,11 +36,22 @@ namespace ams::kern {
constexpr KEvent *GetParent() const { return m_parent; } constexpr KEvent *GetParent() const { return m_parent; }
Result Signal(); Result Signal();
Result Clear(); Result Reset();
Result Clear() {
MESOSPHERE_ASSERT_THIS();
/* Try to perform a reset, succeeding unconditionally. */
this->Reset();
return ResultSuccess();
}
virtual bool IsSignaled() const override; virtual bool IsSignaled() const override;
virtual void Destroy() override; virtual void Destroy() override;
virtual Result Reset();
/* NOTE: This is a virtual function in Nintendo's kernel. */
/* virtual Result Reset(); */
}; };
} }

View file

@ -32,7 +32,7 @@ namespace ams::kern {
using KThreadFunction = void (*)(uintptr_t); using KThreadFunction = void (*)(uintptr_t);
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, public util::IntrusiveListBaseNode<KThread>, public KTimerTask, public KWorkerTask { class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>, public util::IntrusiveListBaseNode<KThread>, public KTimerTask {
MESOSPHERE_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); MESOSPHERE_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
private: private:
friend class KProcess; friend class KProcess;
@ -235,7 +235,7 @@ namespace ams::kern {
bool m_resource_limit_release_hint; bool m_resource_limit_release_hint;
public: public:
constexpr explicit KThread(util::ConstantInitializeTag) constexpr explicit KThread(util::ConstantInitializeTag)
: KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>(util::ConstantInitialize), KTimerTask(util::ConstantInitialize), : KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>(util::ConstantInitialize), KTimerTask(util::ConstantInitialize),
m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{}, m_process_list_node{}, m_condvar_arbiter_tree_node{util::ConstantInitialize}, m_priority{-1}, m_condvar_tree{}, m_condvar_key{},
m_thread_context{util::ConstantInitialize}, m_virtual_affinity_mask{}, m_physical_affinity_mask{}, m_thread_id{}, m_cpu_time{0}, m_address_key{Null<KProcessAddress>}, m_parent{}, m_thread_context{util::ConstantInitialize}, m_virtual_affinity_mask{}, m_physical_affinity_mask{}, m_thread_id{}, m_cpu_time{0}, m_address_key{Null<KProcessAddress>}, m_parent{},
m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null<KProcessAddress>}, m_tls_heap_address{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize}, m_kernel_stack_top{}, m_light_ipc_data{}, m_tls_address{Null<KProcessAddress>}, m_tls_heap_address{}, m_activity_pause_lock{}, m_sync_object_buffer{util::ConstantInitialize},
@ -622,7 +622,7 @@ namespace ams::kern {
virtual bool IsSignaled() const override; virtual bool IsSignaled() const override;
void OnTimer(); void OnTimer();
virtual void DoWorkerTask() override; void DoWorkerTaskImpl();
public: public:
static constexpr bool IsConditionVariableThreadTreeValid() { static constexpr bool IsConditionVariableThreadTreeValid() {
return ConditionVariableThreadTreeTraits::IsValid(); return ConditionVariableThreadTreeTraits::IsValid();

View file

@ -18,16 +18,23 @@
namespace ams::kern { namespace ams::kern {
class KWorkerTask { /* NOTE: We inherit KWorkerTask from KSynchronizationObject in order to devirtualize DoWorkerTask, which is exclusive to KThread/KProcess. */
/* This should be reverted, if Nintendo adds new types of worker tasks in the future. */
/* Nintendo has class KWorkerTask { ... } with identical interface but DoWorkerTask() virtual. */
class KWorkerTask : public KSynchronizationObject {
private: private:
KWorkerTask *m_next_task; KWorkerTask *m_next_task;
public: public:
constexpr ALWAYS_INLINE KWorkerTask() : m_next_task(nullptr) { /* ... */ } constexpr ALWAYS_INLINE explicit KWorkerTask(util::ConstantInitializeTag) : KSynchronizationObject(util::ConstantInitialize), m_next_task(nullptr) { /* ... */ }
ALWAYS_INLINE explicit KWorkerTask() : m_next_task(nullptr) { /* ... */ }
constexpr ALWAYS_INLINE KWorkerTask *GetNextTask() const { return m_next_task; } constexpr ALWAYS_INLINE KWorkerTask *GetNextTask() const { return m_next_task; }
constexpr ALWAYS_INLINE void SetNextTask(KWorkerTask *task) { m_next_task = task; } constexpr ALWAYS_INLINE void SetNextTask(KWorkerTask *task) { m_next_task = task; }
virtual void DoWorkerTask() = 0; void DoWorkerTask();
}; };
} }

View file

@ -432,7 +432,7 @@ namespace ams::kern {
return ResultSuccess(); return ResultSuccess();
} }
void KProcess::DoWorkerTask() { void KProcess::DoWorkerTaskImpl() {
/* Terminate child threads. */ /* Terminate child threads. */
TerminateChildren(this, nullptr); TerminateChildren(this, nullptr);

View file

@ -59,14 +59,6 @@ namespace ams::kern {
return ResultSuccess(); return ResultSuccess();
} }
Result KReadableEvent::Clear() {
MESOSPHERE_ASSERT_THIS();
this->Reset();
return ResultSuccess();
}
Result KReadableEvent::Reset() { Result KReadableEvent::Reset() {
MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT_THIS();

View file

@ -406,7 +406,7 @@ namespace ams::kern {
this->Close(); this->Close();
} }
void KThread::DoWorkerTask() { void KThread::DoWorkerTaskImpl() {
/* Finish the termination that was begun by Exit(). */ /* Finish the termination that was begun by Exit(). */
this->FinishTermination(); this->FinishTermination();
} }

View file

@ -41,6 +41,17 @@ namespace ams::kern {
} }
void KWorkerTask::DoWorkerTask() {
if (auto * const thread = this->DynamicCast<KThread *>(); thread != nullptr) {
return thread->DoWorkerTaskImpl();
} else {
auto * const process = this->DynamicCast<KProcess *>();
MESOSPHERE_ABORT_UNLESS(process != nullptr);
return process->DoWorkerTaskImpl();
}
}
void KWorkerTaskManager::Initialize(s32 priority) { void KWorkerTaskManager::Initialize(s32 priority) {
/* Reserve a thread from the system limit. */ /* Reserve a thread from the system limit. */
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_ThreadCountMax, 1)); MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_ThreadCountMax, 1));

View file

@ -48,9 +48,13 @@ namespace ams::kern::svc {
{ {
KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(event_handle); KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(event_handle);
if (readable_event.IsNotNull()) { if (readable_event.IsNotNull()) {
if (auto * const interrupt_event = readable_event->DynamicCast<KInterruptEvent *>(); interrupt_event != nullptr) {
return interrupt_event->Clear();
} else {
return readable_event->Clear(); return readable_event->Clear();
} }
} }
}
return svc::ResultInvalidHandle(); return svc::ResultInvalidHandle();
} }

View file

@ -35,9 +35,13 @@ namespace ams::kern::svc {
{ {
KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(handle); KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(handle);
if (readable_event.IsNotNull()) { if (readable_event.IsNotNull()) {
if (auto * const interrupt_event = readable_event->DynamicCast<KInterruptEvent *>(); interrupt_event != nullptr) {
return interrupt_event->Reset();
} else {
return readable_event->Reset(); return readable_event->Reset();
} }
} }
}
/* Try to reset as process. */ /* Try to reset as process. */
{ {