os: adopt multiwait naming over waitable
This commit is contained in:
@@ -42,10 +42,10 @@ namespace ams::ddsf {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize waitable manager/holder. */
|
||||
os::InitializeWaitableManager(std::addressof(this->waitable_manager));
|
||||
os::InitializeWaitableHolder(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));
|
||||
/* Initialize multi wait/holder. */
|
||||
os::InitializeMultiWait(std::addressof(this->multi_wait));
|
||||
os::InitializeMultiWaitHolder(std::addressof(this->loop_control_event_holder), this->loop_control_event.GetBase());
|
||||
os::LinkMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->loop_control_event_holder));
|
||||
|
||||
this->is_initialized = true;
|
||||
}
|
||||
@@ -58,10 +58,10 @@ namespace ams::ddsf {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finalize waitable manager/holder. */
|
||||
os::UnlinkWaitableHolder(std::addressof(this->loop_control_event_holder));
|
||||
os::FinalizeWaitableHolder(std::addressof(this->loop_control_event_holder));
|
||||
os::FinalizeWaitableManager(std::addressof(this->waitable_manager));
|
||||
/* Finalize multi wait/holder. */
|
||||
os::UnlinkMultiWaitHolder(std::addressof(this->loop_control_event_holder));
|
||||
os::FinalizeMultiWaitHolder(std::addressof(this->loop_control_event_holder));
|
||||
os::FinalizeMultiWait(std::addressof(this->multi_wait));
|
||||
|
||||
this->is_initialized = false;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ namespace ams::ddsf {
|
||||
/* Process the command. */
|
||||
switch (params->command) {
|
||||
case LoopControlCommand::Register:
|
||||
params->target->Link(std::addressof(this->waitable_manager));
|
||||
params->target->Link(std::addressof(this->multi_wait));
|
||||
break;
|
||||
case LoopControlCommand::Unregister:
|
||||
params->target->Unlink();
|
||||
@@ -180,7 +180,7 @@ namespace ams::ddsf {
|
||||
bool should_terminate = false;
|
||||
while (!should_terminate) {
|
||||
/* 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);
|
||||
|
||||
/* Check if we have a request to handle. */
|
||||
|
||||
@@ -97,13 +97,13 @@ namespace ams::erpt::srv {
|
||||
psc::PmModule pm_module;
|
||||
psc::PmState pm_state;
|
||||
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));
|
||||
|
||||
os::InitializeWaitableHolder(std::addressof(module_event_holder), pm_module.GetEventPointer()->GetBase());
|
||||
os::SetWaitableHolderUserData(std::addressof(module_event_holder), static_cast<uintptr_t>(psc::PmModuleId_Erpt));
|
||||
this->AddUserWaitableHolder(std::addressof(module_event_holder));
|
||||
os::InitializeMultiWaitHolder(std::addressof(module_event_holder), pm_module.GetEventPointer()->GetBase());
|
||||
os::SetMultiWaitHolderUserData(std::addressof(module_event_holder), static_cast<uintptr_t>(psc::PmModuleId_Erpt));
|
||||
this->AddUserMultiWaitHolder(std::addressof(module_event_holder));
|
||||
|
||||
while (true) {
|
||||
/* 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 {
|
||||
AMS_ASSERT(false);
|
||||
}
|
||||
this->AddUserWaitableHolder(signaled_holder);
|
||||
this->AddUserMultiWaitHolder(signaled_holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,22 +276,22 @@ namespace ams::htclow::driver {
|
||||
/* Get the state change event. */
|
||||
os::SystemEventType *state_change_event = g_ds_client.GetStateChangeEvent();
|
||||
|
||||
/* Setup waitable manager. */
|
||||
os::WaitableManagerType manager;
|
||||
os::InitializeWaitableManager(std::addressof(manager));
|
||||
/* Setup multi wait. */
|
||||
os::MultiWaitType multi_wait;
|
||||
os::InitializeMultiWait(std::addressof(multi_wait));
|
||||
|
||||
/* Link waitable holders. */
|
||||
os::WaitableHolderType state_change_holder;
|
||||
os::WaitableHolderType break_holder;
|
||||
os::InitializeWaitableHolder(std::addressof(state_change_holder), state_change_event);
|
||||
os::LinkWaitableHolder(std::addressof(manager), std::addressof(state_change_holder));
|
||||
os::InitializeWaitableHolder(std::addressof(break_holder), g_usb_break_event.GetBase());
|
||||
os::LinkWaitableHolder(std::addressof(manager), std::addressof(break_holder));
|
||||
/* Link multi wait holders. */
|
||||
os::MultiWaitHolderType state_change_holder;
|
||||
os::MultiWaitHolderType break_holder;
|
||||
os::InitializeMultiWaitHolder(std::addressof(state_change_holder), state_change_event);
|
||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(state_change_holder));
|
||||
os::InitializeMultiWaitHolder(std::addressof(break_holder), g_usb_break_event.GetBase());
|
||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(break_holder));
|
||||
|
||||
/* Loop forever. */
|
||||
while (true) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -320,12 +320,12 @@ namespace ams::htclow::driver {
|
||||
g_usb_break_event.Clear();
|
||||
|
||||
/* Unlink all holders. */
|
||||
os::UnlinkAllWaitableHolder(std::addressof(manager));
|
||||
os::UnlinkAllMultiWaitHolder(std::addressof(multi_wait));
|
||||
|
||||
/* Finalize the waitable holders and manager. */
|
||||
os::FinalizeWaitableHolder(std::addressof(break_holder));
|
||||
os::FinalizeWaitableHolder(std::addressof(state_change_holder));
|
||||
os::FinalizeWaitableManager(std::addressof(manager));
|
||||
/* Finalize the multi wait/holders. */
|
||||
os::FinalizeMultiWaitHolder(std::addressof(break_holder));
|
||||
os::FinalizeMultiWaitHolder(std::addressof(state_change_holder));
|
||||
os::FinalizeMultiWait(std::addressof(multi_wait));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ams::lm::srv {
|
||||
|
||||
constinit util::TypedStorage<psc::PmModule> g_pm_module_storage;
|
||||
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 };
|
||||
|
||||
@@ -67,15 +67,15 @@ namespace ams::lm::srv {
|
||||
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));
|
||||
|
||||
/* Create the psc module waitable holder. */
|
||||
os::InitializeWaitableHolder(std::addressof(g_pm_module_holder), g_pm_module->GetEventPointer()->GetBase());
|
||||
os::SetWaitableHolderUserData(std::addressof(g_pm_module_holder), psc::PmModuleId_Lm);
|
||||
/* Create the psc module multi wait holder. */
|
||||
os::InitializeMultiWaitHolder(std::addressof(g_pm_module_holder), g_pm_module->GetEventPointer()->GetBase());
|
||||
os::SetMultiWaitHolderUserData(std::addressof(g_pm_module_holder), psc::PmModuleId_Lm);
|
||||
|
||||
/* Create the server manager. */
|
||||
g_server_manager = util::ConstructAt(g_server_manager_storage);
|
||||
|
||||
/* 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. */
|
||||
R_ABORT_UNLESS(g_server_manager->RegisterObjectForServer(g_log_service_object.GetShared(), LogServiceName, LogSessionCountMax));
|
||||
@@ -100,7 +100,7 @@ namespace ams::lm::srv {
|
||||
} else {
|
||||
/* If pm module, clear the event. */
|
||||
g_pm_module->GetEventPointer()->Clear();
|
||||
g_server_manager->AddUserWaitableHolder(signaled_holder);
|
||||
g_server_manager->AddUserMultiWaitHolder(signaled_holder);
|
||||
|
||||
/* Get the power state. */
|
||||
psc::PmState pm_state;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_inter_process_event.hpp"
|
||||
#include "os_inter_process_event_impl.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ams::os::impl {
|
||||
event->auto_clear = (clear_mode == EventClearMode_AutoClear);
|
||||
|
||||
/* Create the waitlist node. */
|
||||
util::ConstructAt(event->waitable_object_list_storage);
|
||||
util::ConstructAt(event->multi_wait_object_list_storage);
|
||||
|
||||
/* Set state. */
|
||||
event->state = InterProcessEventType::State_Initialized;
|
||||
@@ -71,7 +71,7 @@ namespace ams::os::impl {
|
||||
}
|
||||
|
||||
/* Destroy the waitlist. */
|
||||
util::DestroyAt(event->waitable_object_list_storage);
|
||||
util::DestroyAt(event->multi_wait_object_list_storage);
|
||||
}
|
||||
|
||||
void AttachInterProcessEvent(InterProcessEventType *event, Handle read_handle, bool read_handle_managed, Handle write_handle, bool write_handle_managed, EventClearMode clear_mode) {
|
||||
|
||||
@@ -36,6 +36,6 @@ namespace ams::os::impl {
|
||||
Handle GetReadableHandleOfInterProcessEvent(const InterProcessEventType *event);
|
||||
Handle GetWritableHandleOfInterProcessEvent(const InterProcessEventType *event);
|
||||
|
||||
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, InterProcessEventType *event);
|
||||
void InitializeMultiWaitHolder(MultiWaitHolderType *multi_wait_holder, InterProcessEventType *event);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,21 +18,21 @@
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableObjectList;
|
||||
class WaitableManagerImpl;
|
||||
class MultiWaitObjectList;
|
||||
class MultiWaitImpl;
|
||||
|
||||
class WaitableHolderBase {
|
||||
class MultiWaitHolderBase {
|
||||
private:
|
||||
WaitableManagerImpl *manager = nullptr;
|
||||
MultiWaitImpl *multi_wait = nullptr;
|
||||
public:
|
||||
util::IntrusiveListNode manager_node;
|
||||
util::IntrusiveListNode multi_wait_node;
|
||||
util::IntrusiveListNode object_list_node;
|
||||
public:
|
||||
/* Gets whether the held waitable is currently signaled. */
|
||||
/* Gets whether the held object is currently signaled. */
|
||||
virtual TriBool IsSignaled() const = 0;
|
||||
/* Adds to manager's object list, returns is signaled. */
|
||||
/* Adds to multi wait's object list, returns is signaled. */
|
||||
virtual TriBool LinkToObjectList() = 0;
|
||||
/* Removes from the manager's object list. */
|
||||
/* Removes from the multi wait's object list. */
|
||||
virtual void UnlinkFromObjectList() = 0;
|
||||
/* Gets handle to output, returns INVALID_HANDLE on failure. */
|
||||
virtual Handle GetHandle() const = 0;
|
||||
@@ -41,21 +41,21 @@ namespace ams::os::impl {
|
||||
return TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max());
|
||||
}
|
||||
|
||||
/* Interface with manager. */
|
||||
void SetManager(WaitableManagerImpl *m) {
|
||||
this->manager = m;
|
||||
/* Interface with multi wait. */
|
||||
void SetMultiWait(MultiWaitImpl *m) {
|
||||
this->multi_wait = m;
|
||||
}
|
||||
|
||||
WaitableManagerImpl *GetManager() const {
|
||||
return this->manager;
|
||||
MultiWaitImpl *GetMultiWait() const {
|
||||
return this->multi_wait;
|
||||
}
|
||||
|
||||
bool IsLinkedToManager() const {
|
||||
return this->manager != nullptr;
|
||||
bool IsLinked() const {
|
||||
return this->multi_wait != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class WaitableHolderOfUserObject : public WaitableHolderBase {
|
||||
class MultiWaitHolderOfUserObject : public MultiWaitHolderBase {
|
||||
public:
|
||||
/* All user objects have no handle to wait on. */
|
||||
virtual Handle GetHandle() const override final {
|
||||
@@ -63,7 +63,7 @@ namespace ams::os::impl {
|
||||
}
|
||||
};
|
||||
|
||||
class WaitableHolderOfKernelObject : public WaitableHolderBase {
|
||||
class MultiWaitHolderOfKernelObject : public MultiWaitHolderBase {
|
||||
public:
|
||||
/* All kernel objects have native handles, and thus don't have object list semantics. */
|
||||
virtual TriBool LinkToObjectList() override final {
|
||||
@@ -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));
|
||||
}
|
||||
@@ -14,12 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfEvent : public WaitableHolderOfUserObject {
|
||||
class MultiWaitHolderOfEvent : public MultiWaitHolderOfUserObject {
|
||||
private:
|
||||
EventType *event;
|
||||
private:
|
||||
@@ -27,7 +27,7 @@ namespace ams::os::impl {
|
||||
return this->event->signaled ? TriBool::True : TriBool::False;
|
||||
}
|
||||
public:
|
||||
explicit WaitableHolderOfEvent(EventType *e) : event(e) { /* ... */ }
|
||||
explicit MultiWaitHolderOfEvent(EventType *e) : event(e) { /* ... */ }
|
||||
|
||||
/* IsSignaled, Link, Unlink implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -38,14 +38,14 @@ namespace ams::os::impl {
|
||||
virtual TriBool LinkToObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->event->cs_event));
|
||||
|
||||
GetReference(this->event->waitable_object_list_storage).LinkWaitableHolder(*this);
|
||||
GetReference(this->event->multi_wait_object_list_storage).LinkMultiWaitHolder(*this);
|
||||
return this->IsSignaledImpl();
|
||||
}
|
||||
|
||||
virtual void UnlinkFromObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->event->cs_event));
|
||||
|
||||
GetReference(this->event->waitable_object_list_storage).UnlinkWaitableHolder(*this);
|
||||
GetReference(this->event->multi_wait_object_list_storage).UnlinkMultiWaitHolder(*this);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfHandle : public WaitableHolderOfKernelObject {
|
||||
class MultiWaitHolderOfHandle : public MultiWaitHolderOfKernelObject {
|
||||
private:
|
||||
Handle handle;
|
||||
public:
|
||||
explicit WaitableHolderOfHandle(Handle h) : handle(h) { /* ... */ }
|
||||
explicit MultiWaitHolderOfHandle(Handle h) : handle(h) { /* ... */ }
|
||||
|
||||
/* IsSignaled, GetHandle both implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -14,16 +14,16 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_inter_process_event.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfInterProcessEvent : public WaitableHolderOfKernelObject {
|
||||
class MultiWaitHolderOfInterProcessEvent : public MultiWaitHolderOfKernelObject {
|
||||
private:
|
||||
InterProcessEventType *event;
|
||||
public:
|
||||
explicit WaitableHolderOfInterProcessEvent(InterProcessEventType *e) : event(e) { /* ... */ }
|
||||
explicit MultiWaitHolderOfInterProcessEvent(InterProcessEventType *e) : event(e) { /* ... */ }
|
||||
|
||||
/* IsSignaled, GetHandle both implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -14,12 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_waitable_holder_of_interrupt_event.hpp"
|
||||
#include "os_multiple_wait_holder_of_interrupt_event.hpp"
|
||||
#include "os_interrupt_event_impl.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
Handle WaitableHolderOfInterruptEvent::GetHandle() const {
|
||||
Handle MultiWaitHolderOfInterruptEvent::GetHandle() const {
|
||||
return GetReference(event->impl).GetHandle();
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfInterruptEvent : public WaitableHolderOfKernelObject {
|
||||
class MultiWaitHolderOfInterruptEvent : public MultiWaitHolderOfKernelObject {
|
||||
private:
|
||||
InterruptEventType *event;
|
||||
public:
|
||||
explicit WaitableHolderOfInterruptEvent(InterruptEventType *e) : event(e) { /* ... */ }
|
||||
explicit MultiWaitHolderOfInterruptEvent(InterruptEventType *e) : event(e) { /* ... */ }
|
||||
|
||||
/* IsSignaled, GetHandle both implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -14,13 +14,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
template<MessageQueueWaitType WaitType>
|
||||
class WaitableHolderOfMessageQueue : public WaitableHolderOfUserObject {
|
||||
class MultiWaitHolderOfMessageQueue : public MultiWaitHolderOfUserObject {
|
||||
static_assert(WaitType == MessageQueueWaitType::ForNotEmpty || WaitType == MessageQueueWaitType::ForNotFull);
|
||||
private:
|
||||
MessageQueueType *mq;
|
||||
@@ -37,7 +37,7 @@ namespace ams::os::impl {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline WaitableObjectList &GetObjectList() const {
|
||||
constexpr inline MultiWaitObjectList &GetObjectList() const {
|
||||
if constexpr (WaitType == MessageQueueWaitType::ForNotEmpty) {
|
||||
return GetReference(this->mq->waitlist_not_empty);
|
||||
} else if constexpr (WaitType == MessageQueueWaitType::ForNotFull) {
|
||||
@@ -47,7 +47,7 @@ namespace ams::os::impl {
|
||||
}
|
||||
}
|
||||
public:
|
||||
explicit WaitableHolderOfMessageQueue(MessageQueueType *mq) : mq(mq) { /* ... */ }
|
||||
explicit MultiWaitHolderOfMessageQueue(MessageQueueType *mq) : mq(mq) { /* ... */ }
|
||||
|
||||
/* IsSignaled, Link, Unlink implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -58,18 +58,18 @@ namespace ams::os::impl {
|
||||
virtual TriBool LinkToObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->mq->cs_queue));
|
||||
|
||||
this->GetObjectList().LinkWaitableHolder(*this);
|
||||
this->GetObjectList().LinkMultiWaitHolder(*this);
|
||||
return this->IsSignaledImpl();
|
||||
}
|
||||
|
||||
virtual void UnlinkFromObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->mq->cs_queue));
|
||||
|
||||
this->GetObjectList().UnlinkWaitableHolder(*this);
|
||||
this->GetObjectList().UnlinkMultiWaitHolder(*this);
|
||||
}
|
||||
};
|
||||
|
||||
using WaitableHolderOfMessageQueueForNotEmpty = WaitableHolderOfMessageQueue<MessageQueueWaitType::ForNotEmpty>;
|
||||
using WaitableHolderOfMessageQueueForNotFull = WaitableHolderOfMessageQueue<MessageQueueWaitType::ForNotFull>;
|
||||
using MultiWaitHolderOfMessageQueueForNotEmpty = MultiWaitHolderOfMessageQueue<MessageQueueWaitType::ForNotEmpty>;
|
||||
using MultiWaitHolderOfMessageQueueForNotFull = MultiWaitHolderOfMessageQueue<MessageQueueWaitType::ForNotFull>;
|
||||
|
||||
}
|
||||
@@ -14,12 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfSemaphore : public WaitableHolderOfUserObject {
|
||||
class MultiWaitHolderOfSemaphore : public MultiWaitHolderOfUserObject {
|
||||
private:
|
||||
SemaphoreType *semaphore;
|
||||
private:
|
||||
@@ -27,7 +27,7 @@ namespace ams::os::impl {
|
||||
return this->semaphore->count > 0 ? TriBool::True : TriBool::False;
|
||||
}
|
||||
public:
|
||||
explicit WaitableHolderOfSemaphore(SemaphoreType *s) : semaphore(s) { /* ... */ }
|
||||
explicit MultiWaitHolderOfSemaphore(SemaphoreType *s) : semaphore(s) { /* ... */ }
|
||||
|
||||
/* IsSignaled, Link, Unlink implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -38,14 +38,14 @@ namespace ams::os::impl {
|
||||
virtual TriBool LinkToObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->semaphore->cs_sema));
|
||||
|
||||
GetReference(this->semaphore->waitlist).LinkWaitableHolder(*this);
|
||||
GetReference(this->semaphore->waitlist).LinkMultiWaitHolder(*this);
|
||||
return this->IsSignaledImpl();
|
||||
}
|
||||
|
||||
virtual void UnlinkFromObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->semaphore->cs_sema));
|
||||
|
||||
GetReference(this->semaphore->waitlist).UnlinkWaitableHolder(*this);
|
||||
GetReference(this->semaphore->waitlist).UnlinkMultiWaitHolder(*this);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfThread : public WaitableHolderOfUserObject {
|
||||
class MultiWaitHolderOfThread : public MultiWaitHolderOfUserObject {
|
||||
private:
|
||||
ThreadType *thread;
|
||||
private:
|
||||
@@ -26,7 +26,7 @@ namespace ams::os::impl {
|
||||
return this->thread->state == ThreadType::State_Terminated ? TriBool::True : TriBool::False;
|
||||
}
|
||||
public:
|
||||
explicit WaitableHolderOfThread(ThreadType *t) : thread(t) { /* ... */ }
|
||||
explicit MultiWaitHolderOfThread(ThreadType *t) : thread(t) { /* ... */ }
|
||||
|
||||
/* IsSignaled, Link, Unlink implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -37,14 +37,14 @@ namespace ams::os::impl {
|
||||
virtual TriBool LinkToObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->thread->cs_thread));
|
||||
|
||||
GetReference(this->thread->waitlist).LinkWaitableHolder(*this);
|
||||
GetReference(this->thread->waitlist).LinkMultiWaitHolder(*this);
|
||||
return this->IsSignaledImpl();
|
||||
}
|
||||
|
||||
virtual void UnlinkFromObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->thread->cs_thread));
|
||||
|
||||
GetReference(this->thread->waitlist).UnlinkWaitableHolder(*this);
|
||||
GetReference(this->thread->waitlist).UnlinkMultiWaitHolder(*this);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,22 +16,22 @@
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_timer_event_helper.hpp"
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableHolderOfTimerEvent : public WaitableHolderOfUserObject {
|
||||
class MultiWaitHolderOfTimerEvent : public MultiWaitHolderOfUserObject {
|
||||
private:
|
||||
TimerEventType *event;
|
||||
private:
|
||||
TriBool IsSignaledImpl() const {
|
||||
TimeSpan cur_time = this->GetManager()->GetCurrentTime();
|
||||
TimeSpan cur_time = this->GetMultiWait()->GetCurrentTime();
|
||||
UpdateSignalStateAndRecalculateNextTimeToWakeupUnsafe(this->event, cur_time);
|
||||
return this->event->signaled ? TriBool::True : TriBool::False;
|
||||
}
|
||||
public:
|
||||
explicit WaitableHolderOfTimerEvent(TimerEventType *e) : event(e) { /* ... */ }
|
||||
explicit MultiWaitHolderOfTimerEvent(TimerEventType *e) : event(e) { /* ... */ }
|
||||
|
||||
/* IsSignaled, Link, Unlink implemented. */
|
||||
virtual TriBool IsSignaled() const override {
|
||||
@@ -42,14 +42,14 @@ namespace ams::os::impl {
|
||||
virtual TriBool LinkToObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->event->cs_timer_event));
|
||||
|
||||
GetReference(this->event->waitable_object_list_storage).LinkWaitableHolder(*this);
|
||||
GetReference(this->event->multi_wait_object_list_storage).LinkMultiWaitHolder(*this);
|
||||
return this->IsSignaledImpl();
|
||||
}
|
||||
|
||||
virtual void UnlinkFromObjectList() override {
|
||||
std::scoped_lock lk(GetReference(this->event->cs_timer_event));
|
||||
|
||||
GetReference(this->event->waitable_object_list_storage).UnlinkWaitableHolder(*this);
|
||||
GetReference(this->event->multi_wait_object_list_storage).UnlinkMultiWaitHolder(*this);
|
||||
}
|
||||
|
||||
/* Gets the amount of time remaining until this wakes up. */
|
||||
@@ -14,17 +14,17 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_waitable_manager_impl.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_impl.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
#include "os_tick_manager.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
Result WaitableManagerImpl::WaitAnyImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
|
||||
Result MultiWaitImpl::WaitAnyImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
|
||||
/* Prepare for processing. */
|
||||
this->signaled_holder = nullptr;
|
||||
this->target_impl.SetCurrentThreadHandleForCancelWait();
|
||||
WaitableHolderBase *holder = this->LinkHoldersToObjectList();
|
||||
MultiWaitHolderBase *holder = this->LinkHoldersToObjectList();
|
||||
|
||||
/* Check if we've been signaled. */
|
||||
{
|
||||
@@ -59,9 +59,9 @@ namespace ams::os::impl {
|
||||
return wait_result;
|
||||
}
|
||||
|
||||
Result WaitableManagerImpl::WaitAnyHandleImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
|
||||
Result MultiWaitImpl::WaitAnyHandleImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target) {
|
||||
Handle object_handles[MaximumHandleCount];
|
||||
WaitableHolderBase *objects[MaximumHandleCount];
|
||||
MultiWaitHolderBase *objects[MaximumHandleCount];
|
||||
|
||||
const s32 count = this->BuildHandleArray(object_handles, objects, MaximumHandleCount);
|
||||
const TimeSpan end_time = infinite ? TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()) : GetCurrentTick().ToTimeSpan() + timeout;
|
||||
@@ -70,7 +70,7 @@ namespace ams::os::impl {
|
||||
this->current_time = GetCurrentTick().ToTimeSpan();
|
||||
|
||||
TimeSpan min_timeout = 0;
|
||||
WaitableHolderBase *min_timeout_object = this->RecalculateNextTimeout(&min_timeout, end_time);
|
||||
MultiWaitHolderBase *min_timeout_object = this->RecalculateNextTimeout(&min_timeout, end_time);
|
||||
|
||||
s32 index = WaitInvalid;
|
||||
Result wait_result = ResultSuccess();
|
||||
@@ -129,16 +129,17 @@ namespace ams::os::impl {
|
||||
*out = objects[index];
|
||||
return wait_result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
reply_target = svc::InvalidHandle;
|
||||
}
|
||||
}
|
||||
|
||||
s32 WaitableManagerImpl::BuildHandleArray(Handle out_handles[], WaitableHolderBase *out_objects[], s32 num) {
|
||||
s32 MultiWaitImpl::BuildHandleArray(Handle out_handles[], MultiWaitHolderBase *out_objects[], s32 num) {
|
||||
s32 count = 0;
|
||||
|
||||
for (WaitableHolderBase &holder_base : this->waitable_list) {
|
||||
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
|
||||
if (Handle handle = holder_base.GetHandle(); handle != svc::InvalidHandle) {
|
||||
AMS_ASSERT(count < num);
|
||||
|
||||
@@ -151,10 +152,10 @@ namespace ams::os::impl {
|
||||
return count;
|
||||
}
|
||||
|
||||
WaitableHolderBase *WaitableManagerImpl::LinkHoldersToObjectList() {
|
||||
WaitableHolderBase *signaled_holder = nullptr;
|
||||
MultiWaitHolderBase *MultiWaitImpl::LinkHoldersToObjectList() {
|
||||
MultiWaitHolderBase *signaled_holder = nullptr;
|
||||
|
||||
for (WaitableHolderBase &holder_base : this->waitable_list) {
|
||||
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
|
||||
TriBool is_signaled = holder_base.LinkToObjectList();
|
||||
|
||||
if (signaled_holder == nullptr && is_signaled == TriBool::True) {
|
||||
@@ -165,17 +166,17 @@ namespace ams::os::impl {
|
||||
return signaled_holder;
|
||||
}
|
||||
|
||||
void WaitableManagerImpl::UnlinkHoldersFromObjectList() {
|
||||
for (WaitableHolderBase &holder_base : this->waitable_list) {
|
||||
void MultiWaitImpl::UnlinkHoldersFromObjectList() {
|
||||
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
|
||||
holder_base.UnlinkFromObjectList();
|
||||
}
|
||||
}
|
||||
|
||||
WaitableHolderBase *WaitableManagerImpl::RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time) {
|
||||
WaitableHolderBase *min_timeout_holder = nullptr;
|
||||
MultiWaitHolderBase *MultiWaitImpl::RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time) {
|
||||
MultiWaitHolderBase *min_timeout_holder = nullptr;
|
||||
TimeSpan min_time = end_time;
|
||||
|
||||
for (WaitableHolderBase &holder_base : this->waitable_list) {
|
||||
for (MultiWaitHolderBase &holder_base : this->multi_wait_list) {
|
||||
if (const TimeSpan cur_time = holder_base.GetAbsoluteWakeupTime(); cur_time < min_time) {
|
||||
min_timeout_holder = &holder_base;
|
||||
min_time = cur_time;
|
||||
@@ -190,7 +191,7 @@ namespace ams::os::impl {
|
||||
return min_timeout_holder;
|
||||
}
|
||||
|
||||
void WaitableManagerImpl::SignalAndWakeupThread(WaitableHolderBase *holder_base) {
|
||||
void MultiWaitImpl::SignalAndWakeupThread(MultiWaitHolderBase *holder_base) {
|
||||
std::scoped_lock lk(this->cs_wait);
|
||||
|
||||
if (this->signaled_holder == nullptr) {
|
||||
@@ -14,41 +14,41 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
#include "os_waitable_manager_target_impl.os.horizon.hpp"
|
||||
#include "os_multiple_wait_target_impl.os.horizon.hpp"
|
||||
#else
|
||||
#error "Unknown OS for ams::os::WaitableManagerTargetImpl"
|
||||
#error "Unknown OS for ams::os::MultiWaitTargetImpl"
|
||||
#endif
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableManagerImpl {
|
||||
class MultiWaitImpl {
|
||||
public:
|
||||
static constexpr size_t MaximumHandleCount = WaitableManagerTargetImpl::MaximumHandleCount;
|
||||
static constexpr size_t MaximumHandleCount = MultiWaitTargetImpl::MaximumHandleCount;
|
||||
static constexpr s32 WaitInvalid = -3;
|
||||
static constexpr s32 WaitCancelled = -2;
|
||||
static constexpr s32 WaitTimedOut = -1;
|
||||
using ListType = util::IntrusiveListMemberTraits<&WaitableHolderBase::manager_node>::ListType;
|
||||
using MultiWaitList = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::multi_wait_node>::ListType;
|
||||
private:
|
||||
ListType waitable_list;
|
||||
WaitableHolderBase *signaled_holder;
|
||||
MultiWaitList multi_wait_list;
|
||||
MultiWaitHolderBase *signaled_holder;
|
||||
TimeSpan current_time;
|
||||
InternalCriticalSection cs_wait;
|
||||
WaitableManagerTargetImpl target_impl;
|
||||
MultiWaitTargetImpl target_impl;
|
||||
private:
|
||||
Result WaitAnyImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
|
||||
Result WaitAnyHandleImpl(WaitableHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
|
||||
s32 BuildHandleArray(Handle out_handles[], WaitableHolderBase *out_objects[], s32 num);
|
||||
Result WaitAnyImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
|
||||
Result WaitAnyHandleImpl(MultiWaitHolderBase **out, bool infinite, TimeSpan timeout, bool reply, Handle reply_target);
|
||||
s32 BuildHandleArray(Handle out_handles[], MultiWaitHolderBase *out_objects[], s32 num);
|
||||
|
||||
WaitableHolderBase *LinkHoldersToObjectList();
|
||||
MultiWaitHolderBase *LinkHoldersToObjectList();
|
||||
void UnlinkHoldersFromObjectList();
|
||||
|
||||
WaitableHolderBase *RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time);
|
||||
MultiWaitHolderBase *RecalculateNextTimeout(TimeSpan *out_min_timeout, TimeSpan end_time);
|
||||
|
||||
WaitableHolderBase *WaitAnyImpl(bool infinite, TimeSpan timeout) {
|
||||
WaitableHolderBase *holder = nullptr;
|
||||
MultiWaitHolderBase *WaitAnyImpl(bool infinite, TimeSpan timeout) {
|
||||
MultiWaitHolderBase *holder = nullptr;
|
||||
|
||||
const Result wait_result = this->WaitAnyImpl(std::addressof(holder), infinite, timeout, false, svc::InvalidHandle);
|
||||
R_ASSERT(wait_result);
|
||||
@@ -58,48 +58,48 @@ namespace ams::os::impl {
|
||||
}
|
||||
public:
|
||||
/* Wait. */
|
||||
WaitableHolderBase *WaitAny() {
|
||||
MultiWaitHolderBase *WaitAny() {
|
||||
return this->WaitAnyImpl(true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()));
|
||||
}
|
||||
|
||||
WaitableHolderBase *TryWaitAny() {
|
||||
MultiWaitHolderBase *TryWaitAny() {
|
||||
return this->WaitAnyImpl(false, TimeSpan(0));
|
||||
}
|
||||
|
||||
WaitableHolderBase *TimedWaitAny(TimeSpan ts) {
|
||||
MultiWaitHolderBase *TimedWaitAny(TimeSpan ts) {
|
||||
return this->WaitAnyImpl(false, ts);
|
||||
}
|
||||
|
||||
Result ReplyAndReceive(WaitableHolderBase **out, Handle reply_target) {
|
||||
Result ReplyAndReceive(MultiWaitHolderBase **out, Handle reply_target) {
|
||||
return this->WaitAnyImpl(out, true, TimeSpan::FromNanoSeconds(std::numeric_limits<s64>::max()), true, reply_target);
|
||||
}
|
||||
|
||||
/* List management. */
|
||||
bool IsEmpty() const {
|
||||
return this->waitable_list.empty();
|
||||
return this->multi_wait_list.empty();
|
||||
}
|
||||
|
||||
void LinkWaitableHolder(WaitableHolderBase &holder_base) {
|
||||
this->waitable_list.push_back(holder_base);
|
||||
void LinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
|
||||
this->multi_wait_list.push_back(holder_base);
|
||||
}
|
||||
|
||||
void UnlinkWaitableHolder(WaitableHolderBase &holder_base) {
|
||||
this->waitable_list.erase(this->waitable_list.iterator_to(holder_base));
|
||||
void UnlinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
|
||||
this->multi_wait_list.erase(this->multi_wait_list.iterator_to(holder_base));
|
||||
}
|
||||
|
||||
void UnlinkAll() {
|
||||
while (!this->IsEmpty()) {
|
||||
this->waitable_list.front().SetManager(nullptr);
|
||||
this->waitable_list.pop_front();
|
||||
this->multi_wait_list.front().SetMultiWait(nullptr);
|
||||
this->multi_wait_list.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void MoveAllFrom(WaitableManagerImpl &other) {
|
||||
/* Set manager for all of the other's waitables. */
|
||||
for (auto &w : other.waitable_list) {
|
||||
w.SetManager(this);
|
||||
void MoveAllFrom(MultiWaitImpl &other) {
|
||||
/* Set ourselves as multi wait for all of the other's holders. */
|
||||
for (auto &w : other.multi_wait_list) {
|
||||
w.SetMultiWait(this);
|
||||
}
|
||||
this->waitable_list.splice(this->waitable_list.end(), other.waitable_list);
|
||||
this->multi_wait_list.splice(this->multi_wait_list.end(), other.multi_wait_list);
|
||||
}
|
||||
|
||||
/* Other. */
|
||||
@@ -107,7 +107,7 @@ namespace ams::os::impl {
|
||||
return this->current_time;
|
||||
}
|
||||
|
||||
void SignalAndWakeupThread(WaitableHolderBase *holder_base);
|
||||
void SignalAndWakeupThread(MultiWaitHolderBase *holder_base);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -14,26 +14,26 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_manager_impl.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_impl.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableObjectList {
|
||||
class MultiWaitObjectList {
|
||||
public:
|
||||
using ListType = util::IntrusiveListMemberTraits<&WaitableHolderBase::object_list_node>::ListType;
|
||||
using ListType = util::IntrusiveListMemberTraits<&MultiWaitHolderBase::object_list_node>::ListType;
|
||||
private:
|
||||
ListType object_list;
|
||||
public:
|
||||
void SignalAllThreads() {
|
||||
for (WaitableHolderBase &holder_base : this->object_list) {
|
||||
holder_base.GetManager()->SignalAndWakeupThread(&holder_base);
|
||||
for (MultiWaitHolderBase &holder_base : this->object_list) {
|
||||
holder_base.GetMultiWait()->SignalAndWakeupThread(&holder_base);
|
||||
}
|
||||
}
|
||||
|
||||
void BroadcastAllThreads() {
|
||||
for (WaitableHolderBase &holder_base : this->object_list) {
|
||||
holder_base.GetManager()->SignalAndWakeupThread(nullptr);
|
||||
for (MultiWaitHolderBase &holder_base : this->object_list) {
|
||||
holder_base.GetMultiWait()->SignalAndWakeupThread(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ namespace ams::os::impl {
|
||||
return this->object_list.empty();
|
||||
}
|
||||
|
||||
void LinkWaitableHolder(WaitableHolderBase &holder_base) {
|
||||
void LinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
|
||||
this->object_list.push_back(holder_base);
|
||||
}
|
||||
|
||||
void UnlinkWaitableHolder(WaitableHolderBase &holder_base) {
|
||||
void UnlinkMultiWaitHolder(MultiWaitHolderBase &holder_base) {
|
||||
this->object_list.erase(this->object_list.iterator_to(holder_base));
|
||||
}
|
||||
};
|
||||
@@ -14,18 +14,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_manager_impl.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_impl.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
Result WaitableManagerHorizonImpl::WaitSynchronizationN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns) {
|
||||
Result MultiWaitHorizonImpl::WaitSynchronizationN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns) {
|
||||
AMS_ASSERT(!(num == 0 && ns == 0));
|
||||
s32 index = WaitableManagerImpl::WaitInvalid;
|
||||
s32 index = MultiWaitImpl::WaitInvalid;
|
||||
|
||||
R_TRY_CATCH(svc::WaitSynchronization(std::addressof(index), static_cast<const svc::Handle *>(arr), num, ns)) {
|
||||
R_CATCH(svc::ResultTimedOut) { index = WaitableManagerImpl::WaitTimedOut; }
|
||||
R_CATCH(svc::ResultCancelled) { index = WaitableManagerImpl::WaitCancelled; }
|
||||
R_CATCH(svc::ResultTimedOut) { index = MultiWaitImpl::WaitTimedOut; }
|
||||
R_CATCH(svc::ResultCancelled) { index = MultiWaitImpl::WaitCancelled; }
|
||||
/* All other results are critical errors. */
|
||||
/* svc::ResultThreadTerminating */
|
||||
/* svc::ResultInvalidHandle. */
|
||||
@@ -37,17 +37,17 @@ namespace ams::os::impl {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result WaitableManagerHorizonImpl::ReplyAndReceiveN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns, Handle reply_target) {
|
||||
Result MultiWaitHorizonImpl::ReplyAndReceiveN(s32 *out_index, s32 num, Handle arr[], s32 array_size, s64 ns, Handle reply_target) {
|
||||
/* NOTE: Nintendo does not initialize this value, which seems like it can cause incorrect behavior. */
|
||||
s32 index = WaitableManagerImpl::WaitInvalid;
|
||||
static_assert(WaitableManagerImpl::WaitInvalid != -1);
|
||||
s32 index = MultiWaitImpl::WaitInvalid;
|
||||
static_assert(MultiWaitImpl::WaitInvalid != -1);
|
||||
|
||||
R_TRY_CATCH(svc::ReplyAndReceive(std::addressof(index), arr, num, reply_target, ns)) {
|
||||
R_CATCH(svc::ResultTimedOut) { *out_index = WaitableManagerImpl::WaitTimedOut; return R_CURRENT_RESULT; }
|
||||
R_CATCH(svc::ResultCancelled) { *out_index = WaitableManagerImpl::WaitCancelled; return R_CURRENT_RESULT; }
|
||||
R_CATCH(svc::ResultTimedOut) { *out_index = MultiWaitImpl::WaitTimedOut; return R_CURRENT_RESULT; }
|
||||
R_CATCH(svc::ResultCancelled) { *out_index = MultiWaitImpl::WaitCancelled; return R_CURRENT_RESULT; }
|
||||
R_CATCH(svc::ResultSessionClosed) {
|
||||
if (index == -1) {
|
||||
*out_index = WaitableManagerImpl::WaitInvalid;
|
||||
*out_index = MultiWaitImpl::WaitInvalid;
|
||||
return os::ResultSessionClosedForReply();
|
||||
} else {
|
||||
*out_index = index;
|
||||
@@ -64,7 +64,7 @@ namespace ams::os::impl {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void WaitableManagerHorizonImpl::CancelWait() {
|
||||
void MultiWaitHorizonImpl::CancelWait() {
|
||||
R_ABORT_UNLESS(svc::CancelSynchronization(this->handle));
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
class WaitableManagerHorizonImpl {
|
||||
class MultiWaitHorizonImpl {
|
||||
public:
|
||||
static constexpr size_t MaximumHandleCount = static_cast<size_t>(ams::svc::ArgumentHandleCountMax);
|
||||
private:
|
||||
@@ -63,6 +63,6 @@ namespace ams::os::impl {
|
||||
}
|
||||
};
|
||||
|
||||
using WaitableManagerTargetImpl = WaitableManagerHorizonImpl;
|
||||
using MultiWaitTargetImpl = MultiWaitHorizonImpl;
|
||||
|
||||
}
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "os_thread_manager.hpp"
|
||||
#include "os_waitable_manager_impl.hpp"
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_holder_impl.hpp"
|
||||
#include "os_waitable_object_list.hpp"
|
||||
#include "os_multiple_wait_impl.hpp"
|
||||
#include "os_multiple_wait_holder_base.hpp"
|
||||
#include "os_multiple_wait_holder_impl.hpp"
|
||||
#include "os_multiple_wait_object_list.hpp"
|
||||
#include "os_utility.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "os_waitable_holder_base.hpp"
|
||||
#include "os_waitable_manager_impl.hpp"
|
||||
|
||||
namespace ams::os::impl {
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_timeout_helper.hpp"
|
||||
#include "impl/os_waitable_object_list.hpp"
|
||||
#include "impl/os_waitable_holder_impl.hpp"
|
||||
#include "impl/os_multiple_wait_object_list.hpp"
|
||||
#include "impl/os_multiple_wait_holder_impl.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
@@ -40,8 +40,8 @@ namespace ams::os {
|
||||
util::ConstructAt(event->cs_event);
|
||||
util::ConstructAt(event->cv_signaled);
|
||||
|
||||
/* Initialize the waitable object list. */
|
||||
util::ConstructAt(event->waitable_object_list_storage);
|
||||
/* Initialize the multi wait object list. */
|
||||
util::ConstructAt(event->multi_wait_object_list_storage);
|
||||
|
||||
/* Initialize member variables. */
|
||||
event->signaled = signaled;
|
||||
@@ -61,7 +61,7 @@ namespace ams::os {
|
||||
event->state = EventType::State_NotInitialized;
|
||||
|
||||
/* 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->cs_event);
|
||||
}
|
||||
@@ -89,7 +89,7 @@ namespace ams::os {
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
@@ -160,12 +160,12 @@ namespace ams::os {
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_interrupt_event_impl.hpp"
|
||||
#include "impl/os_waitable_holder_impl.hpp"
|
||||
#include "impl/os_waitable_object_list.hpp"
|
||||
#include "impl/os_multiple_wait_holder_impl.hpp"
|
||||
#include "impl/os_multiple_wait_object_list.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
@@ -62,12 +62,12 @@ namespace ams::os {
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_timeout_helper.hpp"
|
||||
#include "impl/os_waitable_object_list.hpp"
|
||||
#include "impl/os_waitable_holder_impl.hpp"
|
||||
#include "impl/os_multiple_wait_object_list.hpp"
|
||||
#include "impl/os_multiple_wait_holder_impl.hpp"
|
||||
#include "impl/os_message_queue_helper.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
@@ -319,20 +319,20 @@ namespace ams::os {
|
||||
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);
|
||||
|
||||
switch (type) {
|
||||
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;
|
||||
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;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
waitable_holder->user_data = 0;
|
||||
multi_wait_holder->user_data = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
152
libraries/libstratosphere/source/os/os_multiple_wait.cpp
Normal file
152
libraries/libstratosphere/source/os/os_multiple_wait.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,32 +14,32 @@
|
||||
* 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"
|
||||
#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::WaitableManagerImpl &GetWaitableManagerImpl(WaitableManagerType *manager) {
|
||||
return GetReference(manager->impl_storage);
|
||||
ALWAYS_INLINE impl::MultiWaitImpl &GetMultiWaitImpl(MultiWaitType *multi_wait) {
|
||||
return GetReference(multi_wait->impl_storage);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE WaitableHolderType *CastToWaitableHolder(impl::WaitableHolderBase *base) {
|
||||
return reinterpret_cast<WaitableHolderType *>(base);
|
||||
ALWAYS_INLINE MultiWaitHolderType *CastToMultiWaitHolder(impl::MultiWaitHolderBase *base) {
|
||||
return reinterpret_cast<MultiWaitHolderType *>(base);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result SdkReplyAndReceive(os::WaitableHolderType **out, Handle reply_target, WaitableManagerType *manager) {
|
||||
auto &impl = GetWaitableManagerImpl(manager);
|
||||
Result SdkReplyAndReceive(os::MultiWaitHolderType **out, Handle reply_target, MultiWaitType *multi_wait) {
|
||||
auto &impl = GetMultiWaitImpl(multi_wait);
|
||||
|
||||
AMS_ASSERT(manager->state == WaitableManagerType::State_Initialized);
|
||||
AMS_ASSERT(multi_wait->state == MultiWaitType::State_Initialized);
|
||||
AMS_ASSERT(!impl.IsEmpty());
|
||||
|
||||
impl::WaitableHolderBase *holder_base;
|
||||
ON_SCOPE_EXIT { *out = CastToWaitableHolder(holder_base); };
|
||||
impl::MultiWaitHolderBase *holder_base;
|
||||
ON_SCOPE_EXIT { *out = CastToMultiWaitHolder(holder_base); };
|
||||
|
||||
return impl.ReplyAndReceive(std::addressof(holder_base), reply_target);
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_waitable_object_list.hpp"
|
||||
#include "impl/os_waitable_holder_impl.hpp"
|
||||
#include "impl/os_multiple_wait_object_list.hpp"
|
||||
#include "impl/os_multiple_wait_holder_impl.hpp"
|
||||
#include "impl/os_timeout_helper.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
@@ -142,12 +142,12 @@ namespace ams::os {
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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_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) {
|
||||
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;
|
||||
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;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_thread_manager.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 {
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include "impl/os_timer_event_helper.hpp"
|
||||
#include "impl/os_tick_manager.hpp"
|
||||
#include "impl/os_timeout_helper.hpp"
|
||||
#include "impl/os_waitable_object_list.hpp"
|
||||
#include "impl/os_waitable_holder_impl.hpp"
|
||||
#include "impl/os_multiple_wait_object_list.hpp"
|
||||
#include "impl/os_multiple_wait_holder_impl.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace ams::os {
|
||||
}
|
||||
|
||||
/* 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->cv_signaled);
|
||||
|
||||
/* Initialize the waitable object list. */
|
||||
util::ConstructAt(event->waitable_object_list_storage);
|
||||
/* Initialize the multi wait object list. */
|
||||
util::ConstructAt(event->multi_wait_object_list_storage);
|
||||
|
||||
/* Initialize member variables. */
|
||||
event->clear_mode = static_cast<u8>(clear_mode);
|
||||
@@ -83,7 +83,7 @@ namespace ams::os {
|
||||
event->state = TimerEventType::State_NotInitialized;
|
||||
|
||||
/* 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->cs_timer_event);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ namespace ams::os {
|
||||
GetReference(event->cv_signaled).Broadcast();
|
||||
|
||||
/* 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();
|
||||
|
||||
/* 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();
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace ams::osdbg::impl {
|
||||
|
||||
struct ThreadTypeIlp32 {
|
||||
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];
|
||||
u8 _state;
|
||||
bool _stack_is_aliased;
|
||||
@@ -55,7 +55,7 @@ namespace ams::osdbg::impl {
|
||||
|
||||
struct ThreadTypeIlp32Version0 {
|
||||
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];
|
||||
u8 _state;
|
||||
bool _stack_is_aliased;
|
||||
@@ -82,7 +82,7 @@ namespace ams::osdbg::impl {
|
||||
|
||||
struct ThreadTypeLp64 {
|
||||
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];
|
||||
u8 _state;
|
||||
bool _stack_is_aliased;
|
||||
@@ -110,7 +110,7 @@ namespace ams::osdbg::impl {
|
||||
|
||||
struct ThreadTypeLp64Version0 {
|
||||
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];
|
||||
u8 _state;
|
||||
bool _stack_is_aliased;
|
||||
|
||||
@@ -41,12 +41,12 @@ namespace ams::sf::hipc {
|
||||
|
||||
}
|
||||
|
||||
void AttachWaitableHolderForAccept(os::WaitableHolderType *holder, Handle port) {
|
||||
return os::InitializeWaitableHolder(holder, port);
|
||||
void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, Handle port) {
|
||||
return os::InitializeMultiWaitHolder(holder, port);
|
||||
}
|
||||
|
||||
void AttachWaitableHolderForReply(os::WaitableHolderType *holder, Handle request) {
|
||||
return os::InitializeWaitableHolder(holder, request);
|
||||
void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, Handle request) {
|
||||
return os::InitializeMultiWaitHolder(holder, request);
|
||||
}
|
||||
|
||||
Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer) {
|
||||
|
||||
@@ -32,37 +32,37 @@ namespace ams::sf::hipc {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void ServerManagerBase::RegisterSessionToWaitList(ServerSession *session) {
|
||||
void ServerManagerBase::RegisterServerSessionToWait(ServerSession *session) {
|
||||
session->has_received = false;
|
||||
|
||||
/* 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) {
|
||||
std::scoped_lock lk(this->waitlist_mutex);
|
||||
os::LinkWaitableHolder(std::addressof(this->waitlist), holder);
|
||||
void ServerManagerBase::LinkToDeferredList(os::MultiWaitHolderType *holder) {
|
||||
std::scoped_lock lk(this->deferred_list_mutex);
|
||||
os::LinkMultiWaitHolder(std::addressof(this->deferred_list), holder);
|
||||
this->notify_event.Signal();
|
||||
}
|
||||
|
||||
void ServerManagerBase::ProcessWaitList() {
|
||||
std::scoped_lock lk(this->waitlist_mutex);
|
||||
os::MoveAllWaitableHolder(std::addressof(this->waitable_manager), std::addressof(this->waitlist));
|
||||
void ServerManagerBase::LinkDeferred() {
|
||||
std::scoped_lock lk(this->deferred_list_mutex);
|
||||
os::MoveAllMultiWaitHolder(std::addressof(this->multi_wait), std::addressof(this->deferred_list));
|
||||
}
|
||||
|
||||
os::WaitableHolderType *ServerManagerBase::WaitSignaled() {
|
||||
std::scoped_lock lk(this->waitable_selection_mutex);
|
||||
os::MultiWaitHolderType *ServerManagerBase::WaitSignaled() {
|
||||
std::scoped_lock lk(this->selection_mutex);
|
||||
while (true) {
|
||||
this->ProcessWaitList();
|
||||
auto selected = os::WaitAny(std::addressof(this->waitable_manager));
|
||||
this->LinkDeferred();
|
||||
auto selected = os::WaitAny(std::addressof(this->multi_wait));
|
||||
if (selected == &this->request_stop_event_holder) {
|
||||
return nullptr;
|
||||
} else if (selected == &this->notify_event_holder) {
|
||||
this->notify_event.Clear();
|
||||
} else {
|
||||
os::UnlinkWaitableHolder(selected);
|
||||
os::UnlinkMultiWaitHolder(selected);
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
@@ -76,19 +76,19 @@ namespace ams::sf::hipc {
|
||||
this->request_stop_event.Signal();
|
||||
}
|
||||
|
||||
void ServerManagerBase::AddUserWaitableHolder(os::WaitableHolderType *waitable) {
|
||||
const auto user_data_tag = static_cast<UserDataTag>(os::GetWaitableHolderUserData(waitable));
|
||||
void ServerManagerBase::AddUserMultiWaitHolder(os::MultiWaitHolderType *holder) {
|
||||
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::MitmServer);
|
||||
AMS_ABORT_UNLESS(user_data_tag != UserDataTag::Session);
|
||||
this->RegisterToWaitList(waitable);
|
||||
this->LinkToDeferredList(holder);
|
||||
}
|
||||
|
||||
Result ServerManagerBase::ProcessForServer(os::WaitableHolderType *holder) {
|
||||
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder)) == UserDataTag::Server);
|
||||
Result ServerManagerBase::ProcessForServer(os::MultiWaitHolderType *holder) {
|
||||
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder)) == UserDataTag::Server);
|
||||
|
||||
Server *server = static_cast<Server *>(holder);
|
||||
ON_SCOPE_EXIT { this->RegisterToWaitList(server); };
|
||||
ON_SCOPE_EXIT { this->LinkToDeferredList(server); };
|
||||
|
||||
/* Create new session. */
|
||||
if (server->static_object) {
|
||||
@@ -98,18 +98,18 @@ namespace ams::sf::hipc {
|
||||
}
|
||||
}
|
||||
|
||||
Result ServerManagerBase::ProcessForMitmServer(os::WaitableHolderType *holder) {
|
||||
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder)) == UserDataTag::MitmServer);
|
||||
Result ServerManagerBase::ProcessForMitmServer(os::MultiWaitHolderType *holder) {
|
||||
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder)) == UserDataTag::MitmServer);
|
||||
|
||||
Server *server = static_cast<Server *>(holder);
|
||||
ON_SCOPE_EXIT { this->RegisterToWaitList(server); };
|
||||
ON_SCOPE_EXIT { this->LinkToDeferredList(server); };
|
||||
|
||||
/* Create resources for new session. */
|
||||
return this->OnNeedsToAccept(server->index, server);
|
||||
}
|
||||
|
||||
Result ServerManagerBase::ProcessForSession(os::WaitableHolderType *holder) {
|
||||
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder)) == UserDataTag::Session);
|
||||
Result ServerManagerBase::ProcessForSession(os::MultiWaitHolderType *holder) {
|
||||
AMS_ABORT_UNLESS(static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder)) == UserDataTag::Session);
|
||||
|
||||
ServerSession *session = static_cast<ServerSession *>(holder);
|
||||
|
||||
@@ -133,8 +133,8 @@ namespace ams::sf::hipc {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ServerManagerBase::Process(os::WaitableHolderType *holder) {
|
||||
switch (static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder))) {
|
||||
Result ServerManagerBase::Process(os::MultiWaitHolderType *holder) {
|
||||
switch (static_cast<UserDataTag>(os::GetMultiWaitHolderUserData(holder))) {
|
||||
case UserDataTag::Server:
|
||||
return this->ProcessForServer(holder);
|
||||
case UserDataTag::MitmServer:
|
||||
@@ -146,12 +146,12 @@ namespace ams::sf::hipc {
|
||||
}
|
||||
|
||||
bool ServerManagerBase::WaitAndProcessImpl() {
|
||||
auto waitable = this->WaitSignaled();
|
||||
if (!waitable) {
|
||||
if (auto *signaled_holder = this->WaitSignaled(); signaled_holder != nullptr) {
|
||||
R_ABORT_UNLESS(this->Process(signaled_holder));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
R_ABORT_UNLESS(this->Process(waitable));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServerManagerBase::WaitAndProcess() {
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace ams::sf::hipc {
|
||||
|
||||
void ServerSessionManager::CloseSessionImpl(ServerSession *session) {
|
||||
const Handle session_handle = session->session_handle;
|
||||
os::FinalizeWaitableHolder(session);
|
||||
os::FinalizeMultiWaitHolder(session);
|
||||
this->DestroySession(session);
|
||||
R_ABORT_UNLESS(svcCloseHandle(session_handle));
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace ams::sf::hipc {
|
||||
session_memory->saved_message = this->GetSessionSavedMessageBuffer(session_memory);
|
||||
|
||||
/* Register to wait list. */
|
||||
this->RegisterSessionToWaitList(session_memory);
|
||||
this->RegisterServerSessionToWait(session_memory);
|
||||
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);
|
||||
|
||||
/* Register to wait list. */
|
||||
this->RegisterSessionToWaitList(session_memory);
|
||||
this->RegisterServerSessionToWait(session_memory);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace ams::sf::hipc {
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* We succeeded, so we can process future messages on this session. */
|
||||
this->RegisterSessionToWaitList(session);
|
||||
this->RegisterServerSessionToWait(session);
|
||||
return ResultSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user