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

@ -31,10 +31,10 @@ namespace ams::ddsf {
bool is_initialized; bool is_initialized;
bool is_looping; bool is_looping;
os::SdkConditionVariable is_looping_cv; os::SdkConditionVariable is_looping_cv;
os::WaitableManagerType waitable_manager; os::MultiWaitType multi_wait;
os::ThreadType *loop_thread; os::ThreadType *loop_thread;
os::Event loop_control_event; os::Event loop_control_event;
os::WaitableHolderType loop_control_event_holder; os::MultiWaitHolderType loop_control_event_holder;
LoopControlCommandParameters *loop_control_command_params; LoopControlCommandParameters *loop_control_command_params;
os::LightEvent loop_control_command_done_event; os::LightEvent loop_control_command_done_event;
os::SdkMutex loop_control_lock; os::SdkMutex loop_control_lock;
@ -43,7 +43,7 @@ namespace ams::ddsf {
void ProcessControlCommandImpl(LoopControlCommandParameters *params); void ProcessControlCommandImpl(LoopControlCommandParameters *params);
public: public:
EventHandlerManager() EventHandlerManager()
: is_initialized(false), is_looping(false), is_looping_cv(), waitable_manager(), : is_initialized(false), is_looping(false), is_looping_cv(), multi_wait(),
loop_thread(), loop_control_event(os::EventClearMode_AutoClear), loop_control_event_holder(), loop_thread(), loop_control_event(os::EventClearMode_AutoClear), loop_control_event_holder(),
loop_control_command_params(), loop_control_command_done_event(os::EventClearMode_AutoClear), loop_control_command_params(), loop_control_command_done_event(os::EventClearMode_AutoClear),
loop_control_lock() loop_control_lock()

View file

@ -26,27 +26,27 @@ namespace ams::ddsf {
NON_MOVEABLE(IEventHandler); NON_MOVEABLE(IEventHandler);
friend class EventHandlerManager; friend class EventHandlerManager;
private: private:
os::WaitableHolderType holder; os::MultiWaitHolderType holder;
uintptr_t user_data; uintptr_t user_data;
bool is_initialized; bool is_initialized;
bool is_registered; bool is_registered;
private: private:
void Link(os::WaitableManagerType *manager) { void Link(os::MultiWaitType *multi_wait) {
AMS_ASSERT(this->IsInitialized()); AMS_ASSERT(this->IsInitialized());
AMS_ASSERT(!this->IsRegistered()); AMS_ASSERT(!this->IsRegistered());
AMS_ASSERT(manager != nullptr); AMS_ASSERT(multi_wait != nullptr);
os::LinkWaitableHolder(manager, std::addressof(this->holder)); os::LinkMultiWaitHolder(multi_wait, std::addressof(this->holder));
} }
void Unlink() { void Unlink() {
AMS_ASSERT(this->IsInitialized()); AMS_ASSERT(this->IsInitialized());
AMS_ASSERT(this->IsRegistered()); AMS_ASSERT(this->IsRegistered());
os::UnlinkWaitableHolder(std::addressof(this->holder)); os::UnlinkMultiWaitHolder(std::addressof(this->holder));
} }
static IEventHandler &ToEventHandler(os::WaitableHolderType *holder) { static IEventHandler &ToEventHandler(os::MultiWaitHolderType *holder) {
AMS_ASSERT(holder != nullptr); AMS_ASSERT(holder != nullptr);
auto &event_handler = *reinterpret_cast<IEventHandler *>(os::GetWaitableHolderUserData(holder)); auto &event_handler = *reinterpret_cast<IEventHandler *>(os::GetMultiWaitHolderUserData(holder));
AMS_ASSERT(event_handler.IsInitialized()); AMS_ASSERT(event_handler.IsInitialized());
return event_handler; return event_handler;
} }
@ -72,8 +72,8 @@ namespace ams::ddsf {
void Initialize(T *object) { void Initialize(T *object) {
AMS_ASSERT(object != nullptr); AMS_ASSERT(object != nullptr);
AMS_ASSERT(!this->IsInitialized()); AMS_ASSERT(!this->IsInitialized());
os::InitializeWaitableHolder(std::addressof(this->holder), object); os::InitializeMultiWaitHolder(std::addressof(this->holder), object);
os::SetWaitableHolderUserData(std::addressof(this->holder), reinterpret_cast<uintptr_t>(this)); os::SetMultiWaitHolderUserData(std::addressof(this->holder), reinterpret_cast<uintptr_t>(this));
this->is_initialized = true; this->is_initialized = true;
this->is_registered = false; this->is_registered = false;
} }
@ -81,7 +81,7 @@ namespace ams::ddsf {
void Finalize() { void Finalize() {
AMS_ASSERT(this->IsInitialized()); AMS_ASSERT(this->IsInitialized());
AMS_ASSERT(!this->IsRegistered()); AMS_ASSERT(!this->IsRegistered());
os::FinalizeWaitableHolder(std::addressof(this->holder)); os::FinalizeMultiWaitHolder(std::addressof(this->holder));
this->is_initialized = false; this->is_initialized = false;
this->is_registered = false; this->is_registered = false;
} }

View file

@ -50,4 +50,4 @@
#include <stratosphere/os/os_light_semaphore.hpp> #include <stratosphere/os/os_light_semaphore.hpp>
#include <stratosphere/os/os_barrier.hpp> #include <stratosphere/os/os_barrier.hpp>
#include <stratosphere/os/os_io_region.hpp> #include <stratosphere/os/os_io_region.hpp>
#include <stratosphere/os/os_waitable.hpp> #include <stratosphere/os/os_multiple_wait.hpp>

View file

@ -21,7 +21,7 @@
namespace ams::os { namespace ams::os {
struct EventType; struct EventType;
struct WaitableHolderType; struct MultiWaitHolderType;
void InitializeEvent(EventType *event, bool signaled, EventClearMode clear_mode); void InitializeEvent(EventType *event, bool signaled, EventClearMode clear_mode);
void FinalizeEvent(EventType *event); void FinalizeEvent(EventType *event);
@ -32,6 +32,6 @@ namespace ams::os {
bool TimedWaitEvent(EventType *event, TimeSpan timeout); bool TimedWaitEvent(EventType *event, TimeSpan timeout);
void ClearEvent(EventType *event); void ClearEvent(EventType *event);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, EventType *event); void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, EventType *event);
} }

View file

@ -23,7 +23,7 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableObjectList; class MultiWaitObjectList;
} }
@ -33,7 +33,7 @@ namespace ams::os {
State_Initialized = 1, State_Initialized = 1,
}; };
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitable_object_list_storage; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> multi_wait_object_list_storage;
bool signaled; bool signaled;
bool initially_signaled; bool initially_signaled;
u8 clear_mode; u8 clear_mode;

View file

@ -21,7 +21,7 @@
namespace ams::os { namespace ams::os {
struct InterruptEventType; struct InterruptEventType;
struct WaitableHolderType; struct MultiWaitHolderType;
void InitializeInterruptEvent(InterruptEventType *event, InterruptName name, EventClearMode clear_mode); void InitializeInterruptEvent(InterruptEventType *event, InterruptName name, EventClearMode clear_mode);
void FinalizeInterruptEvent(InterruptEventType *event); void FinalizeInterruptEvent(InterruptEventType *event);
@ -31,6 +31,6 @@ namespace ams::os {
bool TimedWaitInterruptEvent(InterruptEventType *event, TimeSpan timeout); bool TimedWaitInterruptEvent(InterruptEventType *event, TimeSpan timeout);
void ClearInterruptEvent(InterruptEventType *event); void ClearInterruptEvent(InterruptEventType *event);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, InterruptEventType *event); void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, InterruptEventType *event);
} }

View file

@ -23,7 +23,7 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableObjectList; class MultiWaitObjectList;
class InterruptEventImpl; class InterruptEventImpl;
} }
@ -34,7 +34,7 @@ namespace ams::os {
State_Initialized = 1, State_Initialized = 1,
}; };
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitable_object_list_storage; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> multi_wait_object_list_storage;
u8 clear_mode; u8 clear_mode;
u8 state; u8 state;

View file

@ -21,7 +21,7 @@
namespace ams::os { namespace ams::os {
struct MessageQueueType; struct MessageQueueType;
struct WaitableHolderType; struct MultiWaitHolderType;
void InitializeMessageQueue(MessageQueueType *mq, uintptr_t *buffer, size_t count); void InitializeMessageQueue(MessageQueueType *mq, uintptr_t *buffer, size_t count);
void FinalizeMessageQueue(MessageQueueType *mq); void FinalizeMessageQueue(MessageQueueType *mq);
@ -46,6 +46,6 @@ namespace ams::os {
bool TryPeekMessageQueue(uintptr_t *out, const MessageQueueType *mq); bool TryPeekMessageQueue(uintptr_t *out, const MessageQueueType *mq);
bool TimedPeekMessageQueue(uintptr_t *out, const MessageQueueType *mq, TimeSpan timeout); bool TimedPeekMessageQueue(uintptr_t *out, const MessageQueueType *mq, TimeSpan timeout);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, MessageQueueType *event, MessageQueueWaitType wait_type); void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, MessageQueueType *event, MessageQueueWaitType wait_type);
} }

View file

@ -23,7 +23,7 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableObjectList; class MultiWaitObjectList;
} }
@ -33,8 +33,8 @@ namespace ams::os {
State_Initialized = 1, State_Initialized = 1,
}; };
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist_not_full; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist_not_full;
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist_not_empty; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist_not_empty;
uintptr_t *buffer; uintptr_t *buffer;
s32 capacity; s32 capacity;
s32 count; s32 count;

View file

@ -14,6 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <stratosphere/os/os_waitable_types.hpp> #include <stratosphere/os/os_multiple_wait_types.hpp>
#include <stratosphere/os/os_waitable_api.hpp> #include <stratosphere/os/os_multiple_wait_api.hpp>
#include <stratosphere/os/os_waitable_utils.hpp> #include <stratosphere/os/os_multiple_wait_utils.hpp>

View file

@ -0,0 +1,45 @@
/*
* 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 <vapours.hpp>
#include <stratosphere/os/os_message_queue_common.hpp>
namespace ams::os {
struct MultiWaitHolderType;
struct MultiWaitType;
void InitializeMultiWait(MultiWaitType *multi_wait);
void FinalizeMultiWait(MultiWaitType *multi_wait);
MultiWaitHolderType *WaitAny(MultiWaitType *multi_wait);
MultiWaitHolderType *TryWaitAny(MultiWaitType *multi_wait);
MultiWaitHolderType *TimedWaitAny(MultiWaitType *multi_wait, TimeSpan timeout);
void FinalizeMultiWaitHolder(MultiWaitHolderType *holder);
void LinkMultiWaitHolder(MultiWaitType *multi_wait, MultiWaitHolderType *holder);
void UnlinkMultiWaitHolder(MultiWaitHolderType *holder);
void UnlinkAllMultiWaitHolder(MultiWaitType *multi_wait);
void MoveAllMultiWaitHolder(MultiWaitType *dst, MultiWaitType *src);
void SetMultiWaitHolderUserData(MultiWaitHolderType *holder, uintptr_t user_data);
uintptr_t GetMultiWaitHolderUserData(const MultiWaitHolderType *holder);
void InitializeMultiWaitHolder(MultiWaitHolderType *holder, Handle handle);
}

View file

@ -21,12 +21,12 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableManagerImpl; class MultiWaitImpl;
struct WaitableHolderImpl; struct MultiWaitHolderImpl;
} }
struct WaitableManagerType { struct MultiWaitType {
enum State { enum State {
State_NotInitialized, State_NotInitialized,
State_Initialized, State_Initialized,
@ -34,14 +34,14 @@ namespace ams::os {
u8 state; u8 state;
bool is_waiting; bool is_waiting;
util::TypedStorage<impl::WaitableManagerImpl, sizeof(util::IntrusiveListNode) + sizeof(impl::InternalCriticalSection) + 2 * sizeof(void *) + sizeof(Handle), alignof(void *)> impl_storage; util::TypedStorage<impl::MultiWaitImpl, sizeof(util::IntrusiveListNode) + sizeof(impl::InternalCriticalSection) + 2 * sizeof(void *) + sizeof(Handle), alignof(void *)> impl_storage;
}; };
static_assert(std::is_trivial<WaitableManagerType>::value); static_assert(std::is_trivial<MultiWaitType>::value);
struct WaitableHolderType { struct MultiWaitHolderType {
util::TypedStorage<impl::WaitableHolderImpl, 2 * sizeof(util::IntrusiveListNode) + 3 * sizeof(void *), alignof(void *)> impl_storage; util::TypedStorage<impl::MultiWaitHolderImpl, 2 * sizeof(util::IntrusiveListNode) + 3 * sizeof(void *), alignof(void *)> impl_storage;
uintptr_t user_data; uintptr_t user_data;
}; };
static_assert(std::is_trivial<WaitableHolderType>::value); static_assert(std::is_trivial<MultiWaitHolderType>::value);
} }

View file

@ -0,0 +1,124 @@
/*
* 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 <vapours.hpp>
#include <stratosphere/os/os_message_queue_common.hpp>
#include <stratosphere/os/os_multiple_wait_api.hpp>
#include <stratosphere/os/os_multiple_wait_types.hpp>
namespace ams::os {
namespace impl {
class AutoMultiWaitHolder {
private:
MultiWaitHolderType m_holder;
public:
template<typename T>
ALWAYS_INLINE explicit AutoMultiWaitHolder(MultiWaitType *multi_wait, T &&arg) {
InitializeMultiWaitHolder(std::addressof(m_holder), std::forward<T>(arg));
LinkMultiWaitHolder(multi_wait, std::addressof(m_holder));
}
ALWAYS_INLINE ~AutoMultiWaitHolder() {
UnlinkMultiWaitHolder(std::addressof(m_holder));
FinalizeMultiWaitHolder(std::addressof(m_holder));
}
ALWAYS_INLINE std::pair<MultiWaitHolderType *, int> ConvertResult(const std::pair<MultiWaitHolderType *, int> result, int index) {
if (result.first == std::addressof(m_holder)) {
return std::make_pair(static_cast<MultiWaitHolderType *>(nullptr), index);
} else {
return result;
}
}
};
template<typename F>
inline std::pair<MultiWaitHolderType *, int> WaitAnyImpl(F &&func, MultiWaitType *multi_wait, int) {
return std::pair<MultiWaitHolderType *, int>(func(multi_wait), -1);
}
template<typename F, typename T, typename... Args>
inline std::pair<MultiWaitHolderType *, int> WaitAnyImpl(F &&func, MultiWaitType *multi_wait, int index, T &&x, Args &&... args) {
AutoMultiWaitHolder holder(multi_wait, std::forward<T>(x));
return holder.ConvertResult(WaitAnyImpl(std::forward<F>(func), multi_wait, index + 1, std::forward<Args>(args)...), index);
}
template<typename F, typename... Args>
inline std::pair<MultiWaitHolderType *, int> WaitAnyImpl(F &&func, MultiWaitType *multi_wait, Args &&... args) {
return WaitAnyImpl(std::forward<F>(func), multi_wait, 0, std::forward<Args>(args)...);
}
class TempMultiWait {
private:
MultiWaitType m_multi_wait;
public:
ALWAYS_INLINE TempMultiWait() {
os::InitializeMultiWait(std::addressof(m_multi_wait));
}
ALWAYS_INLINE ~TempMultiWait() {
os::FinalizeMultiWait(std::addressof(m_multi_wait));
}
MultiWaitType *Get() {
return std::addressof(m_multi_wait);
}
};
template<typename F, typename... Args>
inline std::pair<MultiWaitHolderType *, int> WaitAnyImpl(F &&func, Args &&... args) {
TempMultiWait temp_multi_wait;
return WaitAnyImpl(std::forward<F>(func), temp_multi_wait.Get(), 0, std::forward<Args>(args)...);
}
using WaitAnyFunction = MultiWaitHolderType * (*)(MultiWaitType *);
class NotBoolButInt {
private:
int m_value;
public:
constexpr ALWAYS_INLINE NotBoolButInt(int v) : m_value(v) { /* ... */ }
constexpr ALWAYS_INLINE operator int() const { return m_value; }
explicit operator bool() const = delete;
};
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline std::pair<MultiWaitHolderType *, int> WaitAny(MultiWaitType *multi_wait, Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::WaitAny), multi_wait, std::forward<Args>(args)...);
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline int WaitAny(Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::WaitAny), std::forward<Args>(args)...).second;
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline std::pair<MultiWaitHolderType *, int> TryWaitAny(MultiWaitType *multi_wait, Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::TryWaitAny), multi_wait, std::forward<Args>(args)...);
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline impl::NotBoolButInt TryWaitAny(Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::TryWaitAny), std::forward<Args>(args)...).second;
}
}

View file

@ -18,9 +18,9 @@
namespace ams::os { namespace ams::os {
struct WaitableHolderType; struct MultiWaitHolderType;
struct WaitableManagerType; struct MultiWaitType;
Result SdkReplyAndReceive(os::WaitableHolderType **out, Handle reply_target, WaitableManagerType *manager); Result SdkReplyAndReceive(os::MultiWaitHolderType **out, Handle reply_target, MultiWaitType *multi_wait);
} }

View file

