os: adopt multiwait naming over waitable

This commit is contained in:
Michael Scire
2021-09-30 19:00:47 -07:00
parent d9b4009f82
commit 7444a68cd1
79 changed files with 869 additions and 869 deletions

View File

@@ -16,7 +16,7 @@
#include <stratosphere.hpp>
#include "os_inter_process_event.hpp"
#include "os_inter_process_event_impl.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl {
@@ -33,7 +33,7 @@ namespace ams::os::impl {
event->auto_clear = (clear_mode == EventClearMode_AutoClear);
/* Create the waitlist node. */
util::ConstructAt(event->waitable_object_list_storage);
util::ConstructAt(event->multi_wait_object_list_storage);
/* Set state. */
event->state = InterProcessEventType::State_Initialized;
@@ -71,7 +71,7 @@ namespace ams::os::impl {
}
/* Destroy the waitlist. */
util::DestroyAt(event->waitable_object_list_storage);
util::DestroyAt(event->multi_wait_object_list_storage);
}
void AttachInterProcessEvent(InterProcessEventType *event, Handle read_handle, bool read_handle_managed, Handle write_handle, bool write_handle_managed, EventClearMode clear_mode) {

View File

@@ -36,6 +36,6 @@ namespace ams::os::impl {
Handle GetReadableHandleOfInterProcessEvent(const InterProcessEventType *event);
Handle GetWritableHandleOfInterProcessEvent(const InterProcessEventType *event);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, InterProcessEventType *event);
void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, InterProcessEventType *event);
}

View File