@ -20,7 +20,7 @@
namespace ams::os { namespace ams::os {
struct SemaphoreType; struct SemaphoreType;
struct WaitableHolderType; struct MultiWaitHolderType;
void InitializeSemaphore(SemaphoreType *sema, s32 count, s32 max_count); void InitializeSemaphore(SemaphoreType *sema, s32 count, s32 max_count);
void FinalizeSemaphore(SemaphoreType *sema); void FinalizeSemaphore(SemaphoreType *sema);
@ -34,6 +34,6 @@ namespace ams::os {
s32 GetCurrentSemaphoreCount(const SemaphoreType *sema); s32 GetCurrentSemaphoreCount(const SemaphoreType *sema);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, SemaphoreType *sema); void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, SemaphoreType *sema);
} }

View file

@ -23,7 +23,7 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableObjectList; class MultiWaitObjectList;
} }
@ -33,7 +33,7 @@ namespace ams::os {
State_Initialized = 1, State_Initialized = 1,
}; };
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist;
u8 state; u8 state;
s32 count; s32 count;
s32 max_count; s32 max_count;

View file

@ -21,7 +21,7 @@
namespace ams::os { namespace ams::os {
struct SystemEventType; struct SystemEventType;
struct WaitableHolderType; struct MultiWaitHolderType;
Result CreateSystemEvent(SystemEventType *event, EventClearMode clear_mode, bool inter_process); Result CreateSystemEvent(SystemEventType *event, EventClearMode clear_mode, bool inter_process);
void DestroySystemEvent(SystemEventType *event); void DestroySystemEvent(SystemEventType *event);
@ -42,6 +42,6 @@ namespace ams::os {
bool TimedWaitSystemEvent(SystemEventType *event, TimeSpan timeout); bool TimedWaitSystemEvent(SystemEventType *event, TimeSpan timeout);
void ClearSystemEvent(SystemEventType *event); void ClearSystemEvent(SystemEventType *event);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, SystemEventType *event); void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, SystemEventType *event);
} }

View file

@ -28,7 +28,7 @@ namespace ams::os {
State_Initialized = 1, State_Initialized = 1,
}; };
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitable_object_list_storage; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> multi_wait_object_list_storage;
bool auto_clear; bool auto_clear;
u8 state; u8 state;

View file

@ -21,7 +21,7 @@
namespace ams::os { namespace ams::os {
struct ThreadType; struct ThreadType;
struct WaitableHolderType; struct MultiWaitHolderType;
Result CreateThread(ThreadType *thread, ThreadFunction function, void *argument, void *stack, size_t stack_size, s32 priority, s32 ideal_core); Result CreateThread(ThreadType *thread, ThreadFunction function, void *argument, void *stack, size_t stack_size, s32 priority, s32 ideal_core);
Result CreateThread(ThreadType *thread, ThreadFunction function, void *argument, void *stack, size_t stack_size, s32 priority); Result CreateThread(ThreadType *thread, ThreadFunction function, void *argument, void *stack, size_t stack_size, s32 priority);
@ -62,6 +62,6 @@ namespace ams::os {
ThreadId GetThreadId(const ThreadType *thread); ThreadId GetThreadId(const ThreadType *thread);
void InitializeWaitableHolder(WaitableHolderType *holder, ThreadType *thread); void InitializeMultiWaitHolder(MultiWaitHolderType *holder, ThreadType *thread);
} }

View file

@ -26,7 +26,7 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableObjectList; class MultiWaitObjectList;
} }
@ -47,7 +47,7 @@ namespace ams::os {
}; };
util::TypedStorage<util::IntrusiveListNode> all_threads_node; util::TypedStorage<util::IntrusiveListNode> all_threads_node;
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitlist;
uintptr_t reserved[4]; uintptr_t reserved[4];
u8 state; u8 state;
u8 suspend_count; u8 suspend_count;

View file

@ -21,7 +21,7 @@
namespace ams::os { namespace ams::os {
struct TimerEventType; struct TimerEventType;
struct WaitableHolderType; struct MultiWaitHolderType;
void InitializeTimerEvent(TimerEventType *event, EventClearMode clear_mode); void InitializeTimerEvent(TimerEventType *event, EventClearMode clear_mode);
void FinalizeTimerEvent(TimerEventType *event); void FinalizeTimerEvent(TimerEventType *event);
@ -36,6 +36,6 @@ namespace ams::os {
void SignalTimerEvent(TimerEventType *event); void SignalTimerEvent(TimerEventType *event);
void ClearTimerEvent(TimerEventType *event); void ClearTimerEvent(TimerEventType *event);
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, TimerEventType *event); void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, TimerEventType *event);
} }

View file

@ -24,7 +24,7 @@ namespace ams::os {
namespace impl { namespace impl {
class WaitableObjectList; class MultiWaitObjectList;
} }
@ -42,7 +42,7 @@ namespace ams::os {
TimerState_Periodic = 2, TimerState_Periodic = 2,
}; };
util::TypedStorage<impl::WaitableObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> waitable_object_list_storage; util::TypedStorage<impl::MultiWaitObjectList, sizeof(util::IntrusiveListNode), alignof(util::IntrusiveListNode)> multi_wait_object_list_storage;
u8 state; u8 state;
u8 clear_mode; u8 clear_mode;

View file

@ -1,45 +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 <vapours.hpp>
#include <stratosphere/os/os_message_queue_common.hpp>
namespace ams::os {
struct WaitableHolderType;
struct WaitableManagerType;
void InitializeWaitableManager(WaitableManagerType *manager);
void FinalizeWaitableManager(WaitableManagerType *manager);
WaitableHolderType *WaitAny(WaitableManagerType *manager);
WaitableHolderType *TryWaitAny(WaitableManagerType *manager);
WaitableHolderType *TimedWaitAny(WaitableManagerType *manager, TimeSpan timeout);
void FinalizeWaitableHolder(WaitableHolderType *holder);
void LinkWaitableHolder(WaitableManagerType *manager, WaitableHolderType *holder);
void UnlinkWaitableHolder(WaitableHolderType *holder);
void UnlinkAllWaitableHolder(WaitableManagerType *manager);
void MoveAllWaitableHolder(WaitableManagerType *dst, WaitableManagerType *src);
void SetWaitableHolderUserData(WaitableHolderType *holder, uintptr_t user_data);
uintptr_t GetWaitableHolderUserData(const WaitableHolderType *holder);
void InitializeWaitableHolder(WaitableHolderType *holder, Handle handle);
}

View file

@ -1,124 +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 <vapours.hpp>
#include <stratosphere/os/os_message_queue_common.hpp>
#include <stratosphere/os/os_waitable_api.hpp>
#include <stratosphere/os/os_waitable_types.hpp>
namespace ams::os {
namespace impl {
class AutoWaitableHolder {
private:
WaitableHolderType m_holder;
public:
template<typename T>
ALWAYS_INLINE explicit AutoWaitableHolder(WaitableManagerType *manager, T &&arg) {
InitializeWaitableHolder(std::addressof(m_holder), std::forward<T>(arg));
LinkWaitableHolder(manager, std::addressof(m_holder));
}
ALWAYS_INLINE ~AutoWaitableHolder() {
UnlinkWaitableHolder(std::addressof(m_holder));
FinalizeWaitableHolder(std::addressof(m_holder));
}
ALWAYS_INLINE std::pair<WaitableHolderType *, int> ConvertResult(const std::pair<WaitableHolderType *, int> result, int index) {
if (result.first == std::addressof(m_holder)) {
return std::make_pair(static_cast<WaitableHolderType *>(nullptr), index);
} else {
return result;
}
}
};
template<typename F>
inline std::pair<WaitableHolderType *, int> WaitAnyImpl(F &&func, WaitableManagerType *manager, int) {
return std::pair<WaitableHolderType *, int>(func(manager), -1);
}
template<typename F, typename T, typename... Args>
inline std::pair<WaitableHolderType *, int> WaitAnyImpl(F &&func, WaitableManagerType *manager, int index, T &&x, Args &&... args) {
AutoWaitableHolder holder(manager, std::forward<T>(x));
return holder.ConvertResult(WaitAnyImpl(std::forward<F>(func), manager, index + 1, std::forward<Args>(args)...), index);
}
template<typename F, typename... Args>
inline std::pair<WaitableHolderType *, int> WaitAnyImpl(F &&func, WaitableManagerType *manager, Args &&... args) {
return WaitAnyImpl(std::forward<F>(func), manager, 0, std::forward<Args>(args)...);
}
class TempWaitableManager {
private:
WaitableManagerType m_manager;
public:
ALWAYS_INLINE TempWaitableManager() {
os::InitializeWaitableManager(std::addressof(m_manager));
}
ALWAYS_INLINE ~TempWaitableManager() {
os::FinalizeWaitableManager(std::addressof(m_manager));
}
WaitableManagerType *Get() {
return std::addressof(m_manager);
}
};
template<typename F, typename... Args>
inline std::pair<WaitableHolderType *, int> WaitAnyImpl(F &&func, Args &&... args) {
TempWaitableManager temp_manager;
return WaitAnyImpl(std::forward<F>(func), temp_manager.Get(), 0, std::forward<Args>(args)...);
}
using WaitAnyFunction = WaitableHolderType * (*)(WaitableManagerType *);
class NotBoolButInt {
private:
int m_value;
public:
constexpr ALWAYS_INLINE NotBoolButInt(int v) : m_value(v) { /* ... */ }
constexpr ALWAYS_INLINE operator int() const { return m_value; }
explicit operator bool() const = delete;
};
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline std::pair<WaitableHolderType *, int> WaitAny(WaitableManagerType *manager, Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::WaitAny), manager, std::forward<Args>(args)...);
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline int WaitAny(Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::WaitAny), std::forward<Args>(args)...).second;
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline std::pair<WaitableHolderType *, int> TryWaitAny(WaitableManagerType *manager, Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::TryWaitAny), manager, std::forward<Args>(args)...);
}
template<typename... Args> requires (sizeof...(Args) > 0)
inline impl::NotBoolButInt TryWaitAny(Args &&... args) {
return impl::WaitAnyImpl(static_cast<impl::WaitAnyFunction>(&::ams::os::TryWaitAny), std::forward<Args>(args)...).second;
}
}

View file

@ -28,8 +28,8 @@ namespace ams::sf::hipc {
NeedsRetry, NeedsRetry,
}; };
void AttachWaitableHolderForAccept(os::WaitableHolderType *holder, Handle port); void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, Handle port);
void AttachWaitableHolderForReply(os::WaitableHolderType *holder, Handle request); void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, Handle request);
Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer); Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer);
Result Receive(bool *out_closed, Handle session_handle, const cmif::PointerAndSize &message_buffer); Result Receive(bool *out_closed, Handle session_handle, const cmif::PointerAndSize &message_buffer);

View file

@ -47,7 +47,7 @@ namespace ams::sf::hipc {
using ServerDomainSessionManager::DomainEntryStorage; using ServerDomainSessionManager::DomainEntryStorage;
using ServerDomainSessionManager::DomainStorage; using ServerDomainSessionManager::DomainStorage;
protected: protected:
class Server : public os::WaitableHolderType { class Server : public os::MultiWaitHolderType {
friend class ServerManagerBase; friend class ServerManagerBase;
template<size_t, typename, size_t> template<size_t, typename, size_t>
friend class ServerManager; friend class ServerManager;
@ -73,42 +73,42 @@ namespace ams::sf::hipc {
} }
}; };
private: private:
/* Management of waitables. */ /* Multiple wait management. */
os::WaitableManagerType waitable_manager; os::MultiWaitType multi_wait;
os::Event request_stop_event; os::Event request_stop_event;
os::WaitableHolderType request_stop_event_holder; os::MultiWaitHolderType request_stop_event_holder;
os::Event notify_event; os::Event notify_event;
os::WaitableHolderType notify_event_holder; os::MultiWaitHolderType notify_event_holder;
os::SdkMutex waitable_selection_mutex; os::SdkMutex selection_mutex;
os::SdkMutex waitlist_mutex; os::SdkMutex deferred_list_mutex;
os::WaitableManagerType waitlist; os::MultiWaitType deferred_list;
private: private:
virtual void RegisterSessionToWaitList(ServerSession *session) override final; virtual void RegisterServerSessionToWait(ServerSession *session) override final;
void RegisterToWaitList(os::WaitableHolderType *holder); void LinkToDeferredList(os::MultiWaitHolderType *holder);
void ProcessWaitList(); void LinkDeferred();
bool WaitAndProcessImpl(); bool WaitAndProcessImpl();
Result ProcessForServer(os::WaitableHolderType *holder); Result ProcessForServer(os::MultiWaitHolderType *holder);
Result ProcessForMitmServer(os::WaitableHolderType *holder); Result ProcessForMitmServer(os::MultiWaitHolderType *holder);
Result ProcessForSession(os::WaitableHolderType *holder); Result ProcessForSession(os::MultiWaitHolderType *holder);
void RegisterServerImpl(Server *server, Handle port_handle, bool is_mitm_server) { void RegisterServerImpl(Server *server, Handle port_handle, bool is_mitm_server) {
server->port_handle = port_handle; server->port_handle = port_handle;
hipc::AttachWaitableHolderForAccept(server, port_handle); hipc::AttachMultiWaitHolderForAccept(server, port_handle);
server->is_mitm_server = is_mitm_server; server->is_mitm_server = is_mitm_server;
if (is_mitm_server) { if (is_mitm_server) {
/* Mitm server. */ /* Mitm server. */
os::SetWaitableHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer)); os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer));
} else { } else {
/* Non-mitm server. */ /* Non-mitm server. */
os::SetWaitableHolderUserData(server, static_cast<uintptr_t>(UserDataTag::Server)); os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::Server));
} }
os::LinkWaitableHolder(std::addressof(this->waitable_manager), server); os::LinkMultiWaitHolder(std::addressof(this->multi_wait), server);
} }
void RegisterServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, Handle port_handle, bool is_mitm_server) { void RegisterServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, Handle port_handle, bool is_mitm_server) {
@ -192,15 +192,16 @@ namespace ams::sf::hipc {
ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count) : ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count) :
ServerDomainSessionManager(entry_storage, entry_count), ServerDomainSessionManager(entry_storage, entry_count),
request_stop_event(os::EventClearMode_ManualClear), notify_event(os::EventClearMode_ManualClear), request_stop_event(os::EventClearMode_ManualClear), notify_event(os::EventClearMode_ManualClear),
waitable_selection_mutex(), waitlist_mutex() selection_mutex(), deferred_list_mutex()
{ {
/* Link waitables. */ /* Link multi-wait holders. */
os::InitializeWaitableManager(std::addressof(this->waitable_manager)); os::InitializeMultiWait(std::addressof(this->multi_wait));
os::InitializeWaitableHolder(std::addressof(this->request_stop_event_holder), this->request_stop_event.GetBase()); os::InitializeMultiWaitHolder(std::addressof(this->request_stop_event_holder), this->request_stop_event.GetBase());
os::LinkWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->request_stop_event_holder)); os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->request_stop_event_holder));
os::InitializeWaitableHolder(std::addressof(this->notify_event_holder), this->notify_event.GetBase()); os::InitializeMultiWaitHolder(std::addressof(this->notify_event_holder), this->notify_event.GetBase());
os::LinkWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->notify_event_holder)); os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->notify_event_holder));
os::InitializeWaitableManager(std::addressof(this->waitlist));
os::InitializeMultiWait(std::addressof(this->deferred_list));
} }
template<typename Interface> template<typename Interface>
@ -227,13 +228,13 @@ namespace ams::sf::hipc {
} }
/* Processing. */ /* Processing. */
os::WaitableHolderType *WaitSignaled(); os::MultiWaitHolderType *WaitSignaled();
void ResumeProcessing(); void ResumeProcessing();
void RequestStopProcessing(); void RequestStopProcessing();
void AddUserWaitableHolder(os::WaitableHolderType *waitable); void AddUserMultiWaitHolder(os::MultiWaitHolderType *holder);
Result Process(os::WaitableHolderType *waitable); Result Process(os::MultiWaitHolderType *holder);
void WaitAndProcess(); void WaitAndProcess();
void LoopProcess(); void LoopProcess();
}; };
@ -324,8 +325,8 @@ namespace ams::sf::hipc {
const size_t index = this->GetServerIndex(server); const size_t index = this->GetServerIndex(server);
AMS_ABORT_UNLESS(this->server_allocated[index]); AMS_ABORT_UNLESS(this->server_allocated[index]);
{ {
os::UnlinkWaitableHolder(server); os::UnlinkMultiWaitHolder(server);
os::FinalizeWaitableHolder(server); os::FinalizeMultiWaitHolder(server);
if (server->service_managed) { if (server->service_managed) {
if (server->is_mitm_server) { if (server->is_mitm_server) {
R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->service_name)); R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->service_name));

View file

@ -38,7 +38,7 @@ namespace ams::sf::hipc {
} }
class ServerSession : public os::WaitableHolderType { class ServerSession : public os::MultiWaitHolderType {
friend class ServerSessionManager; friend class ServerSessionManager;
friend class ServerManagerBase; friend class ServerManagerBase;
friend class impl::HipcManagerImpl; friend class impl::HipcManagerImpl;
@ -54,7 +54,7 @@ namespace ams::sf::hipc {
bool has_received; bool has_received;
public: public:
ServerSession(Handle h, cmif::ServiceObjectHolder &&obj) : srv_obj_holder(std::move(obj)), session_handle(h) { ServerSession(Handle h, cmif::ServiceObjectHolder &&obj) : srv_obj_holder(std::move(obj)), session_handle(h) {
hipc::AttachWaitableHolderForReply(this, h); hipc::AttachMultiWaitHolderForReply(this, h);
this->is_closed = false; this->is_closed = false;
this->has_received = false; this->has_received = false;
this->forward_service = nullptr; this->forward_service = nullptr;
@ -62,7 +62,7 @@ namespace ams::sf::hipc {
} }
ServerSession(Handle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : srv_obj_holder(std::move(obj)), session_handle(h) { ServerSession(Handle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : srv_obj_holder(std::move(obj)), session_handle(h) {
hipc::AttachWaitableHolderForReply(this, h); hipc::AttachMultiWaitHolderForReply(this, h);
this->is_closed = false; this->is_closed = false;
this->has_received = false; this->has_received = false;
this->forward_service = std::move(fsrv); this->forward_service = std::move(fsrv);
@ -105,7 +105,7 @@ namespace ams::sf::hipc {
void DestroySession(ServerSession *session); void DestroySession(ServerSession *session);
Result ProcessRequestImpl(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message); Result ProcessRequestImpl(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message);
virtual void RegisterSessionToWaitList(ServerSession *session) = 0; virtual void RegisterServerSessionToWait(ServerSession *session) = 0;
protected: protected:
Result DispatchRequest(cmif::ServiceObjectHolder &&obj, ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message); Result DispatchRequest(cmif::ServiceObjectHolder &&obj, ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message);
virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message); virtual Result DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message);

View file

@ -20,7 +20,7 @@
namespace ams::tipc { namespace ams::tipc {
class WaitableObject { class ObjectHolder {
public: public:
enum ObjectType : u8 { enum ObjectType : u8 {
ObjectType_Invalid = 0, ObjectType_Invalid = 0,
@ -44,7 +44,7 @@ namespace ams::tipc {
m_object = object; m_object = object;
} }
public: public:
constexpr inline WaitableObject() : m_handle(svc::InvalidHandle), m_type(ObjectType_Invalid), m_managed(false), m_object(nullptr) { /* ... */ } constexpr inline ObjectHolder() : m_handle(svc::InvalidHandle), m_type(ObjectType_Invalid), m_managed(false), m_object(nullptr) { /* ... */ }
void InitializeAsPort(svc::Handle handle) { void InitializeAsPort(svc::Handle handle) {
/* NOTE: Nintendo sets ports as managed, but this will cause a nullptr-deref if one is ever closed. */ /* NOTE: Nintendo sets ports as managed, but this will cause a nullptr-deref if one is ever closed. */

View file

@ -17,7 +17,7 @@
#include <vapours.hpp> #include <vapours.hpp>
#include <stratosphere/tipc/tipc_common.hpp> #include <stratosphere/tipc/tipc_common.hpp>
#include <stratosphere/tipc/tipc_service_object.hpp> #include <stratosphere/tipc/tipc_service_object.hpp>
#include <stratosphere/tipc/tipc_waitable_object.hpp> #include <stratosphere/tipc/tipc_object_holder.hpp>
namespace ams::tipc { namespace ams::tipc {
@ -28,14 +28,14 @@ namespace ams::tipc {
class ObjectManagerBase { class ObjectManagerBase {
protected: protected:
struct Entry { struct Entry {
util::TypedStorage<WaitableObject> object; util::TypedStorage<ObjectHolder> object;
os::WaitableHolderType waitable_holder; os::MultiWaitHolderType multi_wait_holder;
}; };
private: private:
os::SdkMutex m_mutex{}; os::SdkMutex m_mutex{};
Entry *m_entries_start{}; Entry *m_entries_start{};
Entry *m_entries_end{}; Entry *m_entries_end{};
os::WaitableManagerType *m_waitable_manager{}; os::MultiWaitType *m_multi_wait{};
private: private:
Entry *FindEntry(svc::Handle handle) { Entry *FindEntry(svc::Handle handle) {
for (Entry *cur = m_entries_start; cur != m_entries_end; ++cur) { for (Entry *cur = m_entries_start; cur != m_entries_end; ++cur) {
@ -46,9 +46,9 @@ namespace ams::tipc {
return nullptr; return nullptr;
} }
Entry *FindEntry(os::WaitableHolderType *holder) { Entry *FindEntry(os::MultiWaitHolderType *holder) {
for (Entry *cur = m_entries_start; cur != m_entries_end; ++cur) { for (Entry *cur = m_entries_start; cur != m_entries_end; ++cur) {
if (std::addressof(cur->waitable_holder) == holder) { if (std::addressof(cur->multi_wait_holder) == holder) {
return cur; return cur;
} }
} }
@ -57,9 +57,9 @@ namespace ams::tipc {
public: public:
constexpr ObjectManagerBase() = default; constexpr ObjectManagerBase() = default;
void InitializeImpl(os::WaitableManagerType *manager, Entry *entries, size_t max_objects) { void InitializeImpl(os::MultiWaitType *multi_wait, Entry *entries, size_t max_objects) {
/* Set our waitable manager. */ /* Set our multi wait. */
m_waitable_manager = manager; m_multi_wait = multi_wait;
/* Setup entry pointers. */ /* Setup entry pointers. */
m_entries_start = entries; m_entries_start = entries;
@ -71,7 +71,7 @@ namespace ams::tipc {
} }
} }
void AddObject(WaitableObject &object) { void AddObject(ObjectHolder &object) {
/* Lock ourselves. */ /* Lock ourselves. */
std::scoped_lock lk(m_mutex); std::scoped_lock lk(m_mutex);
@ -83,8 +83,8 @@ namespace ams::tipc {
GetReference(entry->object) = object; GetReference(entry->object) = object;
/* Setup the entry's holder. */ /* Setup the entry's holder. */
os::InitializeWaitableHolder(std::addressof(entry->waitable_holder), object.GetHandle()); os::InitializeMultiWaitHolder(std::addressof(entry->multi_wait_holder), object.GetHandle());
os::LinkWaitableHolder(m_waitable_manager, std::addressof(entry->waitable_holder)); os::LinkMultiWaitHolder(m_multi_wait, std::addressof(entry->multi_wait_holder));
} }
void CloseObject(svc::Handle handle) { void CloseObject(svc::Handle handle) {
@ -96,21 +96,21 @@ namespace ams::tipc {
AMS_ABORT_UNLESS(entry != nullptr); AMS_ABORT_UNLESS(entry != nullptr);
/* Finalize the entry's holder. */ /* Finalize the entry's holder. */
os::UnlinkWaitableHolder(std::addressof(entry->waitable_holder)); os::UnlinkMultiWaitHolder(std::addressof(entry->multi_wait_holder));
os::FinalizeWaitableHolder(std::addressof(entry->waitable_holder)); os::FinalizeMultiWaitHolder(std::addressof(entry->multi_wait_holder));
/* Destroy the object. */ /* Destroy the object. */
GetReference(entry->object).Destroy(); GetReference(entry->object).Destroy();
} }
Result ReplyAndReceive(os::WaitableHolderType **out_holder, WaitableObject *out_object, svc::Handle reply_target, os::WaitableManagerType *manager) { Result ReplyAndReceive(os::MultiWaitHolderType **out_holder, ObjectHolder *out_object, svc::Handle reply_target, os::MultiWaitType *multi_wait) {
/* Declare signaled holder for processing ahead of time. */ /* Declare signaled holder for processing ahead of time. */
os::WaitableHolderType *signaled_holder; os::MultiWaitHolderType *signaled_holder;
/* Reply and receive until we get a newly signaled target. */ /* Reply and receive until we get a newly signaled target. */
Result result = os::SdkReplyAndReceive(out_holder, reply_target, manager); Result result = os::SdkReplyAndReceive(out_holder, reply_target, multi_wait);
for (signaled_holder = *out_holder; signaled_holder == nullptr; signaled_holder = *out_holder) { for (signaled_holder = *out_holder; signaled_holder == nullptr; signaled_holder = *out_holder) {
result = os::SdkReplyAndReceive(out_holder, svc::InvalidHandle, manager); result = os::SdkReplyAndReceive(out_holder, svc::InvalidHandle, multi_wait);
} }
/* Find the entry matching the signaled holder. */ /* Find the entry matching the signaled holder. */
@ -140,7 +140,7 @@ namespace ams::tipc {
return ResultSuccess(); return ResultSuccess();
} }
Result ProcessRequest(WaitableObject &object) { Result ProcessRequest(ObjectHolder &object) {
/* Get the method id. */ /* Get the method id. */
const auto method_id = svc::ipc::MessageBuffer::MessageHeader(svc::ipc::MessageBuffer(svc::ipc::GetMessageBuffer())).GetTag(); const auto method_id = svc::ipc::MessageBuffer::MessageHeader(svc::ipc::MessageBuffer(svc::ipc::GetMessageBuffer())).GetTag();
@ -176,8 +176,8 @@ namespace ams::tipc {
public: public:
constexpr ObjectManager() = default; constexpr ObjectManager() = default;
void Initialize(os::WaitableManagerType *manager) { void Initialize(os::MultiWaitType *multi_wait) {
this->InitializeImpl(manager, m_entries_storage, MaxObjects); this->InitializeImpl(multi_wait, m_entries_storage, MaxObjects);
} }
}; };

View file

@ -36,7 +36,7 @@ namespace ams::tipc {
class PortManagerInterface { class PortManagerInterface {
public: public:
virtual Result ProcessRequest(WaitableObject &object) = 0; virtual Result ProcessRequest(ObjectHolder &object) = 0;
}; };
template<typename DeferralManagerType, size_t ThreadStackSize, typename... PortInfos> template<typename DeferralManagerType, size_t ThreadStackSize, typename... PortInfos>
@ -97,18 +97,18 @@ namespace ams::tipc {
s32 m_id; s32 m_id;
std::atomic<s32> m_num_sessions; std::atomic<s32> m_num_sessions;
s32 m_port_number; s32 m_port_number;
os::WaitableManagerType m_waitable_manager; os::MultiWaitType m_multi_wait;
DeferralManagerType m_deferral_manager; DeferralManagerType m_deferral_manager;
os::MessageQueueType m_message_queue; os::MessageQueueType m_message_queue;
os::WaitableHolderType m_message_queue_holder; os::MultiWaitHolderType m_message_queue_holder;
uintptr_t m_message_queue_storage[MaxSessions]; uintptr_t m_message_queue_storage[MaxSessions];
ObjectManagerBase *m_object_manager; ObjectManagerBase *m_object_manager;
ServerManagerImpl *m_server_manager; ServerManagerImpl *m_server_manager;
public: public:
PortManagerBase() : m_id(), m_num_sessions(), m_port_number(), m_waitable_manager(), m_deferral_manager(), m_message_queue(), m_message_queue_holder(), m_message_queue_storage(), m_object_manager(), m_server_manager() { PortManagerBase() : m_id(), m_num_sessions(), m_port_number(), m_multi_wait(), m_deferral_manager(), m_message_queue(), m_message_queue_holder(), m_message_queue_storage(), m_object_manager(), m_server_manager() {
/* Setup our message queue. */ /* Setup our message queue. */
os::InitializeMessageQueue(std::addressof(m_message_queue), m_message_queue_storage, util::size(m_message_queue_storage)); os::InitializeMessageQueue(std::addressof(m_message_queue), m_message_queue_storage, util::size(m_message_queue_storage));
os::InitializeWaitableHolder(std::addressof(m_message_queue_holder), std::addressof(m_message_queue), os::MessageQueueWaitType::ForNotEmpty); os::InitializeMultiWaitHolder(std::addressof(m_message_queue_holder), std::addressof(m_message_queue), os::MessageQueueWaitType::ForNotEmpty);
} }
constexpr s32 GetPortIndex() const { constexpr s32 GetPortIndex() const {
@ -133,9 +133,9 @@ namespace ams::tipc {
/* Reset our session count. */ /* Reset our session count. */
m_num_sessions = 0; m_num_sessions = 0;
/* Initialize our waitable manager. */ /* Initialize our multi wait. */
os::InitializeWaitableManager(std::addressof(m_waitable_manager)); os::InitializeMultiWait(std::addressof(m_multi_wait));
os::LinkWaitableHolder(std::addressof(m_waitable_manager), std::addressof(m_message_queue_holder)); os::LinkMultiWaitHolder(std::addressof(m_multi_wait), std::addressof(m_message_queue_holder));
/* Initialize our object manager. */ /* Initialize our object manager. */
m_object_manager = manager; m_object_manager = manager;
@ -145,8 +145,8 @@ namespace ams::tipc {
/* Set our port number. */ /* Set our port number. */
this->m_port_number = index; this->m_port_number = index;
/* Create a waitable object for the port. */ /* Create an object holder for the port. */
tipc::WaitableObject object; tipc::ObjectHolder object;
/* Setup the object. */ /* Setup the object. */
object.InitializeAsPort(port_handle); object.InitializeAsPort(port_handle);
@ -155,7 +155,7 @@ namespace ams::tipc {
m_object_manager->AddObject(object); m_object_manager->AddObject(object);
} }
virtual Result ProcessRequest(WaitableObject &object) override { virtual Result ProcessRequest(ObjectHolder &object) override {
/* Process the request, this must succeed because we succeeded when deferring earlier. */ /* Process the request, this must succeed because we succeeded when deferring earlier. */
R_ABORT_UNLESS(m_object_manager->ProcessRequest(object)); R_ABORT_UNLESS(m_object_manager->ProcessRequest(object));
@ -168,13 +168,13 @@ namespace ams::tipc {
return m_object_manager->Reply(object.GetHandle()); return m_object_manager->Reply(object.GetHandle());
} }
Result ReplyAndReceive(os::WaitableHolderType **out_holder, WaitableObject *out_object, svc::Handle reply_target) { Result ReplyAndReceive(os::MultiWaitHolderType **out_holder, ObjectHolder *out_object, svc::Handle reply_target) {
return m_object_manager->ReplyAndReceive(out_holder, out_object, reply_target, std::addressof(m_waitable_manager)); return m_object_manager->ReplyAndReceive(out_holder, out_object, reply_target, std::addressof(m_multi_wait));
} }
void AddSession(svc::Handle session_handle, tipc::ServiceObjectBase *service_object) { void AddSession(svc::Handle session_handle, tipc::ServiceObjectBase *service_object) {
/* Create a waitable object for the session. */ /* Create an object holder for the session. */
tipc::WaitableObject object; tipc::ObjectHolder object;
/* Setup the object. */ /* Setup the object. */
object.InitializeAsSession(session_handle, true, service_object); object.InitializeAsSession(session_handle, true, service_object);
@ -219,7 +219,7 @@ namespace ams::tipc {
} }
} }
void CloseSession(WaitableObject &object) { void CloseSession(ObjectHolder &object) {
/* Get the object's handle. */ /* Get the object's handle. */
const auto handle = object.GetHandle(); const auto handle = object.GetHandle();
@ -233,7 +233,7 @@ namespace ams::tipc {
--m_num_sessions; --m_num_sessions;
} }
void CloseSessionIfNecessary(WaitableObject &object, bool necessary) { void CloseSessionIfNecessary(ObjectHolder &object, bool necessary) {
if (necessary) { if (necessary) {
/* Get the object's handle. */ /* Get the object's handle. */
const auto handle = object.GetHandle(); const auto handle = object.GetHandle();
@ -261,7 +261,7 @@ namespace ams::tipc {
} }
} }
void ProcessRegisterRetry(WaitableObject &object) { void ProcessRegisterRetry(ObjectHolder &object) {
if constexpr (IsDeferralSupported) { if constexpr (IsDeferralSupported) {
/* Acquire exclusive server manager access. */ /* Acquire exclusive server manager access. */
std::scoped_lock lk(m_server_manager->GetMutex()); std::scoped_lock lk(m_server_manager->GetMutex());
@ -342,7 +342,7 @@ namespace ams::tipc {
this->InitializeBase(id, sm, std::addressof(m_object_manager_impl)); this->InitializeBase(id, sm, std::addressof(m_object_manager_impl));
/* Initialize our object manager. */ /* Initialize our object manager. */
m_object_manager_impl.Initialize(std::addressof(this->m_waitable_manager)); m_object_manager_impl.Initialize(std::addressof(this->m_multi_wait));
} }
}; };
@ -517,8 +517,8 @@ namespace ams::tipc {
svc::Handle reply_target = svc::InvalidHandle; svc::Handle reply_target = svc::InvalidHandle;
while (true) { while (true) {
/* Reply to our pending request, and receive a new one. */ /* Reply to our pending request, and receive a new one. */
os::WaitableHolderType *signaled_holder = nullptr; os::MultiWaitHolderType *signaled_holder = nullptr;
tipc::WaitableObject signaled_object{}; tipc::ObjectHolder signaled_object{};
R_TRY_CATCH(port_manager.ReplyAndReceive(std::addressof(signaled_holder), std::addressof(signaled_object), reply_target)) { R_TRY_CATCH(port_manager.ReplyAndReceive(std::addressof(signaled_holder), std::addressof(signaled_object), reply_target)) {
R_CATCH(os::ResultSessionClosedForReceive, os::ResultReceiveListBroken) { R_CATCH(os::ResultSessionClosedForReceive, os::ResultReceiveListBroken) {
/* Close the object and continue. */ /* Close the object and continue. */
@ -533,7 +533,7 @@ namespace ams::tipc {
if (signaled_holder == nullptr) { if (signaled_holder == nullptr) {
/* A session was signaled, accessible via signaled_object. */ /* A session was signaled, accessible via signaled_object. */
switch (signaled_object.GetType()) { switch (signaled_object.GetType()) {
case WaitableObject::ObjectType_Port: case ObjectHolder::ObjectType_Port:
{ {
/* Try to accept a new session */ /* Try to accept a new session */
svc::Handle session_handle; svc::Handle session_handle;
@ -545,7 +545,7 @@ namespace ams::tipc {
reply_target = svc::InvalidHandle; reply_target = svc::InvalidHandle;
} }
break; break;
case WaitableObject::ObjectType_Session: case ObjectHolder::ObjectType_Session:
{ {
/* Process the request */ /* Process the request */
const Result process_result = port_manager.GetObjectManager()->ProcessRequest(signaled_object); const Result process_result = port_manager.GetObjectManager()->ProcessRequest(signaled_object);

View file

@ -42,10 +42,10 @@ namespace ams::ddsf {
return; return;
} }
/* Initialize waitable manager/holder. */ /* Initialize multi wait/holder. */
os::InitializeWaitableManager(std::addressof(this->waitable_manager)); os::InitializeMultiWait(std::addressof(this->multi_wait));
os::InitializeWaitableHolder(std::addressof(this->loop_control_event_holder), this->loop_control_event.GetBase()); os::InitializeMultiWaitHolder(std::addressof(this->loop_control_event_holder), this->loop_control_event.GetBase());
os::LinkWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->loop_control_event_holder)); os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->loop_control_event_holder));
this->is_initialized = true; this->is_initialized = true;
} }
@ -58,10 +58,10 @@ namespace ams::ddsf {
return; return;
} }
/* Finalize waitable manager/holder. */ /* Finalize multi wait/holder. */
os::UnlinkWaitableHolder(std::addressof(this->loop_control_event_holder)); os::UnlinkMultiWaitHolder(std::addressof(this->loop_control_event_holder));
os::FinalizeWaitableHolder(std::addressof(this->loop_control_event_holder)); os::FinalizeMultiWaitHolder(std::addressof(this->loop_control_event_holder));
os::FinalizeWaitableManager(std::addressof(this->waitable_manager)); os::FinalizeMultiWait(std::addressof(this->multi_wait));
this->is_initialized = false; this->is_initialized = false;
} }
@ -94,7 +94,7 @@ namespace ams::ddsf {
/* Process the command. */ /* Process the command. */
switch (params->command) { switch (params->command) {
case LoopControlCommand::Register: case LoopControlCommand::Register:
params->target->Link(std::addressof(this->waitable_manager)); params->target->Link(std::addressof(this->multi_wait));
break; break;
case LoopControlCommand::Unregister: case LoopControlCommand::Unregister:
params->target->Unlink(); params->target->Unlink();
@ -180,7 +180,7 @@ namespace ams::ddsf {
bool should_terminate = false; bool should_terminate = false;
while (!should_terminate) { while (!should_terminate) {
/* Wait for a holder to be signaled. */ /* Wait for a holder to be signaled. */
os::WaitableHolderType *event_holder = os::WaitAny(std::addressof(this->waitable_manager)); os::MultiWaitHolderType *event_holder = os::WaitAny(std::addressof(this->multi_wait));
AMS_ASSERT(event_holder != nullptr); AMS_ASSERT(event_holder != nullptr);
/* Check if we have a request to handle. */ /* Check if we have a request to handle. */

View file

@ -97,13 +97,13 @@ namespace ams::erpt::srv {
psc::PmModule pm_module; psc::PmModule pm_module;
psc::PmState pm_state; psc::PmState pm_state;
psc::PmFlagSet pm_flags; psc::PmFlagSet pm_flags;
os::WaitableHolderType module_event_holder; os::MultiWaitHolderType module_event_holder;
R_ABORT_UNLESS(pm_module.Initialize(psc::PmModuleId_Erpt, dependencies, util::size(dependencies), os::EventClearMode_ManualClear)); R_ABORT_UNLESS(pm_module.Initialize(psc::PmModuleId_Erpt, dependencies, util::size(dependencies), os::EventClearMode_ManualClear));
os::InitializeWaitableHolder(std::addressof(module_event_holder), pm_module.GetEventPointer()->GetBase()); os::InitializeMultiWaitHolder(std::addressof(module_event_holder), pm_module.GetEventPointer()->GetBase());
os::SetWaitableHolderUserData(std::addressof(module_event_holder), static_cast<uintptr_t>(psc::PmModuleId_Erpt)); os::SetMultiWaitHolderUserData(std::addressof(module_event_holder), static_cast<uintptr_t>(psc::PmModuleId_Erpt));
this->AddUserWaitableHolder(std::addressof(module_event_holder)); this->AddUserMultiWaitHolder(std::addressof(module_event_holder));
while (true) { while (true) {
/* NOTE: Nintendo checks the user holder data to determine what's signaled, we will prefer to just check the address. */ /* NOTE: Nintendo checks the user holder data to determine what's signaled, we will prefer to just check the address. */
@ -131,7 +131,7 @@ namespace ams::erpt::srv {
} else { } else {
AMS_ASSERT(false); AMS_ASSERT(false);
} }
this->AddUserWaitableHolder(signaled_holder); this->AddUserMultiWaitHolder(signaled_holder);
} }
} }
} }

View file

@ -276,22 +276,22 @@ namespace ams::htclow::driver {
/* Get the state change event. */ /* Get the state change event. */
os::SystemEventType *state_change_event = g_ds_client.GetStateChangeEvent(); os::SystemEventType *state_change_event = g_ds_client.GetStateChangeEvent();
/* Setup waitable manager. */ /* Setup multi wait. */
os::WaitableManagerType manager; os::MultiWaitType multi_wait;
os::InitializeWaitableManager(std::addressof(manager)); os::InitializeMultiWait(std::addressof(multi_wait));
/* Link waitable holders. */ /* Link multi wait holders. */
os::WaitableHolderType state_change_holder; os::MultiWaitHolderType state_change_holder;
os::WaitableHolderType break_holder; os::MultiWaitHolderType break_holder;
os::InitializeWaitableHolder(std::addressof(state_change_holder), state_change_event); os::InitializeMultiWaitHolder(std::addressof(state_change_holder), state_change_event);
os::LinkWaitableHolder(std::addressof(manager), std::addressof(state_change_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(state_change_holder));
os::InitializeWaitableHolder(std::addressof(break_holder), g_usb_break_event.GetBase()); os::InitializeMultiWaitHolder(std::addressof(break_holder), g_usb_break_event.GetBase());
os::LinkWaitableHolder(std::addressof(manager), std::addressof(break_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(break_holder));
/* Loop forever. */ /* Loop forever. */
while (true) { while (true) {
/* If we should break, do so. */ /* If we should break, do so. */
if (os::WaitAny(std::addressof(manager)) == std::addressof(break_holder)) { if (os::WaitAny(std::addressof(multi_wait)) == std::addressof(break_holder)) {
break; break;
} }
@ -320,12 +320,12 @@ namespace ams::htclow::driver {
g_usb_break_event.Clear(); g_usb_break_event.Clear();
/* Unlink all holders. */ /* Unlink all holders. */
os::UnlinkAllWaitableHolder(std::addressof(manager)); os::UnlinkAllMultiWaitHolder(std::addressof(multi_wait));
/* Finalize the waitable holders and manager. */ /* Finalize the multi wait/holders. */
os::FinalizeWaitableHolder(std::addressof(break_holder)); os::FinalizeMultiWaitHolder(std::addressof(break_holder));
os::FinalizeWaitableHolder(std::addressof(state_change_holder)); os::FinalizeMultiWaitHolder(std::addressof(state_change_holder));
os::FinalizeWaitableManager(std::addressof(manager)); os::FinalizeMultiWait(std::addressof(multi_wait));
} }
} }

View file

@ -42,7 +42,7 @@ namespace ams::lm::srv {
constinit util::TypedStorage<psc::PmModule> g_pm_module_storage; constinit util::TypedStorage<psc::PmModule> g_pm_module_storage;
constinit psc::PmModule *g_pm_module; constinit psc::PmModule *g_pm_module;
constinit os::WaitableHolderType g_pm_module_holder; constinit os::MultiWaitHolderType g_pm_module_holder;
constexpr const psc::PmModuleId PmModuleDependencies[] = { psc::PmModuleId_TmaHostIo, psc::PmModuleId_Fs }; constexpr const psc::PmModuleId PmModuleDependencies[] = { psc::PmModuleId_TmaHostIo, psc::PmModuleId_Fs };
@ -67,15 +67,15 @@ namespace ams::lm::srv {
g_pm_module = util::ConstructAt(g_pm_module_storage); g_pm_module = util::ConstructAt(g_pm_module_storage);
R_ABORT_UNLESS(g_pm_module->Initialize(psc::PmModuleId_Lm, PmModuleDependencies, util::size(PmModuleDependencies), os::EventClearMode_ManualClear)); R_ABORT_UNLESS(g_pm_module->Initialize(psc::PmModuleId_Lm, PmModuleDependencies, util::size(PmModuleDependencies), os::EventClearMode_ManualClear));
/* Create the psc module waitable holder. */ /* Create the psc module multi wait holder. */
os::InitializeWaitableHolder(std::addressof(g_pm_module_holder), g_pm_module->GetEventPointer()->GetBase()); os::InitializeMultiWaitHolder(std::addressof(g_pm_module_holder), g_pm_module->GetEventPointer()->GetBase());
os::SetWaitableHolderUserData(std::addressof(g_pm_module_holder), psc::PmModuleId_Lm); os::SetMultiWaitHolderUserData(std::addressof(g_pm_module_holder), psc::PmModuleId_Lm);
/* Create the server manager. */ /* Create the server manager. */
g_server_manager = util::ConstructAt(g_server_manager_storage); g_server_manager = util::ConstructAt(g_server_manager_storage);
/* Add the pm module holder. */ /* Add the pm module holder. */
g_server_manager->AddUserWaitableHolder(std::addressof(g_pm_module_holder)); g_server_manager->AddUserMultiWaitHolder(std::addressof(g_pm_module_holder));
/* Create services. */ /* Create services. */
R_ABORT_UNLESS(g_server_manager->RegisterObjectForServer(g_log_service_object.GetShared(), LogServiceName, LogSessionCountMax)); R_ABORT_UNLESS(g_server_manager->RegisterObjectForServer(g_log_service_object.GetShared(), LogServiceName, LogSessionCountMax));
@ -100,7 +100,7 @@ namespace ams::lm::srv {
} else { } else {
/* If pm module, clear the event. */ /* If pm module, clear the event. */
g_pm_module->GetEventPointer()->Clear(); g_pm_module->GetEventPointer()->Clear();
g_server_manager->AddUserWaitableHolder(signaled_holder); g_server_manager->AddUserMultiWaitHolder(signaled_holder);
/* Get the power state. */ /* Get the power state. */
psc::PmState pm_state; psc::PmState pm_state;

View file

@ -16,7 +16,7 @@
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "os_inter_process_event.hpp" #include "os_inter_process_event.hpp"
#include "os_inter_process_event_impl.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 { namespace ams::os::impl {
@ -33,7 +33,7 @@ namespace ams::os::impl {
event->auto_clear = (clear_mode == EventClearMode_AutoClear); event->auto_clear = (clear_mode == EventClearMode_AutoClear);
/* Create the waitlist node. */ /* Create the waitlist node. */
util::ConstructAt(event->waitable_object_list_storage); util::ConstructAt(event->multi_wait_object_list_storage);
/* Set state. */ /* Set state. */
event->state = InterProcessEventType::State_Initialized; event->state = InterProcessEventType::State_Initialized;
@ -71,7 +71,7 @@ namespace ams::os::impl {
} }
/* Destroy the waitlist. */ /* 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) { 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 GetReadableHandleOfInterProcessEvent(const InterProcessEventType *event);
Handle GetWritableHandleOfInterProcessEvent(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 { namespace ams::os::impl {
class WaitableObjectList; class MultiWaitObjectList;
class WaitableManagerImpl; class MultiWaitImpl;
class WaitableHolderBase { class MultiWaitHolderBase {
private: private:
WaitableManagerImpl *manager = nullptr; MultiWaitImpl *multi_wait = nullptr;
public: public:
util::IntrusiveListNode manager_node; util::IntrusiveListNode multi_wait_node;
util::IntrusiveListNode object_list_node; util::IntrusiveListNode object_list_node;
public: public:
/* Gets whether the held waitable is currently signaled. */ /* Gets whether the held object is currently signaled. */
virtual TriBool IsSignaled() const = 0; 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; virtual TriBool LinkToObjectList() = 0;
/* Removes from the manager's object list. */ /* Removes from the multi wait's object list. */
virtual void UnlinkFromObjectList() = 0; virtual void UnlinkFromObjectList() = 0;
/* Gets handle to output, returns INVALID_HANDLE on failure. */ /* Gets handle to output, returns INVALID_HANDLE on failure. */
virtual Handle GetHandle() const = 0; virtual Handle GetHandle() const = 0;
@ -41,21 +41,21 @@ namespace ams::os::impl {
return TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()); return TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max());
} }
/* Interface with manager. */ /* Interface with multi wait. */
void SetManager(WaitableManagerImpl *m) { void SetMultiWait(MultiWaitImpl *m) {
this->manager = m; this->multi_wait = m;
} }
WaitableManagerImpl *GetManager() const { MultiWaitImpl *GetMultiWait() const {
return this->manager; return this->multi_wait;
} }
bool IsLinkedToManager() const { bool IsLinked() const {
return this->manager != nullptr; return this->multi_wait != nullptr;
} }
}; };
class WaitableHolderOfUserObject : public WaitableHolderBase { class MultiWaitHolderOfUserObject : public MultiWaitHolderBase {
public: public:
/* All user objects have no handle to wait on. */ /* All user objects have no handle to wait on. */
virtual Handle GetHandle() const override final { virtual Handle GetHandle() const override final {
@ -63,7 +63,7 @@ namespace ams::os::impl {
} }
}; };
class WaitableHolderOfKernelObject : public WaitableHolderBase { class MultiWaitHolderOfKernelObject : public MultiWaitHolderBase {
public: public:
/* All kernel objects have native handles, and thus don't have object list semantics. */ /* All kernel objects have native handles, and thus don't have object list semantics. */
virtual TriBool LinkToObjectList() override final { 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#include "os_waitable_object_list.hpp" #include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl { namespace ams::os::impl {
class WaitableHolderOfEvent : public WaitableHolderOfUserObject { class MultiWaitHolderOfEvent : public MultiWaitHolderOfUserObject {
private: private:
EventType *event; EventType *event;
private: private:
@ -27,7 +27,7 @@ namespace ams::os::impl {
return this->event->signaled ? TriBool::True : TriBool::False; return this->event->signaled ? TriBool::True : TriBool::False;
} }
public: public:
explicit WaitableHolderOfEvent(EventType *e) : event(e) { /* ... */ } explicit MultiWaitHolderOfEvent(EventType *e) : event(e) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */ /* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override { virtual TriBool IsSignaled() const override {
@ -38,14 +38,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override { virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_event)); 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(); return this->IsSignaledImpl();
} }
virtual void UnlinkFromObjectList() override { virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_event)); 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
namespace ams::os::impl { namespace ams::os::impl {
class WaitableHolderOfHandle : public WaitableHolderOfKernelObject { class MultiWaitHolderOfHandle : public MultiWaitHolderOfKernelObject {
private: private:
Handle handle; Handle handle;
public: public:
explicit WaitableHolderOfHandle(Handle h) : handle(h) { /* ... */ } explicit MultiWaitHolderOfHandle(Handle h) : handle(h) { /* ... */ }
/* IsSignaled, GetHandle both implemented. */ /* IsSignaled, GetHandle both implemented. */
virtual TriBool IsSignaled() const override { virtual TriBool IsSignaled() const override {

View file

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

View file

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

View file

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

View file

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

View file

@ -14,12 +14,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#include "os_waitable_object_list.hpp" #include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl { namespace ams::os::impl {
class WaitableHolderOfSemaphore : public WaitableHolderOfUserObject { class MultiWaitHolderOfSemaphore : public MultiWaitHolderOfUserObject {
private: private:
SemaphoreType *semaphore; SemaphoreType *semaphore;
private: private:
@ -27,7 +27,7 @@ namespace ams::os::impl {
return this->semaphore->count > 0 ? TriBool::True : TriBool::False; return this->semaphore->count > 0 ? TriBool::True : TriBool::False;
} }
public: public:
explicit WaitableHolderOfSemaphore(SemaphoreType *s) : semaphore(s) { /* ... */ } explicit MultiWaitHolderOfSemaphore(SemaphoreType *s) : semaphore(s) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */ /* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override { virtual TriBool IsSignaled() const override {
@ -38,14 +38,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override { virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->semaphore->cs_sema)); std::scoped_lock lk(GetReference(this->semaphore->cs_sema));
GetReference(this->semaphore->waitlist).LinkWaitableHolder(*this); GetReference(this->semaphore->waitlist).LinkMultiWaitHolder(*this);
return this->IsSignaledImpl(); return this->IsSignaledImpl();
} }
virtual void UnlinkFromObjectList() override { virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->semaphore->cs_sema)); 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
namespace ams::os::impl { namespace ams::os::impl {
class WaitableHolderOfThread : public WaitableHolderOfUserObject { class MultiWaitHolderOfThread : public MultiWaitHolderOfUserObject {
private: private:
ThreadType *thread; ThreadType *thread;
private: private:
@ -26,7 +26,7 @@ namespace ams::os::impl {
return this->thread->state == ThreadType::State_Terminated ? TriBool::True : TriBool::False; return this->thread->state == ThreadType::State_Terminated ? TriBool::True : TriBool::False;
} }
public: public:
explicit WaitableHolderOfThread(ThreadType *t) : thread(t) { /* ... */ } explicit MultiWaitHolderOfThread(ThreadType *t) : thread(t) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */ /* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override { virtual TriBool IsSignaled() const override {
@ -37,14 +37,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override { virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->thread->cs_thread)); std::scoped_lock lk(GetReference(this->thread->cs_thread));
GetReference(this->thread->waitlist).LinkWaitableHolder(*this); GetReference(this->thread->waitlist).LinkMultiWaitHolder(*this);
return this->IsSignaledImpl(); return this->IsSignaledImpl();
} }
virtual void UnlinkFromObjectList() override { virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->thread->cs_thread)); 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 #pragma once
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "os_timer_event_helper.hpp" #include "os_timer_event_helper.hpp"
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#include "os_waitable_object_list.hpp" #include "os_multiple_wait_object_list.hpp"
namespace ams::os::impl { namespace ams::os::impl {
class WaitableHolderOfTimerEvent : public WaitableHolderOfUserObject { class MultiWaitHolderOfTimerEvent : public MultiWaitHolderOfUserObject {
private: private:
TimerEventType *event; TimerEventType *event;
private: private:
TriBool IsSignaledImpl() const { TriBool IsSignaledImpl() const {
TimeSpan cur_time = this->GetManager()->GetCurrentTime(); TimeSpan cur_time = this->GetMultiWait()->GetCurrentTime();
UpdateSignalStateAndRecalculateNextTimeToWakeupUnsafe(this->event, cur_time); UpdateSignalStateAndRecalculateNextTimeToWakeupUnsafe(this->event, cur_time);
return this->event->signaled ? TriBool::True : TriBool::False; return this->event->signaled ? TriBool::True : TriBool::False;
} }
public: public:
explicit WaitableHolderOfTimerEvent(TimerEventType *e) : event(e) { /* ... */ } explicit MultiWaitHolderOfTimerEvent(TimerEventType *e) : event(e) { /* ... */ }
/* IsSignaled, Link, Unlink implemented. */ /* IsSignaled, Link, Unlink implemented. */
virtual TriBool IsSignaled() const override { virtual TriBool IsSignaled() const override {
@ -42,14 +42,14 @@ namespace ams::os::impl {
virtual TriBool LinkToObjectList() override { virtual TriBool LinkToObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_timer_event)); 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(); return this->IsSignaledImpl();
} }
virtual void UnlinkFromObjectList() override { virtual void UnlinkFromObjectList() override {
std::scoped_lock lk(GetReference(this->event->cs_timer_event)); 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. */ /* 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "os_waitable_manager_impl.hpp" #include "os_multiple_wait_impl.hpp"
#include "os_waitable_object_list.hpp" #include "os_multiple_wait_object_list.hpp"
#include "os_tick_manager.hpp" #include "os_tick_manager.hpp"
namespace ams::os::impl { 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. */ /* Prepare for processing. */
this->signaled_holder = nullptr; this->signaled_holder = nullptr;
this->target_impl.SetCurrentThreadHandleForCancelWait(); this->target_impl.SetCurrentThreadHandleForCancelWait();
WaitableHolderBase *holder = this->LinkHoldersToObjectList(); MultiWaitHolderBase *holder = this->LinkHoldersToObjectList();
/* Check if we've been signaled. */ /* Check if we've been signaled. */
{ {
@ -59,9 +59,9 @@ namespace ams::os::impl {
return wait_result; 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]; Handle object_handles[MaximumHandleCount];
WaitableHolderBase *objects[MaximumHandleCount]; MultiWaitHolderBase *objects[MaximumHandleCount];
const s32 count = this->BuildHandleArray(object_handles, 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; 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(); this->current_time = GetCurrentTick().ToTimeSpan();
TimeSpan min_timeout = 0; 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; s32 index = WaitInvalid;
Result wait_result = ResultSuccess(); Result wait_result = ResultSuccess();
@ -129,16 +129,17 @@ namespace ams::os::impl {
*out = objects[index]; *out = objects[index];
return wait_result; return wait_result;
} }
break;
} }
reply_target = svc::InvalidHandle; 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; 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) { if (Handle handle = holder_base.GetHandle(); handle != svc::InvalidHandle) {
AMS_ASSERT(count < num); AMS_ASSERT(count < num);
@ -151,10 +152,10 @@ namespace ams::os::impl {
return count; return count;
} }
WaitableHolderBase *WaitableManagerImpl::LinkHoldersToObjectList() { MultiWaitHolderBase *MultiWaitImpl::LinkHoldersToObjectList() {
WaitableHolderBase *signaled_holder = nullptr; 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(); TriBool is_signaled = holder_base.LinkToObjectList();
if (signaled_holder == nullptr && is_signaled == TriBool::True) { if (signaled_holder == nullptr && is_signaled == TriBool::True) {
@ -165,17 +166,17 @@ namespace ams::os::impl {
return signaled_holder; return signaled_holder;
} }
void WaitableManagerImpl::UnlinkHoldersFromObjectList() { void MultiWaitImpl::UnlinkHoldersFromObjectList() {
for (WaitableHolderBase &holder_base : this->waitable_list) { for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
holder_base.UnlinkFromObjectList(); holder_base.UnlinkFromObjectList();
} }
} }
WaitableHolderBase *WaitableManagerImpl::RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time) { MultiWaitHolderBase *MultiWaitImpl::RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time) {
WaitableHolderBase *min_timeout_holder = nullptr; MultiWaitHolderBase *min_timeout_holder = nullptr;
TimeSpan min_time = end_time; 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) { if (const TimeSpan cur_time = holder_base.GetAbsoluteWakeupTime(); cur_time < min_time) {
min_timeout_holder = &holder_base; min_timeout_holder = &holder_base;
min_time = cur_time; min_time = cur_time;
@ -190,7 +191,7 @@ namespace ams::os::impl {
return min_timeout_holder; return min_timeout_holder;
} }
void WaitableManagerImpl::SignalAndWakeupThread(WaitableHolderBase *holder_base) { void MultiWaitImpl::SignalAndWakeupThread(MultiWaitHolderBase *holder_base) {
std::scoped_lock lk(this->cs_wait); std::scoped_lock lk(this->cs_wait);
if (this->signaled_holder == nullptr) { if (this->signaled_holder == nullptr) {

View file

@ -14,41 +14,41 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#if defined(ATMOSPHERE_OS_HORIZON) #if defined(ATMOSPHERE_OS_HORIZON)
#include "os_waitable_manager_target_impl.os.horizon.hpp" #include "os_multiple_wait_target_impl.os.horizon.hpp"
#else #else
#error "Unknown OS for ams::os::WaitableManagerTargetImpl" #error "Unknown OS for ams::os::MultiWaitTargetImpl"
#endif #endif
namespace ams::os::impl { namespace ams::os::impl {
class WaitableManagerImpl { class MultiWaitImpl {
public: public:
static constexpr size_t MaximumHandleCount = WaitableManagerTargetImpl::MaximumHandleCount; static constexpr size_t MaximumHandleCount = MultiWaitTargetImpl::MaximumHandleCount;
static constexpr s32 WaitInvalid = -3; static constexpr s32 WaitInvalid = -3;
static constexpr s32 WaitCancelled = -2; static constexpr s32 WaitCancelled = -2;
static constexpr s32 WaitTimedOut = -1; static constexpr s32 WaitTimedOut = -1;
using ListType = util::IntrusiveListMemberTraits<&WaitableHolderBase::manager_node>::ListType; using MultiWaitList = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::multi_wait_node>::ListType;
private: private:
ListType waitable_list; MultiWaitList multi_wait_list;
WaitableHolderBase *signaled_holder; MultiWaitHolderBase *signaled_holder;
TimeSpan current_time; TimeSpan current_time;
InternalCriticalSection cs_wait; InternalCriticalSection cs_wait;
WaitableManagerTargetImpl target_impl; MultiWaitTargetImpl target_impl;
private: private:
Result WaitAnyImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target); Result WaitAnyImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
Result WaitAnyHandleImpl(WaitableHolderBase **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[], WaitableHolderBase *out_objects[], s32 num); s32 BuildHandleArray(Handle out_handles[], MultiWaitHolderBase *out_objects[], s32 num);
WaitableHolderBase *LinkHoldersToObjectList(); MultiWaitHolderBase *LinkHoldersToObjectList();
void UnlinkHoldersFromObjectList(); 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) { MultiWaitHolderBase *WaitAnyImpl(bool infinite, TimeSpan timeout) {
WaitableHolderBase *holder = nullptr; MultiWaitHolderBase *holder = nullptr;
const Result wait_result = this->WaitAnyImpl(std::addressof(holder), infinite, timeout, false, svc::InvalidHandle); const Result wait_result = this->WaitAnyImpl(std::addressof(holder), infinite, timeout, false, svc::InvalidHandle);
R_ASSERT(wait_result); R_ASSERT(wait_result);
@ -58,48 +58,48 @@ namespace ams::os::impl {
} }
public: public:
/* Wait. */ /* Wait. */
WaitableHolderBase *WaitAny() { MultiWaitHolderBase *WaitAny() {
return this->WaitAnyImpl(true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max())); return this->WaitAnyImpl(true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()));
} }
WaitableHolderBase *TryWaitAny() { MultiWaitHolderBase *TryWaitAny() {
return this->WaitAnyImpl(false, TimeSpan(0)); return this->WaitAnyImpl(false, TimeSpan(0));
} }
WaitableHolderBase *TimedWaitAny(TimeSpan ts) { MultiWaitHolderBase *TimedWaitAny(TimeSpan ts) {
return this->WaitAnyImpl(false, 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); return this->WaitAnyImpl(out, true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()), true, reply_target);
} }
/* List management. */ /* List management. */
bool IsEmpty() const { bool IsEmpty() const {
return this->waitable_list.empty(); return this->multi_wait_list.empty();
} }
void LinkWaitableHolder(WaitableHolderBase &holder_base) { void LinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->waitable_list.push_back(holder_base); this->multi_wait_list.push_back(holder_base);
} }
void UnlinkWaitableHolder(WaitableHolderBase &holder_base) { void UnlinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->waitable_list.erase(this->waitable_list.iterator_to(holder_base)); this->multi_wait_list.erase(this->multi_wait_list.iterator_to(holder_base));
} }
void UnlinkAll() { void UnlinkAll() {
while (!this->IsEmpty()) { while (!this->IsEmpty()) {
this->waitable_list.front().SetManager(nullptr); this->multi_wait_list.front().SetMultiWait(nullptr);
this->waitable_list.pop_front(); this->multi_wait_list.pop_front();
} }
} }
void MoveAllFrom(WaitableManagerImpl &other) { void MoveAllFrom(MultiWaitImpl &other) {
/* Set manager for all of the other's waitables. */ /* Set ourselves as multi wait for all of the other's holders. */
for (auto &w : other.waitable_list) { for (auto &w : other.multi_wait_list) {
w.SetManager(this); 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. */ /* Other. */
@ -107,7 +107,7 @@ namespace ams::os::impl {
return this->current_time; 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#include "os_waitable_manager_impl.hpp" #include "os_multiple_wait_impl.hpp"
namespace ams::os::impl { namespace ams::os::impl {
class WaitableObjectList { class MultiWaitObjectList {
public: public:
using ListType = util::IntrusiveListMemberTraits<&WaitableHolderBase::object_list_node>::ListType; using ListType = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::object_list_node>::ListType;
private: private:
ListType object_list; ListType object_list;
public: public:
void SignalAllThreads() { void SignalAllThreads() {
for (WaitableHolderBase &holder_base : this->object_list) { for (MultiWaitHolderBase &holder_base : this->object_list) {
holder_base.GetManager()->SignalAndWakeupThread(&holder_base); holder_base.GetMultiWait()->SignalAndWakeupThread(&holder_base);
} }
} }
void BroadcastAllThreads() { void BroadcastAllThreads() {
for (WaitableHolderBase &holder_base : this->object_list) { for (MultiWaitHolderBase &holder_base : this->object_list) {
holder_base.GetManager()->SignalAndWakeupThread(nullptr); holder_base.GetMultiWait()->SignalAndWakeupThread(nullptr);
} }
} }
@ -41,11 +41,11 @@ namespace ams::os::impl {
return this->object_list.empty(); return this->object_list.empty();
} }
void LinkWaitableHolder(WaitableHolderBase &holder_base) { void LinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
this->object_list.push_back(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)); 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#include "os_waitable_manager_impl.hpp" #include "os_multiple_wait_impl.hpp"
namespace ams::os::impl { 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)); 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_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::ResultTimedOut) { index = MultiWaitImpl::WaitTimedOut; }
R_CATCH(svc::ResultCancelled) { index = WaitableManagerImpl::WaitCancelled; } R_CATCH(svc::ResultCancelled) { index = MultiWaitImpl::WaitCancelled; }
/* All other results are critical errors. */ /* All other results are critical errors. */
/* svc::ResultThreadTerminating */ /* svc::ResultThreadTerminating */
/* svc::ResultInvalidHandle. */ /* svc::ResultInvalidHandle. */
@ -37,17 +37,17 @@ namespace ams::os::impl {
return ResultSuccess(); 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. */ /* NOTE: Nintendo does not initialize this value, which seems like it can cause incorrect behavior. */
s32 index = WaitableManagerImpl::WaitInvalid; s32 index = MultiWaitImpl::WaitInvalid;
static_assert(WaitableManagerImpl::WaitInvalid != -1); static_assert(MultiWaitImpl::WaitInvalid != -1);
R_TRY_CATCH(svc::ReplyAndReceive(std::addressof(index), arr, num, reply_target, ns)) { 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::ResultTimedOut) { *out_index = MultiWaitImpl::WaitTimedOut; return R_CURRENT_RESULT; }
R_CATCH(svc::ResultCancelled) { *out_index = WaitableManagerImpl::WaitCancelled; return R_CURRENT_RESULT; } R_CATCH(svc::ResultCancelled) { *out_index = MultiWaitImpl::WaitCancelled; return R_CURRENT_RESULT; }
R_CATCH(svc::ResultSessionClosed) { R_CATCH(svc::ResultSessionClosed) {
if (index == -1) { if (index == -1) {
*out_index = WaitableManagerImpl::WaitInvalid; *out_index = MultiWaitImpl::WaitInvalid;
return os::ResultSessionClosedForReply(); return os::ResultSessionClosedForReply();
} else { } else {
*out_index = index; *out_index = index;
@ -64,7 +64,7 @@ namespace ams::os::impl {
return ResultSuccess(); return ResultSuccess();
} }
void WaitableManagerHorizonImpl::CancelWait() { void MultiWaitHorizonImpl::CancelWait() {
R_ABORT_UNLESS(svc::CancelSynchronization(this->handle)); R_ABORT_UNLESS(svc::CancelSynchronization(this->handle));
} }

View file

@ -19,7 +19,7 @@
namespace ams::os::impl { namespace ams::os::impl {
class WaitableManagerHorizonImpl { class MultiWaitHorizonImpl {
public: public:
static constexpr size_t MaximumHandleCount = static_cast<size_t>(ams::svc::ArgumentHandleCountMax); static constexpr size_t MaximumHandleCount = static_cast<size_t>(ams::svc::ArgumentHandleCountMax);
private: 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 <stratosphere.hpp>
#include "os_thread_manager.hpp" #include "os_thread_manager.hpp"
#include "os_waitable_manager_impl.hpp" #include "os_multiple_wait_impl.hpp"
#include "os_waitable_holder_base.hpp" #include "os_multiple_wait_holder_base.hpp"
#include "os_waitable_holder_impl.hpp" #include "os_multiple_wait_holder_impl.hpp"
#include "os_waitable_object_list.hpp" #include "os_multiple_wait_object_list.hpp"
#include "os_utility.hpp" #include "os_utility.hpp"
namespace ams::os::impl { namespace ams::os::impl {

View file

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

View file

@ -15,8 +15,8 @@
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_timeout_helper.hpp" #include "impl/os_timeout_helper.hpp"
#include "impl/os_waitable_object_list.hpp" #include "impl/os_multiple_wait_object_list.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
namespace ams::os { namespace ams::os {
@ -40,8 +40,8 @@ namespace ams::os {
util::ConstructAt(event->cs_event); util::ConstructAt(event->cs_event);
util::ConstructAt(event->cv_signaled); util::ConstructAt(event->cv_signaled);
/* Initialize the waitable object list. */ /* Initialize the multi wait object list. */
util::ConstructAt(event->waitable_object_list_storage); util::ConstructAt(event->multi_wait_object_list_storage);
/* Initialize member variables. */ /* Initialize member variables. */
event->signaled = signaled; event->signaled = signaled;
@ -61,7 +61,7 @@ namespace ams::os {
event->state = EventType::State_NotInitialized; event->state = EventType::State_NotInitialized;
/* Destroy objects. */ /* Destroy objects. */
util::DestroyAt(event->waitable_object_list_storage); util::DestroyAt(event->multi_wait_object_list_storage);
util::DestroyAt(event->cv_signaled); util::DestroyAt(event->cv_signaled);
util::DestroyAt(event->cs_event); util::DestroyAt(event->cs_event);
} }
@ -89,7 +89,7 @@ namespace ams::os {
} }
/* Wake up whatever manager, if any. */ /* Wake up whatever manager, if any. */
GetReference(event->waitable_object_list_storage).SignalAllThreads(); GetReference(event->multi_wait_object_list_storage).SignalAllThreads();
} }
void WaitEvent(EventType *event) { void WaitEvent(EventType *event) {
@ -160,12 +160,12 @@ namespace ams::os {
event->signaled = false; event->signaled = false;
} }
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, EventType *event) { void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, EventType *event) {
AMS_ASSERT(event->state == EventType::State_Initialized); AMS_ASSERT(event->state == EventType::State_Initialized);
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_event_storage, event); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_event_storage, event);
waitable_holder->user_data = 0; multi_wait_holder->user_data = 0;
} }
} }

View file

@ -15,8 +15,8 @@
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_interrupt_event_impl.hpp" #include "impl/os_interrupt_event_impl.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
#include "impl/os_waitable_object_list.hpp" #include "impl/os_multiple_wait_object_list.hpp"
namespace ams::os { namespace ams::os {
@ -62,12 +62,12 @@ namespace ams::os {
return GetReference(event->impl).Clear(); return GetReference(event->impl).Clear();
} }
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, InterruptEventType *event) { void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, InterruptEventType *event) {
AMS_ASSERT(event->state == InterruptEventType::State_Initialized); AMS_ASSERT(event->state == InterruptEventType::State_Initialized);
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_interrupt_event_storage, event); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_interrupt_event_storage, event);
waitable_holder->user_data = 0; multi_wait_holder->user_data = 0;
} }
} }

View file

@ -15,8 +15,8 @@
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_timeout_helper.hpp" #include "impl/os_timeout_helper.hpp"
#include "impl/os_waitable_object_list.hpp" #include "impl/os_multiple_wait_object_list.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
#include "impl/os_message_queue_helper.hpp" #include "impl/os_message_queue_helper.hpp"
namespace ams::os { namespace ams::os {
@ -319,20 +319,20 @@ namespace ams::os {
return true; return true;
} }
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, MessageQueueType *mq, MessageQueueWaitType type) { void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, MessageQueueType *mq, MessageQueueWaitType type) {
AMS_ASSERT(mq->state == MessageQueueType::State_Initialized); AMS_ASSERT(mq->state == MessageQueueType::State_Initialized);
switch (type) { switch (type) {
case MessageQueueWaitType::ForNotFull: case MessageQueueWaitType::ForNotFull:
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_mq_for_not_full_storage, mq); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_mq_for_not_full_storage, mq);
break; break;
case MessageQueueWaitType::ForNotEmpty: case MessageQueueWaitType::ForNotEmpty:
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_mq_for_not_empty_storage, mq); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_mq_for_not_empty_storage, mq);
break; break;
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }
waitable_holder->user_data = 0; multi_wait_holder->user_data = 0;
} }
} }

View file

@ -0,0 +1,152 @@
/*
* 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/>.
*/
#include <stratosphere.hpp>
#include "impl/os_multiple_wait_impl.hpp"
#include "impl/os_multiple_wait_holder_base.hpp"
#include "impl/os_multiple_wait_holder_impl.hpp"
namespace ams::os {
namespace {
ALWAYS_INLINE impl::MultiWaitImpl &GetMultiWaitImpl(MultiWaitType *multi_wait) {
return GetReference(multi_wait->impl_storage);
}
ALWAYS_INLINE MultiWaitHolderType *CastToMultiWaitHolder(impl::MultiWaitHolderBase *base) {
return reinterpret_cast<MultiWaitHolderType *>(base);
}
}
void InitializeMultiWait(MultiWaitType *multi_wait) {
/* Initialize storage. */
util::ConstructAt(multi_wait->impl_storage);
/* Mark initialized. */
multi_wait->state = MultiWaitType::State_Initialized;
}
void FinalizeMultiWait(MultiWaitType *multi_wait) {
auto &impl = GetMultiWaitImpl(multi_wait);
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
AMS_ASSERT(impl.IsEmpty());
AMS_UNUSED(impl);
/* Mark not initialized. */
multi_wait->state = MultiWaitType::State_NotInitialized;
/* Destroy. */
util::DestroyAt(multi_wait->impl_storage);
}
MultiWaitHolderType *WaitAny(MultiWaitType *multi_wait) {
auto &impl = GetMultiWaitImpl(multi_wait);
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty());
auto *holder = CastToMultiWaitHolder(impl.WaitAny());
AMS_ASSERT(holder != nullptr);
return holder;
}
MultiWaitHolderType *TryWaitAny(MultiWaitType *multi_wait) {
auto &impl = GetMultiWaitImpl(multi_wait);
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty());
auto *holder = CastToMultiWaitHolder(impl.TryWaitAny());
return holder;
}
MultiWaitHolderType *TimedWaitAny(MultiWaitType *multi_wait, TimeSpan timeout) {
auto &impl = GetMultiWaitImpl(multi_wait);
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty());
AMS_ASSERT(timeout.GetNanoSeconds() >= 0);
auto *holder = CastToMultiWaitHolder(impl.TimedWaitAny(timeout));
return holder;
}
void FinalizeMultiWaitHolder(MultiWaitHolderType *holder) {
auto *holder_base = reinterpret_cast<impl::MultiWaitHolderBase *>(GetPointer(holder->impl_storage));
AMS_ASSERT(!holder_base->IsLinked());
std::destroy_at(holder_base);
}
void LinkMultiWaitHolder(MultiWaitType *multi_wait, MultiWaitHolderType *holder) {
auto &impl = GetMultiWaitImpl(multi_wait);
auto *holder_base = reinterpret_cast<impl::MultiWaitHolderBase *>(GetPointer(holder->impl_storage));
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
AMS_ASSERT(!holder_base->IsLinked());
impl.LinkMultiWaitHolder(*holder_base);
holder_base->SetMultiWait(&impl);
}
void UnlinkMultiWaitHolder(MultiWaitHolderType *holder) {
auto *holder_base = reinterpret_cast<impl::MultiWaitHolderBase *>(GetPointer(holder->impl_storage));
/* Don't allow unlinking of an unlinked holder. */
AMS_ABORT_UNLESS(holder_base->IsLinked());
holder_base->GetMultiWait()->UnlinkMultiWaitHolder(*holder_base);
holder_base->SetMultiWait(nullptr);
}
void UnlinkAllMultiWaitHolder(MultiWaitType *multi_wait) {
auto &impl = GetMultiWaitImpl(multi_wait);
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
return impl.UnlinkAll();
}
void MoveAllMultiWaitHolder(MultiWaitType *_dst, MultiWaitType *_src) {
auto &dst = GetMultiWaitImpl(_dst);
auto &src = GetMultiWaitImpl(_src);
AMS_ASSERT(_dst->state == MultiWaitType::State_Initialized);
AMS_ASSERT(_src->state == MultiWaitType::State_Initialized);
return dst.MoveAllFrom(src);
}
void SetMultiWaitHolderUserData(MultiWaitHolderType *holder, uintptr_t user_data) {
holder->user_data = user_data;
}
uintptr_t GetMultiWaitHolderUserData(const MultiWaitHolderType *holder) {
return holder->user_data;
}
void InitializeMultiWaitHolder(MultiWaitHolderType *holder, Handle handle) {
AMS_ASSERT(handle != svc::InvalidHandle);
util::ConstructAt(GetReference(holder->impl_storage).holder_of_handle_storage, handle);
holder->user_data = 0;
}
}

View file

@ -14,32 +14,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_waitable_manager_impl.hpp" #include "impl/os_multiple_wait_impl.hpp"
#include "impl/os_waitable_holder_base.hpp" #include "impl/os_multiple_wait_holder_base.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
namespace ams::os { namespace ams::os {
namespace { namespace {
ALWAYS_INLINE impl::WaitableManagerImpl &GetWaitableManagerImpl(WaitableManagerType *manager) { ALWAYS_INLINE impl::MultiWaitImpl &GetMultiWaitImpl(MultiWaitType *multi_wait) {
return GetReference(manager->impl_storage); return GetReference(multi_wait->impl_storage);
} }
ALWAYS_INLINE WaitableHolderType *CastToWaitableHolder(impl::WaitableHolderBase *base) { ALWAYS_INLINE MultiWaitHolderType *CastToMultiWaitHolder(impl::MultiWaitHolderBase *base) {
return reinterpret_cast<WaitableHolderType *>(base); return reinterpret_cast<MultiWaitHolderType *>(base);
} }
} }
Result SdkReplyAndReceive(os::WaitableHolderType **out, Handle reply_target, WaitableManagerType *manager) { Result SdkReplyAndReceive(os::MultiWaitHolderType **out, Handle reply_target, MultiWaitType *multi_wait) {
auto &impl = GetWaitableManagerImpl(manager); auto &impl = GetMultiWaitImpl(multi_wait);
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized); AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty()); AMS_ASSERT(!impl.IsEmpty());
impl::WaitableHolderBase *holder_base; impl::MultiWaitHolderBase *holder_base;
ON_SCOPE_EXIT { *out = CastToWaitableHolder(holder_base); }; ON_SCOPE_EXIT { *out = CastToMultiWaitHolder(holder_base); };
return impl.ReplyAndReceive(std::addressof(holder_base), reply_target); return impl.ReplyAndReceive(std::addressof(holder_base), reply_target);
} }

View file

@ -14,8 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_waitable_object_list.hpp" #include "impl/os_multiple_wait_object_list.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
#include "impl/os_timeout_helper.hpp" #include "impl/os_timeout_helper.hpp"
namespace ams::os { namespace ams::os {
@ -142,12 +142,12 @@ namespace ams::os {
return sema->count; return sema->count;
} }
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, SemaphoreType *sema) { void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, SemaphoreType *sema) {
AMS_ASSERT(sema->state == SemaphoreType::State_Initialized); AMS_ASSERT(sema->state == SemaphoreType::State_Initialized);
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_semaphore_storage, sema); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_semaphore_storage, sema);
waitable_holder->user_data = 0; multi_wait_holder->user_data = 0;
} }
} }

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
#include "impl/os_inter_process_event.hpp" #include "impl/os_inter_process_event.hpp"
#include "impl/os_timeout_helper.hpp" #include "impl/os_timeout_helper.hpp"
@ -119,13 +119,13 @@ namespace ams::os {
} }
} }
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, SystemEventType *event) { void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, SystemEventType *event) {
switch (event->state) { switch (event->state) {
case SystemEventType::State_InitializedAsInterProcessEvent: case SystemEventType::State_InitializedAsInterProcessEvent:
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_inter_process_event_storage, std::addressof(event->inter_process_event)); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_inter_process_event_storage, std::addressof(event->inter_process_event));
break; break;
case SystemEventType::State_InitializedAsEvent: case SystemEventType::State_InitializedAsEvent:
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_event_storage, std::addressof(event->event)); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_event_storage, std::addressof(event->event));
break; break;
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }

View file

@ -16,7 +16,7 @@
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "impl/os_thread_manager.hpp" #include "impl/os_thread_manager.hpp"
#include "impl/os_timeout_helper.hpp" #include "impl/os_timeout_helper.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
namespace ams::os { namespace ams::os {

View file

@ -17,8 +17,8 @@
#include "impl/os_timer_event_helper.hpp" #include "impl/os_timer_event_helper.hpp"
#include "impl/os_tick_manager.hpp" #include "impl/os_tick_manager.hpp"
#include "impl/os_timeout_helper.hpp" #include "impl/os_timeout_helper.hpp"
#include "impl/os_waitable_object_list.hpp" #include "impl/os_multiple_wait_object_list.hpp"
#include "impl/os_waitable_holder_impl.hpp" #include "impl/os_multiple_wait_holder_impl.hpp"
namespace ams::os { namespace ams::os {
@ -49,7 +49,7 @@ namespace ams::os {
} }
/* Wake up whatever manager, if any. */ /* Wake up whatever manager, if any. */
GetReference(event->waitable_object_list_storage).SignalAllThreads(); GetReference(event->multi_wait_object_list_storage).SignalAllThreads();
} }
} }
@ -59,8 +59,8 @@ namespace ams::os {
util::ConstructAt(event->cs_timer_event); util::ConstructAt(event->cs_timer_event);
util::ConstructAt(event->cv_signaled); util::ConstructAt(event->cv_signaled);
/* Initialize the waitable object list. */ /* Initialize the multi wait object list. */
util::ConstructAt(event->waitable_object_list_storage); util::ConstructAt(event->multi_wait_object_list_storage);
/* Initialize member variables. */ /* Initialize member variables. */
event->clear_mode = static_cast<u8>(clear_mode); event->clear_mode = static_cast<u8>(clear_mode);
@ -83,7 +83,7 @@ namespace ams::os {
event->state = TimerEventType::State_NotInitialized; event->state = TimerEventType::State_NotInitialized;
/* Destroy objects. */ /* Destroy objects. */
util::DestroyAt(event->waitable_object_list_storage); util::DestroyAt(event->multi_wait_object_list_storage);
util::DestroyAt(event->cv_signaled); util::DestroyAt(event->cv_signaled);
util::DestroyAt(event->cs_timer_event); util::DestroyAt(event->cs_timer_event);
} }
@ -110,7 +110,7 @@ namespace ams::os {
GetReference(event->cv_signaled).Broadcast(); GetReference(event->cv_signaled).Broadcast();
/* Wake up whatever manager, if any. */ /* Wake up whatever manager, if any. */
GetReference(event->waitable_object_list_storage).SignalAllThreads(); GetReference(event->multi_wait_object_list_storage).SignalAllThreads();
} }
} }
@ -137,7 +137,7 @@ namespace ams::os {
GetReference(event->cv_signaled).Broadcast(); GetReference(event->cv_signaled).Broadcast();
/* Wake up whatever manager, if any. */ /* Wake up whatever manager, if any. */
GetReference(event->waitable_object_list_storage).SignalAllThreads(); GetReference(event->multi_wait_object_list_storage).SignalAllThreads();
} }
} }
@ -154,7 +154,7 @@ namespace ams::os {
GetReference(event->cv_signaled).Broadcast(); GetReference(event->cv_signaled).Broadcast();
/* Wake up whatever manager, if any. */ /* Wake up whatever manager, if any. */
GetReference(event->waitable_object_list_storage).SignalAllThreads(); GetReference(event->multi_wait_object_list_storage).SignalAllThreads();
} }
} }
@ -252,12 +252,12 @@ namespace ams::os {
} }
} }
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, TimerEventType *event) { void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, TimerEventType *event) {
AMS_ASSERT(event->state == EventType::State_Initialized); AMS_ASSERT(event->state == EventType::State_Initialized);
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_timer_event_storage, event); util::ConstructAt(GetReference(multi_wait_holder->impl_storage).holder_of_timer_event_storage, event);
waitable_holder->user_data = 0; multi_wait_holder->user_data = 0;
} }
} }

View file

@ -1,152 +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/>.
*/
#include <stratosphere.hpp>
#include "impl/os_waitable_manager_impl.hpp"
#include "impl/os_waitable_holder_base.hpp"
#include "impl/os_waitable_holder_impl.hpp"
namespace ams::os {
namespace {
ALWAYS_INLINE impl::WaitableManagerImpl &GetWaitableManagerImpl(WaitableManagerType *manager) {
return GetReference(manager->impl_storage);
}
ALWAYS_INLINE WaitableHolderType *CastToWaitableHolder(impl::WaitableHolderBase *base) {
return reinterpret_cast<WaitableHolderType *>(base);
}
}
void InitializeWaitableManager(WaitableManagerType *manager) {
/* Initialize storage. */
util::ConstructAt(manager->impl_storage);
/* Mark initialized. */
manager->state = WaitableManagerType::State_Initialized;
}
void FinalizeWaitableManager(WaitableManagerType *manager) {
auto &impl = GetWaitableManagerImpl(manager);
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
AMS_ASSERT(impl.IsEmpty());
AMS_UNUSED(impl);
/* Mark not initialized. */
manager->state = WaitableManagerType::State_NotInitialized;
/* Destroy. */
util::DestroyAt(manager->impl_storage);
}
WaitableHolderType *WaitAny(WaitableManagerType *manager) {
auto &impl = GetWaitableManagerImpl(manager);
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty());
auto *holder = CastToWaitableHolder(impl.WaitAny());
AMS_ASSERT(holder != nullptr);
return holder;
}
WaitableHolderType *TryWaitAny(WaitableManagerType *manager) {
auto &impl = GetWaitableManagerImpl(manager);
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty());
auto *holder = CastToWaitableHolder(impl.TryWaitAny());
return holder;
}
WaitableHolderType *TimedWaitAny(WaitableManagerType *manager, TimeSpan timeout) {
auto &impl = GetWaitableManagerImpl(manager);
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
AMS_ASSERT(!impl.IsEmpty());
AMS_ASSERT(timeout.GetNanoSeconds() >= 0);
auto *holder = CastToWaitableHolder(impl.TimedWaitAny(timeout));
return holder;
}
void FinalizeWaitableHolder(WaitableHolderType *holder) {
auto *holder_base = reinterpret_cast<impl::WaitableHolderBase *>(GetPointer(holder->impl_storage));
AMS_ASSERT(!holder_base->IsLinkedToManager());
std::destroy_at(holder_base);
}
void LinkWaitableHolder(WaitableManagerType *manager, WaitableHolderType *holder) {
auto &impl = GetWaitableManagerImpl(manager);
auto *holder_base = reinterpret_cast<impl::WaitableHolderBase *>(GetPointer(holder->impl_storage));
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
AMS_ASSERT(!holder_base->IsLinkedToManager());
impl.LinkWaitableHolder(*holder_base);
holder_base->SetManager(&impl);
}
void UnlinkWaitableHolder(WaitableHolderType *holder) {
auto *holder_base = reinterpret_cast<impl::WaitableHolderBase *>(GetPointer(holder->impl_storage));
/* Don't allow unlinking of an unlinked holder. */
AMS_ABORT_UNLESS(holder_base->IsLinkedToManager());
holder_base->GetManager()->UnlinkWaitableHolder(*holder_base);
holder_base->SetManager(nullptr);
}
void UnlinkAllWaitableHolder(WaitableManagerType *manager) {
auto &impl = GetWaitableManagerImpl(manager);
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
return impl.UnlinkAll();
}
void MoveAllWaitableHolder(WaitableManagerType *_dst, WaitableManagerType *_src) {
auto &dst = GetWaitableManagerImpl(_dst);
auto &src = GetWaitableManagerImpl(_src);
AMS_ASSERT(_dst->state == WaitableManagerType::State_Initialized);
AMS_ASSERT(_src->state == WaitableManagerType::State_Initialized);
return dst.MoveAllFrom(src);
}
void SetWaitableHolderUserData(WaitableHolderType *holder, uintptr_t user_data) {
holder->user_data = user_data;
}
uintptr_t GetWaitableHolderUserData(const WaitableHolderType *holder) {
return holder->user_data;
}
void InitializeWaitableHolder(WaitableHolderType *holder, Handle handle) {
AMS_ASSERT(handle != svc::InvalidHandle);
util::ConstructAt(GetReference(holder->impl_storage).holder_of_handle_storage, handle);
holder->user_data = 0;
}
}

View file

@ -26,7 +26,7 @@ namespace ams::osdbg::impl {
struct ThreadTypeIlp32 { struct ThreadTypeIlp32 {
AlignedStorageIlp32<0, 2, alignof(u32)> _all_threads_node; AlignedStorageIlp32<0, 2, alignof(u32)> _all_threads_node;
AlignedStorageIlp32<0, 2, alignof(u32)> _waitable_object_list; AlignedStorageIlp32<0, 2, alignof(u32)> _multi_wait_object_list;
u32 _padding[4]; u32 _padding[4];
u8 _state; u8 _state;
bool _stack_is_aliased; bool _stack_is_aliased;
@ -55,7 +55,7 @@ namespace ams::osdbg::impl {
struct ThreadTypeIlp32Version0 { struct ThreadTypeIlp32Version0 {
AlignedStorageIlp32<0, 2, alignof(u32)> _all_threads_node; AlignedStorageIlp32<0, 2, alignof(u32)> _all_threads_node;
AlignedStorageIlp32<0, 2, alignof(u32)> _waitable_object_list; AlignedStorageIlp32<0, 2, alignof(u32)> _multi_wait_object_list;
u32 _padding[4]; u32 _padding[4];
u8 _state; u8 _state;
bool _stack_is_aliased; bool _stack_is_aliased;
@ -82,7 +82,7 @@ namespace ams::osdbg::impl {
struct ThreadTypeLp64 { struct ThreadTypeLp64 {
AlignedStorageLp64<0, 2, alignof(u64)> _all_threads_node; AlignedStorageLp64<0, 2, alignof(u64)> _all_threads_node;
AlignedStorageLp64<0, 2, alignof(u64)> _waitable_object_list; AlignedStorageLp64<0, 2, alignof(u64)> _multi_wait_object_list;
u64 _padding[4]; u64 _padding[4];
u8 _state; u8 _state;
bool _stack_is_aliased; bool _stack_is_aliased;
@ -110,7 +110,7 @@ namespace ams::osdbg::impl {
struct ThreadTypeLp64Version0 { struct ThreadTypeLp64Version0 {
AlignedStorageLp64<0, 2, alignof(u64)> _all_threads_node; AlignedStorageLp64<0, 2, alignof(u64)> _all_threads_node;
AlignedStorageLp64<0, 2, alignof(u64)> _waitable_object_list; AlignedStorageLp64<0, 2, alignof(u64)> _multi_wait_object_list;
u64 _padding[4]; u64 _padding[4];
u8 _state; u8 _state;
bool _stack_is_aliased; bool _stack_is_aliased;

View file

@ -41,12 +41,12 @@ namespace ams::sf::hipc {
} }
void AttachWaitableHolderForAccept(os::WaitableHolderType *holder, Handle port) { void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, Handle port) {
return os::InitializeWaitableHolder(holder, port); return os::InitializeMultiWaitHolder(holder, port);
} }
void AttachWaitableHolderForReply(os::WaitableHolderType *holder, Handle request) { void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, Handle request) {
return os::InitializeWaitableHolder(holder, request); return os::InitializeMultiWaitHolder(holder, request);
} }
Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer) { Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer) {

View file

@ -32,37 +32,37 @@ namespace ams::sf::hipc {
return ResultSuccess(); return ResultSuccess();
} }
void ServerManagerBase::RegisterSessionToWaitList(ServerSession *session) { void ServerManagerBase::RegisterServerSessionToWait(ServerSession *session) {
session->has_received = false; session->has_received = false;
/* Set user data tag. */ /* Set user data tag. */
os::SetWaitableHolderUserData(session, static_cast<uintptr_t>(UserDataTag::Session)); os::SetMultiWaitHolderUserData(session, static_cast<uintptr_t>(UserDataTag::Session));
this->RegisterToWaitList(session); this->LinkToDeferredList(session);
} }
void ServerManagerBase::RegisterToWaitList(os::WaitableHolderType *holder) { void ServerManagerBase::LinkToDeferredList(os::MultiWaitHolderType *holder) {
std::scoped_lock lk(this->waitlist_mutex); std::scoped_lock lk(this->deferred_list_mutex);
os::LinkWaitableHolder(std::addressof(this->waitlist), holder); os::LinkMultiWaitHolder(std::addressof(this->deferred_list), holder);
this->notify_event.Signal(); this->notify_event.Signal();
} }
void ServerManagerBase::ProcessWaitList() { void ServerManagerBase::LinkDeferred() {
std::scoped_lock lk(this->waitlist_mutex); std::scoped_lock lk(this->deferred_list_mutex);
os::MoveAllWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->waitlist)); os::MoveAllMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->deferred_list));
} }
os::WaitableHolderType *ServerManagerBase::WaitSignaled() { os::MultiWaitHolderType *ServerManagerBase::WaitSignaled() {
std::scoped_lock lk(this->waitable_selection_mutex); std::scoped_lock lk(this->selection_mutex);
while (true) { while (true) {
this->ProcessWaitList(); this->LinkDeferred();
auto selected = os::WaitAny(std::addressof(this->waitable_manager)); auto selected = os::WaitAny(std::addressof(this->multi_wait));
if (selected == &this->request_stop_event_holder) { if (selected == &this->request_stop_event_holder) {
return nullptr; return nullptr;
} else if (selected == &this->notify_event_holder) { } else if (selected == &this->notify_event_holder) {
this->notify_event.Clear(); this->notify_event.Clear();
} else { } else {
os::UnlinkWaitableHolder(selected); os::UnlinkMultiWaitHolder(selected);
return selected; return selected;
} }
} }
@ -76,19 +76,19 @@ namespace ams::sf::hipc {
this->request_stop_event.Signal(); this->request_stop_event.Signal();
} }
void ServerManagerBase::AddUserWaitableHolder(os::WaitableHolderType *waitable) { void ServerManagerBase::AddUserMultiWaitHolder(os::MultiWaitHolderType *holder) {
const auto user_data_tag = static_cast<UserDataTag>(os::GetWaitableHolderUserData(waitable)); const auto user_data_tag = static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder));
AMS_ABORT_UNLESS(user_data_tag != UserDataTag::Server); AMS_ABORT_UNLESS(user_data_tag != UserDataTag::Server);
AMS_ABORT_UNLESS(user_data_tag != UserDataTag::MitmServer); AMS_ABORT_UNLESS(user_data_tag != UserDataTag::MitmServer);
AMS_ABORT_UNLESS(user_data_tag != UserDataTag::Session); AMS_ABORT_UNLESS(user_data_tag != UserDataTag::Session);
this->RegisterToWaitList(waitable); this->LinkToDeferredList(holder);
} }
Result ServerManagerBase::ProcessForServer(os::WaitableHolderType *holder) { Result ServerManagerBase::ProcessForServer(os::MultiWaitHolderType *holder) {
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder)) == UserDataTag::Server); AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder)) == UserDataTag::Server);
Server *server = static_cast<Server *>(holder); Server *server = static_cast<Server *>(holder);
ON_SCOPE_EXIT { this->RegisterToWaitList(server); }; ON_SCOPE_EXIT { this->LinkToDeferredList(server); };
/* Create new session. */ /* Create new session. */
if (server->static_object) { if (server->static_object) {
@ -98,18 +98,18 @@ namespace ams::sf::hipc {
} }
} }
Result ServerManagerBase::ProcessForMitmServer(os::WaitableHolderType *holder) { Result ServerManagerBase::ProcessForMitmServer(os::MultiWaitHolderType *holder) {
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder)) == UserDataTag::MitmServer); AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder)) == UserDataTag::MitmServer);
Server *server = static_cast<Server *>(holder); Server *server = static_cast<Server *>(holder);
ON_SCOPE_EXIT { this->RegisterToWaitList(server); }; ON_SCOPE_EXIT { this->LinkToDeferredList(server); };
/* Create resources for new session. */ /* Create resources for new session. */
return this->OnNeedsToAccept(server->index, server); return this->OnNeedsToAccept(server->index, server);
} }
Result ServerManagerBase::ProcessForSession(os::WaitableHolderType *holder) { Result ServerManagerBase::ProcessForSession(os::MultiWaitHolderType *holder) {
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder)) == UserDataTag::Session); AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder)) == UserDataTag::Session);
ServerSession *session = static_cast<ServerSession *>(holder); ServerSession *session = static_cast<ServerSession *>(holder);
@ -133,8 +133,8 @@ namespace ams::sf::hipc {
return ResultSuccess(); return ResultSuccess();
} }
Result ServerManagerBase::Process(os::WaitableHolderType *holder) { Result ServerManagerBase::Process(os::MultiWaitHolderType *holder) {
switch (static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder))) { switch (static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder))) {
case UserDataTag::Server: case UserDataTag::Server:
return this->ProcessForServer(holder); return this->ProcessForServer(holder);
case UserDataTag::MitmServer: case UserDataTag::MitmServer:
@ -146,12 +146,12 @@ namespace ams::sf::hipc {
} }
bool ServerManagerBase::WaitAndProcessImpl() { bool ServerManagerBase::WaitAndProcessImpl() {
auto waitable = this->WaitSignaled(); if (auto *signaled_holder = this->WaitSignaled(); signaled_holder != nullptr) {
if (!waitable) { R_ABORT_UNLESS(this->Process(signaled_holder));
return true;
} else {
return false; return false;
} }
R_ABORT_UNLESS(this->Process(waitable));
return true;
} }
void ServerManagerBase::WaitAndProcess() { void ServerManagerBase::WaitAndProcess() {

View file

@ -78,7 +78,7 @@ namespace ams::sf::hipc {
void ServerSessionManager::CloseSessionImpl(ServerSession *session) { void ServerSessionManager::CloseSessionImpl(ServerSession *session) {
const Handle session_handle = session->session_handle; const Handle session_handle = session->session_handle;
os::FinalizeWaitableHolder(session); os::FinalizeMultiWaitHolder(session);
this->DestroySession(session); this->DestroySession(session);
R_ABORT_UNLESS(svcCloseHandle(session_handle)); R_ABORT_UNLESS(svcCloseHandle(session_handle));
} }
@ -92,7 +92,7 @@ namespace ams::sf::hipc {
session_memory->saved_message = this->GetSessionSavedMessageBuffer(session_memory); session_memory->saved_message = this->GetSessionSavedMessageBuffer(session_memory);
/* Register to wait list. */ /* Register to wait list. */
this->RegisterSessionToWaitList(session_memory); this->RegisterServerSessionToWait(session_memory);
return ResultSuccess(); return ResultSuccess();
} }
@ -123,7 +123,7 @@ namespace ams::sf::hipc {
session_memory->pointer_buffer = cmif::PointerAndSize(session_memory->pointer_buffer.GetAddress(), session_memory->forward_service->pointer_buffer_size); session_memory->pointer_buffer = cmif::PointerAndSize(session_memory->pointer_buffer.GetAddress(), session_memory->forward_service->pointer_buffer_size);
/* Register to wait list. */ /* Register to wait list. */
this->RegisterSessionToWaitList(session_memory); this->RegisterServerSessionToWait(session_memory);
return ResultSuccess(); return ResultSuccess();
} }
@ -233,7 +233,7 @@ namespace ams::sf::hipc {
} R_END_TRY_CATCH; } R_END_TRY_CATCH;
/* We succeeded, so we can process future messages on this session. */ /* We succeeded, so we can process future messages on this session. */
this->RegisterSessionToWaitList(session); this->RegisterServerSessionToWait(session);
return ResultSuccess(); return ResultSuccess();
} }
} }

View file

@ -71,18 +71,18 @@ namespace ams::sdmmc::impl {
os::SystemEventType gpio_event; os::SystemEventType gpio_event;
R_ABORT_UNLESS(gpio::BindInterrupt(std::addressof(gpio_event), std::addressof(this->gpio_pad_session))); R_ABORT_UNLESS(gpio::BindInterrupt(std::addressof(gpio_event), std::addressof(this->gpio_pad_session)));
/* Initialize and link waitable holders. */ /* Initialize and link multi wait/holders. */
os::WaitableManagerType wait_manager; os::MultiWaitType multi_wait;
os::WaitableHolderType detector_thread_end_holder; os::MultiWaitHolderType detector_thread_end_holder;
os::WaitableHolderType request_sleep_wake_event_holder; os::MultiWaitHolderType request_sleep_wake_event_holder;
os::WaitableHolderType gpio_event_holder; os::MultiWaitHolderType gpio_event_holder;
os::InitializeWaitableManager(std::addressof(wait_manager)); os::InitializeMultiWait(std::addressof(multi_wait));
os::InitializeWaitableHolder(std::addressof(detector_thread_end_holder), std::addressof(this->detector_thread_end_event)); os::InitializeMultiWaitHolder(std::addressof(detector_thread_end_holder), std::addressof(this->detector_thread_end_event));
os::LinkWaitableHolder(std::addressof(wait_manager), std::addressof(detector_thread_end_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(detector_thread_end_holder));
os::InitializeWaitableHolder(std::addressof(request_sleep_wake_event_holder), std::addressof(this->request_sleep_wake_event)); os::InitializeMultiWaitHolder(std::addressof(request_sleep_wake_event_holder), std::addressof(this->request_sleep_wake_event));
os::LinkWaitableHolder(std::addressof(wait_manager), std::addressof(request_sleep_wake_event_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(request_sleep_wake_event_holder));
os::InitializeWaitableHolder(std::addressof(gpio_event_holder), std::addressof(gpio_event)); os::InitializeMultiWaitHolder(std::addressof(gpio_event_holder), std::addressof(gpio_event));
os::LinkWaitableHolder(std::addressof(wait_manager), std::addressof(gpio_event_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(gpio_event_holder));
/* Wait before detecting the initial state of the card. */ /* Wait before detecting the initial state of the card. */
os::SleepThread(TimeSpan::FromMilliSeconds(this->gpio_debounce_ms)); os::SleepThread(TimeSpan::FromMilliSeconds(this->gpio_debounce_ms));
@ -99,7 +99,7 @@ namespace ams::sdmmc::impl {
/* Wait, servicing our events. */ /* Wait, servicing our events. */
while (true) { while (true) {
/* Get the signaled holder. */ /* Get the signaled holder. */
os::WaitableHolderType *signaled_holder = os::WaitAny(std::addressof(wait_manager)); os::MultiWaitHolderType *signaled_holder = os::WaitAny(std::addressof(multi_wait));
/* Process the holder. */ /* Process the holder. */
bool insert_change = false; bool insert_change = false;
@ -115,13 +115,13 @@ namespace ams::sdmmc::impl {
os::SignalEvent(std::addressof(this->acknowledge_sleep_awake_event)); os::SignalEvent(std::addressof(this->acknowledge_sleep_awake_event));
/* Temporarily unlink our interrupt event. */ /* Temporarily unlink our interrupt event. */
os::UnlinkWaitableHolder(std::addressof(gpio_event_holder)); os::UnlinkMultiWaitHolder(std::addressof(gpio_event_holder));
/* Wait to be signaled. */ /* Wait to be signaled. */
signaled_holder = os::WaitAny(std::addressof(wait_manager)); signaled_holder = os::WaitAny(std::addressof(multi_wait));
/* Link our interrupt event back in. */ /* Link our interrupt event back in. */
os::LinkWaitableHolder(std::addressof(wait_manager), std::addressof(gpio_event_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(gpio_event_holder));
/* We're awake again. Either because we should exit, or because we were asked to wake up. */ /* We're awake again. Either because we should exit, or because we were asked to wake up. */
os::ClearEvent(std::addressof(this->request_sleep_wake_event)); os::ClearEvent(std::addressof(this->request_sleep_wake_event));
@ -170,14 +170,14 @@ namespace ams::sdmmc::impl {
/* Disable interrupts to our gpio event. */ /* Disable interrupts to our gpio event. */
gpio::SetInterruptEnable(std::addressof(this->gpio_pad_session), false); gpio::SetInterruptEnable(std::addressof(this->gpio_pad_session), false);
/* Finalize and unlink waitable holders. */ /* Finalize and unlink multi wait/holders. */
os::UnlinkWaitableHolder(std::addressof(gpio_event_holder)); os::UnlinkMultiWaitHolder(std::addressof(gpio_event_holder));
os::FinalizeWaitableHolder(std::addressof(gpio_event_holder)); os::FinalizeMultiWaitHolder(std::addressof(gpio_event_holder));
os::UnlinkWaitableHolder(std::addressof(request_sleep_wake_event_holder)); os::UnlinkMultiWaitHolder(std::addressof(request_sleep_wake_event_holder));
os::FinalizeWaitableHolder(std::addressof(request_sleep_wake_event_holder)); os::FinalizeMultiWaitHolder(std::addressof(request_sleep_wake_event_holder));
os::UnlinkWaitableHolder(std::addressof(detector_thread_end_holder)); os::UnlinkMultiWaitHolder(std::addressof(detector_thread_end_holder));
os::FinalizeWaitableHolder(std::addressof(detector_thread_end_holder)); os::FinalizeMultiWaitHolder(std::addressof(detector_thread_end_holder));
os::FinalizeWaitableManager(std::addressof(wait_manager)); os::FinalizeMultiWait(std::addressof(multi_wait));
/* Finalize the gpio session. */ /* Finalize the gpio session. */
gpio::UnbindInterrupt(std::addressof(this->gpio_pad_session)); gpio::UnbindInterrupt(std::addressof(this->gpio_pad_session));

View file

@ -173,7 +173,7 @@ namespace ams::sdmmc::impl {
this->EnsureControl(); this->EnsureControl();
/* Wait for the interrupt to be signaled. */ /* Wait for the interrupt to be signaled. */
os::WaitableHolderType *signaled_holder = os::TimedWaitAny(std::addressof(this->waitable_manager), TimeSpan::FromMilliSeconds(timeout_ms)); os::MultiWaitHolderType *signaled_holder = os::TimedWaitAny(std::addressof(this->multi_wait), TimeSpan::FromMilliSeconds(timeout_ms));
if (signaled_holder == std::addressof(this->interrupt_event_holder)) { if (signaled_holder == std::addressof(this->interrupt_event_holder)) {
/* We received the interrupt. */ /* We received the interrupt. */
return ResultSuccess(); return ResultSuccess();
@ -781,15 +781,15 @@ namespace ams::sdmmc::impl {
void SdHostStandardController::Initialize() { void SdHostStandardController::Initialize() {
#if defined(AMS_SDMMC_USE_OS_EVENTS) #if defined(AMS_SDMMC_USE_OS_EVENTS)
{ {
os::InitializeWaitableManager(std::addressof(this->waitable_manager)); os::InitializeMultiWait(std::addressof(this->multi_wait));
AMS_ABORT_UNLESS(this->interrupt_event != nullptr); AMS_ABORT_UNLESS(this->interrupt_event != nullptr);
os::InitializeWaitableHolder(std::addressof(this->interrupt_event_holder), this->interrupt_event); os::InitializeMultiWaitHolder(std::addressof(this->interrupt_event_holder), this->interrupt_event);
os::LinkWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->interrupt_event_holder)); os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->interrupt_event_holder));
if (this->removed_event != nullptr) { if (this->removed_event != nullptr) {
os::InitializeWaitableHolder(std::addressof(this->removed_event_holder), this->removed_event); os::InitializeMultiWaitHolder(std::addressof(this->removed_event_holder), this->removed_event);
os::LinkWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->removed_event_holder)); os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->removed_event_holder));
} }
} }
#endif #endif
@ -799,14 +799,14 @@ namespace ams::sdmmc::impl {
#if defined(AMS_SDMMC_USE_OS_EVENTS) #if defined(AMS_SDMMC_USE_OS_EVENTS)
{ {
if (this->removed_event != nullptr) { if (this->removed_event != nullptr) {
os::UnlinkWaitableHolder(std::addressof(this->removed_event_holder)); os::UnlinkMultiWaitHolder(std::addressof(this->removed_event_holder));
os::FinalizeWaitableHolder(std::addressof(this->removed_event_holder)); os::FinalizeMultiWaitHolder(std::addressof(this->removed_event_holder));
} }
os::UnlinkWaitableHolder(std::addressof(this->interrupt_event_holder)); os::UnlinkMultiWaitHolder(std::addressof(this->interrupt_event_holder));
os::FinalizeWaitableHolder(std::addressof(this->interrupt_event_holder)); os::FinalizeMultiWaitHolder(std::addressof(this->interrupt_event_holder));
os::FinalizeWaitableManager(std::addressof(this->waitable_manager)); os::FinalizeMultiWait(std::addressof(this->multi_wait));
} }
#endif #endif
} }

View file

@ -39,11 +39,11 @@ namespace ams::sdmmc::impl {
#endif #endif
#if defined(AMS_SDMMC_USE_OS_EVENTS) #if defined(AMS_SDMMC_USE_OS_EVENTS)
os::WaitableManagerType waitable_manager; os::MultiWaitType multi_wait;
os::InterruptEventType *interrupt_event; os::InterruptEventType *interrupt_event;
os::WaitableHolderType interrupt_event_holder; os::MultiWaitHolderType interrupt_event_holder;
os::EventType *removed_event; os::EventType *removed_event;
os::WaitableHolderType removed_event_holder; os::MultiWaitHolderType removed_event_holder;
#endif #endif
u64 next_sdma_address; u64 next_sdma_address;

View file

@ -32,19 +32,19 @@ namespace ams::fatal::srv {
/* Global event. */ /* Global event. */
os::SystemEventType g_fatal_dirty_event; os::SystemEventType g_fatal_dirty_event;
os::WaitableHolderType g_fatal_dirty_waitable_holder; os::MultiWaitHolderType g_fatal_dirty_multi_wait_holder;
bool g_initialized; bool g_initialized;
} }
os::WaitableHolderType *GetFatalDirtyWaitableHolder() { os::MultiWaitHolderType *GetFatalDirtyMultiWaitHolder() {
if (AMS_UNLIKELY(!g_initialized)) { if (AMS_UNLIKELY(!g_initialized)) {
os::AttachReadableHandleToSystemEvent(std::addressof(g_fatal_dirty_event), GetFatalDirtyEventReadableHandle(), true, os::EventClearMode_ManualClear); os::AttachReadableHandleToSystemEvent(std::addressof(g_fatal_dirty_event), GetFatalDirtyEventReadableHandle(), true, os::EventClearMode_ManualClear);
os::InitializeWaitableHolder(std::addressof(g_fatal_dirty_waitable_holder), std::addressof(g_fatal_dirty_event)); os::InitializeMultiWaitHolder(std::addressof(g_fatal_dirty_multi_wait_holder), std::addressof(g_fatal_dirty_event));
os::SetWaitableHolderUserData(std::addressof(g_fatal_dirty_waitable_holder), reinterpret_cast<uintptr_t>(std::addressof(g_fatal_dirty_waitable_holder))); os::SetMultiWaitHolderUserData(std::addressof(g_fatal_dirty_multi_wait_holder), reinterpret_cast<uintptr_t>(std::addressof(g_fatal_dirty_multi_wait_holder)));
g_initialized = true; g_initialized = true;
} }
return std::addressof(g_fatal_dirty_waitable_holder); return std::addressof(g_fatal_dirty_multi_wait_holder);
} }
void OnFatalDirtyEvent() { void OnFatalDirtyEvent() {

View file

@ -88,7 +88,7 @@ namespace ams::fatal::srv {
} }
}; };
os::WaitableHolderType *GetFatalDirtyWaitableHolder(); os::MultiWaitHolderType *GetFatalDirtyMultiWaitHolder();
void OnFatalDirtyEvent(); void OnFatalDirtyEvent();
const FatalConfig &GetFatalConfig(); const FatalConfig &GetFatalConfig();

View file

@ -218,8 +218,8 @@ int main(int argc, char **argv)
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_private_service_object.GetShared(), PrivateServiceName, PrivateMaxSessions)); R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_private_service_object.GetShared(), PrivateServiceName, PrivateMaxSessions));
/* Add dirty event holder. */ /* Add dirty event holder. */
auto *dirty_event_holder = ams::fatal::srv::GetFatalDirtyWaitableHolder(); auto *dirty_event_holder = ams::fatal::srv::GetFatalDirtyMultiWaitHolder();
g_server_manager.AddUserWaitableHolder(dirty_event_holder); g_server_manager.AddUserMultiWaitHolder(dirty_event_holder);
/* Loop forever, servicing our services. */ /* Loop forever, servicing our services. */
/* Because fatal has a user wait holder, we need to specify how to process manually. */ /* Because fatal has a user wait holder, we need to specify how to process manually. */
@ -227,7 +227,7 @@ int main(int argc, char **argv)
if (signaled_holder == dirty_event_holder) { if (signaled_holder == dirty_event_holder) {
/* Dirty event holder was signaled. */ /* Dirty event holder was signaled. */
fatal::srv::OnFatalDirtyEvent(); fatal::srv::OnFatalDirtyEvent();
g_server_manager.AddUserWaitableHolder(signaled_holder); g_server_manager.AddUserMultiWaitHolder(signaled_holder);
} else { } else {
/* A server/session was signaled. Have the manager handle it. */ /* A server/session was signaled. Have the manager handle it. */
R_ABORT_UNLESS(g_server_manager.Process(signaled_holder)); R_ABORT_UNLESS(g_server_manager.Process(signaled_holder));

View file

@ -19,8 +19,8 @@
namespace ams::pm::impl { namespace ams::pm::impl {
ProcessInfo::ProcessInfo(Handle h, os::ProcessId pid, ldr::PinId pin, const ncm::ProgramLocation &l, const cfg::OverrideStatus &s) : process_id(pid), pin_id(pin), loc(l), status(s), handle(h), state(svc::ProcessState_Created), flags(0) { ProcessInfo::ProcessInfo(Handle h, os::ProcessId pid, ldr::PinId pin, const ncm::ProgramLocation &l, const cfg::OverrideStatus &s) : process_id(pid), pin_id(pin), loc(l), status(s), handle(h), state(svc::ProcessState_Created), flags(0) {
os::InitializeWaitableHolder(std::addressof(this->waitable_holder), this->handle); os::InitializeMultiWaitHolder(std::addressof(this->multi_wait_holder), this->handle);
os::SetWaitableHolderUserData(std::addressof(this->waitable_holder), reinterpret_cast<uintptr_t>(this)); os::SetMultiWaitHolderUserData(std::addressof(this->multi_wait_holder), reinterpret_cast<uintptr_t>(this));
} }
ProcessInfo::~ProcessInfo() { ProcessInfo::~ProcessInfo() {
@ -38,8 +38,8 @@ namespace ams::pm::impl {
svcCloseHandle(this->handle); svcCloseHandle(this->handle);
this->handle = INVALID_HANDLE; this->handle = INVALID_HANDLE;
/* Unlink the process from its waitable manager. */ /* Unlink the process from its multi wait. */
os::UnlinkWaitableHolder(std::addressof(this->waitable_holder)); os::UnlinkMultiWaitHolder(std::addressof(this->multi_wait_holder));
} }
} }

View file

@ -46,7 +46,7 @@ namespace ams::pm::impl {
Handle handle; Handle handle;
svc::ProcessState state; svc::ProcessState state;
u32 flags; u32 flags;
os::WaitableHolderType waitable_holder; os::MultiWaitHolderType multi_wait_holder;
private: private:
void SetFlag(Flag flag) { void SetFlag(Flag flag) {
this->flags |= flag; this->flags |= flag;
@ -64,8 +64,8 @@ namespace ams::pm::impl {
~ProcessInfo(); ~ProcessInfo();
void Cleanup(); void Cleanup();
void LinkToWaitableManager(os::WaitableManagerType &manager) { void LinkToMultiWait(os::MultiWaitType &multi_wait) {
os::LinkWaitableHolder(std::addressof(manager), std::addressof(this->waitable_holder)); os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(this->multi_wait_holder));
} }
Handle GetHandle() const { Handle GetHandle() const {

View file

@ -150,33 +150,33 @@ namespace ams::pm::impl {
constinit std::atomic<bool> g_application_hook; constinit std::atomic<bool> g_application_hook;
/* Forward declarations. */ /* Forward declarations. */
Result LaunchProcess(os::WaitableManagerType &waitable_manager, const LaunchProcessArgs &args); Result LaunchProcess(os::MultiWaitType &multi_wait, const LaunchProcessArgs &args);
void OnProcessSignaled(ProcessListAccessor &list, ProcessInfo *process_info); void OnProcessSignaled(ProcessListAccessor &list, ProcessInfo *process_info);
/* Helpers. */ /* Helpers. */
void ProcessTrackingMain(void *arg) { void ProcessTrackingMain(void *arg) {
/* This is the main loop of the process tracking thread. */ /* This is the main loop of the process tracking thread. */
/* Setup waitable manager. */ /* Setup multi wait/holders. */
os::WaitableManagerType process_waitable_manager; os::MultiWaitType process_multi_wait;
os::WaitableHolderType start_event_holder; os::MultiWaitHolderType start_event_holder;
os::InitializeWaitableManager(std::addressof(process_waitable_manager)); os::InitializeMultiWait(std::addressof(process_multi_wait));
os::InitializeWaitableHolder(std::addressof(start_event_holder), g_process_launch_start_event.GetBase()); os::InitializeMultiWaitHolder(std::addressof(start_event_holder), g_process_launch_start_event.GetBase());
os::LinkWaitableHolder(std::addressof(process_waitable_manager), std::addressof(start_event_holder)); os::LinkMultiWaitHolder(std::addressof(process_multi_wait), std::addressof(start_event_holder));
while (true) { while (true) {
auto signaled_holder = os::WaitAny(std::addressof(process_waitable_manager)); auto signaled_holder = os::WaitAny(std::addressof(process_multi_wait));
if (signaled_holder == &start_event_holder) { if (signaled_holder == &start_event_holder) {
/* Launch start event signaled. */ /* Launch start event signaled. */
/* TryWait will clear signaled, preventing duplicate notifications. */ /* TryWait will clear signaled, preventing duplicate notifications. */
if (g_process_launch_start_event.TryWait()) { if (g_process_launch_start_event.TryWait()) {
g_process_launch_result = LaunchProcess(process_waitable_manager, g_process_launch_args); g_process_launch_result = LaunchProcess(process_multi_wait, g_process_launch_args);
g_process_launch_finish_event.Signal(); g_process_launch_finish_event.Signal();
} }
} else { } else {
/* Some process was signaled. */ /* Some process was signaled. */
ProcessListAccessor list(g_process_list); ProcessListAccessor list(g_process_list);
OnProcessSignaled(list, reinterpret_cast<ProcessInfo *>(os::GetWaitableHolderUserData(signaled_holder))); OnProcessSignaled(list, reinterpret_cast<ProcessInfo *>(os::GetMultiWaitHolderUserData(signaled_holder)));
} }
} }
} }
@ -220,7 +220,7 @@ namespace ams::pm::impl {
g_process_info_allocator.FreeProcessInfo(process_info); g_process_info_allocator.FreeProcessInfo(process_info);
} }
Result LaunchProcess(os::WaitableManagerType &waitable_manager, const LaunchProcessArgs &args) { Result LaunchProcess(os::MultiWaitType &multi_wait, const LaunchProcessArgs &args) {
/* Get Program Info. */ /* Get Program Info. */
ldr::ProgramInfo program_info; ldr::ProgramInfo program_info;
cfg::OverrideStatus override_status; cfg::OverrideStatus override_status;
@ -260,7 +260,7 @@ namespace ams::pm::impl {
{ {
ProcessListAccessor list(g_process_list); ProcessListAccessor list(g_process_list);
list->push_back(*process_info); list->push_back(*process_info);
process_info->LinkToWaitableManager(waitable_manager); process_info->LinkToMultiWait(multi_wait);
} }
/* Prevent resource leakage if register fails. */ /* Prevent resource leakage if register fails. */
@ -362,7 +362,7 @@ namespace ams::pm::impl {
process_info->ClearUnhandledException(); process_info->ClearUnhandledException();
break; break;
case svc::ProcessState_Terminated: case svc::ProcessState_Terminated:
/* Free process resources, unlink from waitable manager. */ /* Free process resources, unlink from multi wait. */
process_info->Cleanup(); process_info->Cleanup();
if (hos::GetVersion() < hos::Version_5_0_0 && process_info->ShouldSignalOnExit()) { if (hos::GetVersion() < hos::Version_5_0_0 && process_info->ShouldSignalOnExit()) {

View file

@ -47,7 +47,7 @@ namespace ams::sm {
private: private:
struct Entry { struct Entry {
sm::ServiceName service_name{sm::InvalidServiceName}; sm::ServiceName service_name{sm::InvalidServiceName};
tipc::WaitableObject object{}; tipc::ObjectHolder object{};
u8 message_buffer[svc::ipc::MessageBufferSize]; u8 message_buffer[svc::ipc::MessageBufferSize];
}; };
private: private:
@ -83,7 +83,7 @@ namespace ams::sm {
return tipc::ResultRequestDeferred(); return tipc::ResultRequestDeferred();
} }
void ProcessRegisterRetry(tipc::WaitableObject &object) { void ProcessRegisterRetry(tipc::ObjectHolder &object) {
/* Verify that we have a processing entry. */ /* Verify that we have a processing entry. */
AMS_ABORT_UNLESS(m_processing_entry != nullptr); AMS_ABORT_UNLESS(m_processing_entry != nullptr);