@@ -18,21 +18,21 @@
namespace ams::os::impl {
class WaitableObjectList;
class WaitableManagerImpl;
class MultiWaitObjectList;
class MultiWaitImpl;
class WaitableHolderBase {
class MultiWaitHolderBase {
private:
WaitableManagerImpl *manager = nullptr;
MultiWaitImpl *multi_wait = nullptr;
public:
util::IntrusiveListNode manager_node;
util::IntrusiveListNode multi_wait_node;
util::IntrusiveListNode object_list_node;
public:
/* Gets whether the held waitable is currently signaled. */
/* Gets whether the held object is currently signaled. */
virtual TriBool IsSignaled() const = 0;
/* Adds to manager's object list, returns is signaled. */
/* Adds to multi wait's object list, returns is signaled. */
virtual TriBool LinkToObjectList() = 0;
/* Removes from the manager's object list. */
/* Removes from the multi wait's object list. */
virtual void UnlinkFromObjectList() = 0;
/* Gets handle to output, returns INVALID_HANDLE on failure. */
virtual Handle GetHandle() const = 0;
@@ -41,21 +41,21 @@ namespace ams::os::impl {
return TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max());
}
/* Interface with manager. */
void SetManager(WaitableManagerImpl *m) {
this->manager = m;
/* Interface with multi wait. */
void SetMultiWait(MultiWaitImpl *m) {
this->multi_wait = m;
}
WaitableManagerImpl *GetManager() const {
return this->manager;
MultiWaitImpl *GetMultiWait() const {
return this->multi_wait;
}
bool IsLinkedToManager() const {
return this->manager != nullptr;
bool IsLinked() const {
return this->multi_wait != nullptr;
}
};
class WaitableHolderOfUserObject : public WaitableHolderBase {
class MultiWaitHolderOfUserObject : public MultiWaitHolderBase {
public:
/* All user objects have no handle to wait on. */
virtual Handle GetHandle() const override final {
@@ -63,7 +63,7 @@ namespace ams::os::impl {
}
};
class WaitableHolderOfKernelObject : public WaitableHolderBase {
class MultiWaitHolderOfKernelObject : public MultiWaitHolderBase {
public:
/* All kernel objects have native handles, and thus don't have object list semantics. */
virtual TriBool LinkToObjectList() override final {

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_multiple_wait_holder_of_handle.hpp"
#include "os_multiple_wait_holder_of_event.hpp"
#include "os_multiple_wait_holder_of_inter_process_event.hpp"
#include "os_multiple_wait_holder_of_interrupt_event.hpp"
#include "os_multiple_wait_holder_of_timer_event.hpp"
#include "os_multiple_wait_holder_of_thread.hpp"
#include "os_multiple_wait_holder_of_semaphore.hpp"
#include "os_multiple_wait_holder_of_message_queue.hpp"
namespace ams::os::impl {
struct MultiWaitHolderImpl {
union {
util::TypedStorage<MultiWaitHolderOfHandle> holder_of_handle_storage;
util::TypedStorage<MultiWaitHolderOfEvent> holder_of_event_storage;
util::TypedStorage<MultiWaitHolderOfInterProcessEvent> holder_of_inter_process_event_storage;
util::TypedStorage<MultiWaitHolderOfInterruptEvent> holder_of_interrupt_event_storage;
util::TypedStorage<MultiWaitHolderOfTimerEvent> holder_of_timer_event_storage;
util::TypedStorage<MultiWaitHolderOfThread> holder_of_thread_storage;
util::TypedStorage<MultiWaitHolderOfSemaphore> holder_of_semaphore_storage;
util::TypedStorage<MultiWaitHolderOfMessageQueueForNotFull> holder_of_mq_for_not_full_storage;
util::TypedStorage<MultiWaitHolderOfMessageQueueForNotEmpty> holder_of_mq_for_not_empty_storage;
};
};
#define CHECK_HOLDER(T) \
static_assert(std::is_base_of<::ams::os::impl::MultiWaitHolderBase, T>::value && std::is_trivially_destructible<T>::value, #T)
CHECK_HOLDER(MultiWaitHolderOfHandle);
CHECK_HOLDER(MultiWaitHolderOfEvent);
CHECK_HOLDER(MultiWaitHolderOfInterProcessEvent);
CHECK_HOLDER(MultiWaitHolderOfInterruptEvent);
CHECK_HOLDER(MultiWaitHolderOfTimerEvent);
CHECK_HOLDER(MultiWaitHolderOfThread);
CHECK_HOLDER(MultiWaitHolderOfSemaphore);
CHECK_HOLDER(MultiWaitHolderOfMessageQueueForNotFull);
CHECK_HOLDER(MultiWaitHolderOfMessageQueueForNotEmpty);
#undef CHECK_HOLDER
static_assert(std::is_trivial<MultiWaitHolderImpl>::value && std::is_trivially_destructible<MultiWaitHolderImpl>::value);
static_assert(sizeof(MultiWaitHolderImpl) == sizeof(os::MultiWaitHolderType::impl_storage));
}

View File

@@ -14,12 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl {
class WaitableHolderOfEvent : public WaitableHolderOfUserObject {
class MultiWaitHolderOfEvent : public MultiWaitHolderOfUserObject {
private:
EventType *event;
private:
@@ -27,7 +27,7 @@ namespace ams::os::impl {
return this->event->signaled ? TriBool::True : TriBool::False;
}
public:
explicit WaitableHolderOfEvent(EventType *e) : event(e) { /* ... */ }
explicit MultiWaitHolderOfEvent(EventType *e) : event(e) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override {
@@ -38,14 +38,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_event));
GetReference(this->event->waitable_object_list_storage).LinkWaitableHolder(*this);
GetReference(this->event->multi_wait_object_list_storage).LinkMultiWaitHolder(*this);
return this->IsSignaledImpl();
}
virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_event));
GetReference(this->event->waitable_object_list_storage).UnlinkWaitableHolder(*this);
GetReference(this->event->multi_wait_object_list_storage).UnlinkMultiWaitHolder(*this);
}
};

View File

@@ -14,15 +14,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_multiple_wait_holder_base.hpp"
namespace ams::os::impl {
class WaitableHolderOfHandle : public WaitableHolderOfKernelObject {
class MultiWaitHolderOfHandle : public MultiWaitHolderOfKernelObject {
private:
Handle handle;
public:
explicit WaitableHolderOfHandle(Handle h) : handle(h) { /* ... */ }
explicit MultiWaitHolderOfHandle(Handle h) : handle(h) { /* ... */ }
/* IsSignaled, GetHandle both implemented. */
virtual TriBool IsSignaled() const override {

View File

@@ -14,16 +14,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_inter_process_event.hpp"
namespace ams::os::impl {
class WaitableHolderOfInterProcessEvent : public WaitableHolderOfKernelObject {
class MultiWaitHolderOfInterProcessEvent : public MultiWaitHolderOfKernelObject {
private:
InterProcessEventType *event;
public:
explicit WaitableHolderOfInterProcessEvent(InterProcessEventType *e) : event(e) { /* ... */ }
explicit MultiWaitHolderOfInterProcessEvent(InterProcessEventType *e) : event(e) { /* ... */ }
/* IsSignaled, GetHandle both implemented. */
virtual TriBool IsSignaled() const override {

View File

@@ -14,12 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "os_waitable_holder_of_interrupt_event.hpp"
#include "os_multiple_wait_holder_of_interrupt_event.hpp"
#include "os_interrupt_event_impl.hpp"
namespace ams::os::impl {
Handle WaitableHolderOfInterruptEvent::GetHandle() const {
Handle MultiWaitHolderOfInterruptEvent::GetHandle() const {
return GetReference(event->impl).GetHandle();
}

View File

@@ -14,15 +14,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_multiple_wait_holder_base.hpp"
namespace ams::os::impl {
class WaitableHolderOfInterruptEvent : public WaitableHolderOfKernelObject {
class MultiWaitHolderOfInterruptEvent : public MultiWaitHolderOfKernelObject {
private:
InterruptEventType *event;
public:
explicit WaitableHolderOfInterruptEvent(InterruptEventType *e) : event(e) { /* ... */ }
explicit MultiWaitHolderOfInterruptEvent(InterruptEventType *e) : event(e) { /* ... */ }
/* IsSignaled, GetHandle both implemented. */
virtual TriBool IsSignaled() const override {

View File

@@ -14,13 +14,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl {
template<MessageQueueWaitType WaitType>
class WaitableHolderOfMessageQueue : public WaitableHolderOfUserObject {
class MultiWaitHolderOfMessageQueue : public MultiWaitHolderOfUserObject {
static_assert(WaitType == MessageQueueWaitType::ForNotEmpty || WaitType == MessageQueueWaitType::ForNotFull);
private:
MessageQueueType *mq;
@@ -37,7 +37,7 @@ namespace ams::os::impl {
}
}
constexpr inline WaitableObjectList &GetObjectList() const {
constexpr inline MultiWaitObjectList &GetObjectList() const {
if constexpr (WaitType == MessageQueueWaitType::ForNotEmpty) {
return GetReference(this->mq->waitlist_not_empty);
} else if constexpr (WaitType == MessageQueueWaitType::ForNotFull) {
@@ -47,7 +47,7 @@ namespace ams::os::impl {
}
}
public:
explicit WaitableHolderOfMessageQueue(MessageQueueType *mq) : mq(mq) { /* ... */ }
explicit MultiWaitHolderOfMessageQueue(MessageQueueType *mq) : mq(mq) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override {
@@ -58,18 +58,18 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->mq->cs_queue));
this->GetObjectList().LinkWaitableHolder(*this);
this->GetObjectList().LinkMultiWaitHolder(*this);
return this->IsSignaledImpl();
}
virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->mq->cs_queue));
this->GetObjectList().UnlinkWaitableHolder(*this);
this->GetObjectList().UnlinkMultiWaitHolder(*this);
}
};
using WaitableHolderOfMessageQueueForNotEmpty = WaitableHolderOfMessageQueue<MessageQueueWaitType::ForNotEmpty>;
using WaitableHolderOfMessageQueueForNotFull = WaitableHolderOfMessageQueue<MessageQueueWaitType::ForNotFull>;
using MultiWaitHolderOfMessageQueueForNotEmpty = MultiWaitHolderOfMessageQueue<MessageQueueWaitType::ForNotEmpty>;
using MultiWaitHolderOfMessageQueueForNotFull = MultiWaitHolderOfMessageQueue<MessageQueueWaitType::ForNotFull>;
}

View File

@@ -14,12 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl {
class WaitableHolderOfSemaphore : public WaitableHolderOfUserObject {
class MultiWaitHolderOfSemaphore : public MultiWaitHolderOfUserObject {
private:
SemaphoreType *semaphore;
private:
@@ -27,7 +27,7 @@ namespace ams::os::impl {
return this->semaphore->count > 0 ? TriBool::True : TriBool::False;
}
public:
explicit WaitableHolderOfSemaphore(SemaphoreType *s) : semaphore(s) { /* ... */ }
explicit MultiWaitHolderOfSemaphore(SemaphoreType *s) : semaphore(s) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override {
@@ -38,14 +38,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->semaphore->cs_sema));
GetReference(this->semaphore->waitlist).LinkWaitableHolder(*this);
GetReference(this->semaphore->waitlist).LinkMultiWaitHolder(*this);
return this->IsSignaledImpl();
}
virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->semaphore->cs_sema));
GetReference(this->semaphore->waitlist).UnlinkWaitableHolder(*this);
GetReference(this->semaphore->waitlist).UnlinkMultiWaitHolder(*this);
}
};

View File

@@ -14,11 +14,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_multiple_wait_holder_base.hpp"
namespace ams::os::impl {
class WaitableHolderOfThread : public WaitableHolderOfUserObject {
class MultiWaitHolderOfThread : public MultiWaitHolderOfUserObject {
private:
ThreadType *thread;
private:
@@ -26,7 +26,7 @@ namespace ams::os::impl {
return this->thread->state == ThreadType::State_Terminated ? TriBool::True : TriBool::False;
}
public:
explicit WaitableHolderOfThread(ThreadType *t) : thread(t) { /* ... */ }
explicit MultiWaitHolderOfThread(ThreadType *t) : thread(t) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override {
@@ -37,14 +37,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->thread->cs_thread));
GetReference(this->thread->waitlist).LinkWaitableHolder(*this);
GetReference(this->thread->waitlist).LinkMultiWaitHolder(*this);
return this->IsSignaledImpl();
}
virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->thread->cs_thread));
GetReference(this->thread->waitlist).UnlinkWaitableHolder(*this);
GetReference(this->thread->waitlist).UnlinkMultiWaitHolder(*this);
}
};

View File

@@ -16,22 +16,22 @@
#pragma once
#include <stratosphere.hpp>
#include "os_timer_event_helper.hpp"
#include "os_waitable_holder_base.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl {
class WaitableHolderOfTimerEvent : public WaitableHolderOfUserObject {
class MultiWaitHolderOfTimerEvent : public MultiWaitHolderOfUserObject {
private:
TimerEventType *event;
private:
TriBool IsSignaledImpl() const {
TimeSpan cur_time = this->GetManager()->GetCurrentTime();
TimeSpan cur_time = this->GetMultiWait()->GetCurrentTime();
UpdateSignalStateAndRecalculateNextTimeToWakeupUnsafe(this->event, cur_time);
return this->event->signaled ? TriBool::True : TriBool::False;
}
public:
explicit WaitableHolderOfTimerEvent(TimerEventType *e) : event(e) { /* ... */ }
explicit MultiWaitHolderOfTimerEvent(TimerEventType *e) : event(e) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override {
@@ -42,14 +42,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_timer_event));
GetReference(this->event->waitable_object_list_storage).LinkWaitableHolder(*this);
GetReference(this->event->multi_wait_object_list_storage).LinkMultiWaitHolder(*this);
return this->IsSignaledImpl();
}
virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_timer_event));
GetReference(this->event->waitable_object_list_storage).UnlinkWaitableHolder(*this);
GetReference(this->event->multi_wait_object_list_storage).UnlinkMultiWaitHolder(*this);
}
/* Gets the amount of time remaining until this wakes up. */

View File

@@ -14,17 +14,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "os_waitable_manager_impl.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_impl.hpp"
#include "os_multiple_wait_object_list.hpp"
#include "os_tick_manager.hpp"
namespace ams::os::impl {
Result WaitableManagerImpl::WaitAnyImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
Result MultiWaitImpl::WaitAnyImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
/* Prepare for processing. */
this->signaled_holder = nullptr;
this->target_impl.SetCurrentThreadHandleForCancelWait();
WaitableHolderBase *holder = this->LinkHoldersToObjectList();
MultiWaitHolderBase *holder = this->LinkHoldersToObjectList();
/* Check if we've been signaled. */
{
@@ -59,9 +59,9 @@ namespace ams::os::impl {
return wait_result;
}
Result WaitableManagerImpl::WaitAnyHandleImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
Result MultiWaitImpl::WaitAnyHandleImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
Handle object_handles[MaximumHandleCount];
WaitableHolderBase *objects[MaximumHandleCount];
MultiWaitHolderBase *objects[MaximumHandleCount];
const s32 count = this->BuildHandleArray(object_handles, objects, MaximumHandleCount);
const TimeSpan end_time = infinite ? TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()) : GetCurrentTick().ToTimeSpan() + timeout;
@@ -70,7 +70,7 @@ namespace ams::os::impl {
this->current_time = GetCurrentTick().ToTimeSpan();
TimeSpan min_timeout = 0;
WaitableHolderBase *min_timeout_object = this->RecalculateNextTimeout(&min_timeout, end_time);
MultiWaitHolderBase *min_timeout_object = this->RecalculateNextTimeout(&min_timeout, end_time);
s32 index = WaitInvalid;
Result wait_result = ResultSuccess();
@@ -129,16 +129,17 @@ namespace ams::os::impl {
*out = objects[index];
return wait_result;
}
break;
}
reply_target = svc::InvalidHandle;
}
}
s32 WaitableManagerImpl::BuildHandleArray(Handle out_handles[], WaitableHolderBase *out_objects[], s32 num) {
s32 MultiWaitImpl::BuildHandleArray(Handle out_handles[], MultiWaitHolderBase *out_objects[], s32 num) {
s32 count = 0;
for (WaitableHolderBase &holder_base : this->waitable_list) {
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
if (Handle handle = holder_base.GetHandle(); handle != svc::InvalidHandle) {
AMS_ASSERT(count < num);
@@ -151,10 +152,10 @@ namespace ams::os::impl {
return count;
}
WaitableHolderBase *WaitableManagerImpl::LinkHoldersToObjectList() {
WaitableHolderBase *signaled_holder = nullptr;
MultiWaitHolderBase *MultiWaitImpl::LinkHoldersToObjectList() {
MultiWaitHolderBase *signaled_holder = nullptr;
for (WaitableHolderBase &holder_base : this->waitable_list) {
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
TriBool is_signaled = holder_base.LinkToObjectList();
if (signaled_holder == nullptr && is_signaled == TriBool::True) {
@@ -165,17 +166,17 @@ namespace ams::os::impl {
return signaled_holder;
}
void WaitableManagerImpl::UnlinkHoldersFromObjectList() {
for (WaitableHolderBase &holder_base : this->waitable_list) {
void MultiWaitImpl::UnlinkHoldersFromObjectList() {
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
holder_base.UnlinkFromObjectList();
}
}
WaitableHolderBase *WaitableManagerImpl::RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time) {
WaitableHolderBase *min_timeout_holder = nullptr;
MultiWaitHolderBase *MultiWaitImpl::RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time) {
MultiWaitHolderBase *min_timeout_holder = nullptr;
TimeSpan min_time = end_time;
for (WaitableHolderBase &holder_base : this->waitable_list) {
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
if (const TimeSpan cur_time = holder_base.GetAbsoluteWakeupTime(); cur_time < min_time) {
min_timeout_holder = &holder_base;
min_time = cur_time;
@@ -190,7 +191,7 @@ namespace ams::os::impl {
return min_timeout_holder;
}
void WaitableManagerImpl::SignalAndWakeupThread(WaitableHolderBase *holder_base) {
void MultiWaitImpl::SignalAndWakeupThread(MultiWaitHolderBase *holder_base) {
std::scoped_lock lk(this->cs_wait);
if (this->signaled_holder == nullptr) {

View File

@@ -14,41 +14,41 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_multiple_wait_holder_base.hpp"
#if defined(ATMOSPHERE_OS_HORIZON)
#include "os_waitable_manager_target_impl.os.horizon.hpp"
#include "os_multiple_wait_target_impl.os.horizon.hpp"
#else
#error "Unknown OS for ams::os::WaitableManagerTargetImpl"
#error "Unknown OS for ams::os::MultiWaitTargetImpl"
#endif
namespace ams::os::impl {
class WaitableManagerImpl {
class MultiWaitImpl {
public:
static constexpr size_t MaximumHandleCount = WaitableManagerTargetImpl::MaximumHandleCount;
static constexpr size_t MaximumHandleCount = MultiWaitTargetImpl::MaximumHandleCount;
static constexpr s32 WaitInvalid = -3;
static constexpr s32 WaitCancelled = -2;
static constexpr s32 WaitTimedOut = -1;
using ListType = util::IntrusiveListMemberTraits<&WaitableHolderBase::manager_node>::ListType;
using MultiWaitList = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::multi_wait_node>::ListType;
private:
ListType waitable_list;
WaitableHolderBase *signaled_holder;
MultiWaitList multi_wait_list;
MultiWaitHolderBase *signaled_holder;
TimeSpan current_time;
InternalCriticalSection cs_wait;
WaitableManagerTargetImpl target_impl;
MultiWaitTargetImpl target_impl;
private:
Result WaitAnyImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
Result WaitAnyHandleImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
s32 BuildHandleArray(Handle out_handles[], WaitableHolderBase *out_objects[], s32 num);
Result WaitAnyImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
Result WaitAnyHandleImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
s32 BuildHandleArray(Handle out_handles[], MultiWaitHolderBase *out_objects[], s32 num);
WaitableHolderBase *LinkHoldersToObjectList();
MultiWaitHolderBase *LinkHoldersToObjectList();
void UnlinkHoldersFromObjectList();
WaitableHolderBase *RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time);
MultiWaitHolderBase *RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time);
WaitableHolderBase *WaitAnyImpl(bool infinite, TimeSpan timeout) {
WaitableHolderBase *holder = nullptr;
MultiWaitHolderBase *WaitAnyImpl(bool infinite, TimeSpan timeout) {
MultiWaitHolderBase *holder = nullptr;
const Result wait_result = this->WaitAnyImpl(std::addressof(holder), infinite, timeout, false, svc::InvalidHandle);
R_ASSERT(wait_result);
@@ -58,48 +58,48 @@ namespace ams::os::impl {
}
public:
/* Wait. */
WaitableHolderBase *WaitAny() {
MultiWaitHolderBase *WaitAny() {
return this->WaitAnyImpl(true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()));
}
WaitableHolderBase *TryWaitAny() {
MultiWaitHolderBase *TryWaitAny() {
return this->WaitAnyImpl(false, TimeSpan(0));
}
WaitableHolderBase *TimedWaitAny(TimeSpan ts) {
MultiWaitHolderBase *TimedWaitAny(TimeSpan ts) {
return this->WaitAnyImpl(false, ts);
}
Result ReplyAndReceive(WaitableHolderBase **out, Handle reply_target) {
Result ReplyAndReceive(MultiWaitHolderBase **out, Handle reply_target) {
return this->WaitAnyImpl(out, true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()), true, reply_target);
}
/* List management. */
bool IsEmpty() const {
return this->waitable_list.empty();
return this->multi_wait_list.empty();
}
void LinkWaitableHolder(WaitableHolderBase &holder_base) {
this->waitable_list.push_back(holder_base);
void LinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->multi_wait_list.push_back(holder_base);
}
void UnlinkWaitableHolder(WaitableHolderBase &holder_base) {
this->waitable_list.erase(this->waitable_list.iterator_to(holder_base));
void UnlinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->multi_wait_list.erase(this->multi_wait_list.iterator_to(holder_base));
}
void UnlinkAll() {
while (!this->IsEmpty()) {
this->waitable_list.front().SetManager(nullptr);
this->waitable_list.pop_front();
this->multi_wait_list.front().SetMultiWait(nullptr);
this->multi_wait_list.pop_front();
}
}
void MoveAllFrom(WaitableManagerImpl &other) {
/* Set manager for all of the other's waitables. */
for (auto &w : other.waitable_list) {
w.SetManager(this);
void MoveAllFrom(MultiWaitImpl &other) {
/* Set ourselves as multi wait for all of the other's holders. */
for (auto &w : other.multi_wait_list) {
w.SetMultiWait(this);
}
this->waitable_list.splice(this->waitable_list.end(), other.waitable_list);
this->multi_wait_list.splice(this->multi_wait_list.end(), other.multi_wait_list);
}
/* Other. */
@@ -107,7 +107,7 @@ namespace ams::os::impl {
return this->current_time;
}
void SignalAndWakeupThread(WaitableHolderBase *holder_base);
void SignalAndWakeupThread(MultiWaitHolderBase *holder_base);
};
}

View File

@@ -14,26 +14,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_waitable_manager_impl.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_impl.hpp"
namespace ams::os::impl {
class WaitableObjectList {
class MultiWaitObjectList {
public:
using ListType = util::IntrusiveListMemberTraits<&WaitableHolderBase::object_list_node>::ListType;
using ListType = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::object_list_node>::ListType;
private:
ListType object_list;
public:
void SignalAllThreads() {
for (WaitableHolderBase &holder_base : this->object_list) {
holder_base.GetManager()->SignalAndWakeupThread(&holder_base);
for (MultiWaitHolderBase &holder_base : this->object_list) {
holder_base.GetMultiWait()->SignalAndWakeupThread(&holder_base);
}
}
void BroadcastAllThreads() {
for (WaitableHolderBase &holder_base : this->object_list) {
holder_base.GetManager()->SignalAndWakeupThread(nullptr);
for (MultiWaitHolderBase &holder_base : this->object_list) {
holder_base.GetMultiWait()->SignalAndWakeupThread(nullptr);
}
}
@@ -41,11 +41,11 @@ namespace ams::os::impl {
return this->object_list.empty();
}
void LinkWaitableHolder(WaitableHolderBase &holder_base) {
void LinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->object_list.push_back(holder_base);
}
void UnlinkWaitableHolder(WaitableHolderBase &holder_base) {
void UnlinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->object_list.erase(this->object_list.iterator_to(holder_base));
}
};

View File

@@ -14,18 +14,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "os_waitable_holder_base.hpp"
#include "os_waitable_manager_impl.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_impl.hpp"
namespace ams::os::impl {
Result WaitableManagerHorizonImpl::WaitSynchronizationN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns) {
Result MultiWaitHorizonImpl::WaitSynchronizationN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns) {
AMS_ASSERT(!(num == 0 && ns == 0));
s32 index = WaitableManagerImpl::WaitInvalid;
s32 index = MultiWaitImpl::WaitInvalid;
R_TRY_CATCH(svc::WaitSynchronization(std::addressof(index), static_cast<const svc::Handle *>(arr), num, ns)) {
R_CATCH(svc::ResultTimedOut) { index = WaitableManagerImpl::WaitTimedOut; }
R_CATCH(svc::ResultCancelled) { index = WaitableManagerImpl::WaitCancelled; }
R_CATCH(svc::ResultTimedOut) { index = MultiWaitImpl::WaitTimedOut; }
R_CATCH(svc::ResultCancelled) { index = MultiWaitImpl::WaitCancelled; }
/* All other results are critical errors. */
/* svc::ResultThreadTerminating */
/* svc::ResultInvalidHandle. */
@@ -37,17 +37,17 @@ namespace ams::os::impl {
return ResultSuccess();
}
Result WaitableManagerHorizonImpl::ReplyAndReceiveN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns, Handle reply_target) {
Result MultiWaitHorizonImpl::ReplyAndReceiveN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns, Handle reply_target) {
/* NOTE: Nintendo does not initialize this value, which seems like it can cause incorrect behavior. */
s32 index = WaitableManagerImpl::WaitInvalid;
static_assert(WaitableManagerImpl::WaitInvalid != -1);
s32 index = MultiWaitImpl::WaitInvalid;
static_assert(MultiWaitImpl::WaitInvalid != -1);
R_TRY_CATCH(svc::ReplyAndReceive(std::addressof(index), arr, num, reply_target, ns)) {
R_CATCH(svc::ResultTimedOut) { *out_index = WaitableManagerImpl::WaitTimedOut; return R_CURRENT_RESULT; }
R_CATCH(svc::ResultCancelled) { *out_index = WaitableManagerImpl::WaitCancelled; return R_CURRENT_RESULT; }
R_CATCH(svc::ResultTimedOut) { *out_index = MultiWaitImpl::WaitTimedOut; return R_CURRENT_RESULT; }
R_CATCH(svc::ResultCancelled) { *out_index = MultiWaitImpl::WaitCancelled; return R_CURRENT_RESULT; }
R_CATCH(svc::ResultSessionClosed) {
if (index == -1) {
*out_index = WaitableManagerImpl::WaitInvalid;
*out_index = MultiWaitImpl::WaitInvalid;
return os::ResultSessionClosedForReply();
} else {
*out_index = index;
@@ -64,7 +64,7 @@ namespace ams::os::impl {
return ResultSuccess();
}
void WaitableManagerHorizonImpl::CancelWait() {
void MultiWaitHorizonImpl::CancelWait() {
R_ABORT_UNLESS(svc::CancelSynchronization(this->handle));
}

View File

@@ -19,7 +19,7 @@
namespace ams::os::impl {
class WaitableManagerHorizonImpl {
class MultiWaitHorizonImpl {
public:
static constexpr size_t MaximumHandleCount = static_cast<size_t>(ams::svc::ArgumentHandleCountMax);
private:
@@ -63,6 +63,6 @@ namespace ams::os::impl {
}
};
using WaitableManagerTargetImpl = WaitableManagerHorizonImpl;
using MultiWaitTargetImpl = MultiWaitHorizonImpl;
}

View File

@@ -15,10 +15,10 @@
*/
#include <stratosphere.hpp>
#include "os_thread_manager.hpp"
#include "os_waitable_manager_impl.hpp"
#include "os_waitable_holder_base.hpp"
#include "os_waitable_holder_impl.hpp"
#include "os_waitable_object_list.hpp"
#include "os_multiple_wait_impl.hpp"
#include "os_multiple_wait_holder_base.hpp"
#include "os_multiple_wait_holder_impl.hpp"
#include "os_multiple_wait_object_list.hpp"
#include "os_utility.hpp"
namespace ams::os::impl {

View File

@@ -14,8 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_base.hpp"
#include "os_waitable_manager_impl.hpp"
namespace ams::os::impl {

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "os_waitable_holder_of_handle.hpp"
#include "os_waitable_holder_of_event.hpp"
#include "os_waitable_holder_of_inter_process_event.hpp"
#include "os_waitable_holder_of_interrupt_event.hpp"
#include "os_waitable_holder_of_timer_event.hpp"
#include "os_waitable_holder_of_thread.hpp"
#include "os_waitable_holder_of_semaphore.hpp"
#include "os_waitable_holder_of_message_queue.hpp"
namespace ams::os::impl {
struct WaitableHolderImpl {
union {
util::TypedStorage<WaitableHolderOfHandle> holder_of_handle_storage;
util::TypedStorage<WaitableHolderOfEvent> holder_of_event_storage;
util::TypedStorage<WaitableHolderOfInterProcessEvent> holder_of_inter_process_event_storage;
util::TypedStorage<WaitableHolderOfInterruptEvent> holder_of_interrupt_event_storage;
util::TypedStorage<WaitableHolderOfTimerEvent> holder_of_timer_event_storage;
util::TypedStorage<WaitableHolderOfThread> holder_of_thread_storage;
util::TypedStorage<WaitableHolderOfSemaphore> holder_of_semaphore_storage;
util::TypedStorage<WaitableHolderOfMessageQueueForNotFull> holder_of_mq_for_not_full_storage;
util::TypedStorage<WaitableHolderOfMessageQueueForNotEmpty> holder_of_mq_for_not_empty_storage;
};
};
#define CHECK_HOLDER(T) \
static_assert(std::is_base_of<::ams::os::impl::WaitableHolderBase, T>::value && std::is_trivially_destructible<T>::value, #T)
CHECK_HOLDER(WaitableHolderOfHandle);
CHECK_HOLDER(WaitableHolderOfEvent);
CHECK_HOLDER(WaitableHolderOfInterProcessEvent);
CHECK_HOLDER(WaitableHolderOfInterruptEvent);
CHECK_HOLDER(WaitableHolderOfTimerEvent);
CHECK_HOLDER(WaitableHolderOfThread);
CHECK_HOLDER(WaitableHolderOfSemaphore);
CHECK_HOLDER(WaitableHolderOfMessageQueueForNotFull);
CHECK_HOLDER(WaitableHolderOfMessageQueueForNotEmpty);
#undef CHECK_HOLDER
static_assert(std::is_trivial<WaitableHolderImpl>::value && std::is_trivially_destructible<WaitableHolderImpl>::value);
static_assert(sizeof(WaitableHolderImpl) == sizeof(os::WaitableHolderType::impl_storage));
}