mirror of
https://github.com/Atmosphere-NX/Atmosphere-libs.git
synced 2025-06-21 19:12:42 +02:00
sm: implement accurate request deferral semantics
This commit is contained in:
parent
b05ba02f04
commit
ced1312dc7
@ -128,10 +128,6 @@ namespace ams::sf::hipc {
|
|||||||
|
|
||||||
os::Mutex waitlist_mutex;
|
os::Mutex waitlist_mutex;
|
||||||
os::WaitableManagerType waitlist;
|
os::WaitableManagerType waitlist;
|
||||||
|
|
||||||
os::Mutex deferred_session_mutex;
|
|
||||||
using DeferredSessionList = typename util::IntrusiveListMemberTraits<&ServerSession::deferred_list_node>::ListType;
|
|
||||||
DeferredSessionList deferred_session_list;
|
|
||||||
private:
|
private:
|
||||||
virtual void RegisterSessionToWaitList(ServerSession *session) override final;
|
virtual void RegisterSessionToWaitList(ServerSession *session) override final;
|
||||||
void RegisterToWaitList(os::WaitableHolderType *holder);
|
void RegisterToWaitList(os::WaitableHolderType *holder);
|
||||||
@ -143,8 +139,6 @@ namespace ams::sf::hipc {
|
|||||||
Result ProcessForMitmServer(os::WaitableHolderType *holder);
|
Result ProcessForMitmServer(os::WaitableHolderType *holder);
|
||||||
Result ProcessForSession(os::WaitableHolderType *holder);
|
Result ProcessForSession(os::WaitableHolderType *holder);
|
||||||
|
|
||||||
void ProcessDeferredSessions();
|
|
||||||
|
|
||||||
template<typename Interface, auto MakeShared>
|
template<typename Interface, auto MakeShared>
|
||||||
void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) {
|
void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) {
|
||||||
/* Allocate server memory. */
|
/* Allocate server memory. */
|
||||||
@ -176,7 +170,7 @@ 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(false), waitlist_mutex(false), deferred_session_mutex(false)
|
waitable_selection_mutex(false), waitlist_mutex(false)
|
||||||
{
|
{
|
||||||
/* Link waitables. */
|
/* Link waitables. */
|
||||||
os::InitializeWaitableManager(std::addressof(this->waitable_manager));
|
os::InitializeWaitableManager(std::addressof(this->waitable_manager));
|
||||||
|
@ -45,7 +45,6 @@ namespace ams::sf::hipc {
|
|||||||
NON_COPYABLE(ServerSession);
|
NON_COPYABLE(ServerSession);
|
||||||
NON_MOVEABLE(ServerSession);
|
NON_MOVEABLE(ServerSession);
|
||||||
private:
|
private:
|
||||||
util::IntrusiveListNode deferred_list_node;
|
|
||||||
cmif::ServiceObjectHolder srv_obj_holder;
|
cmif::ServiceObjectHolder srv_obj_holder;
|
||||||
cmif::PointerAndSize pointer_buffer;
|
cmif::PointerAndSize pointer_buffer;
|
||||||
cmif::PointerAndSize saved_message;
|
cmif::PointerAndSize saved_message;
|
||||||
|
@ -147,62 +147,14 @@ namespace ams::sf::hipc {
|
|||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerManagerBase::ProcessDeferredSessions() {
|
|
||||||
/* Iterate over the list of deferred sessions, and see if we can't do anything. */
|
|
||||||
std::scoped_lock lk(this->deferred_session_mutex);
|
|
||||||
|
|
||||||
/* Undeferring a request may undefer another request. We'll continue looping until everything is stable. */
|
|
||||||
bool needs_undefer_all = true;
|
|
||||||
while (needs_undefer_all) {
|
|
||||||
needs_undefer_all = false;
|
|
||||||
|
|
||||||
auto it = this->deferred_session_list.begin();
|
|
||||||
while (it != this->deferred_session_list.end()) {
|
|
||||||
ServerSession *session = static_cast<ServerSession *>(&*it);
|
|
||||||
R_TRY_CATCH(this->ProcessForSession(session)) {
|
|
||||||
R_CATCH(sf::ResultRequestDeferred) {
|
|
||||||
/* Session is still deferred, so let's continue. */
|
|
||||||
it++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
R_CATCH(sf::impl::ResultRequestInvalidated) {
|
|
||||||
/* Session is no longer deferred! */
|
|
||||||
it = this->deferred_session_list.erase(it);
|
|
||||||
needs_undefer_all = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
|
||||||
|
|
||||||
/* We succeeded! Remove from deferred list. */
|
|
||||||
it = this->deferred_session_list.erase(it);
|
|
||||||
needs_undefer_all = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ServerManagerBase::Process(os::WaitableHolderType *holder) {
|
Result ServerManagerBase::Process(os::WaitableHolderType *holder) {
|
||||||
switch (static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder))) {
|
switch (static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder))) {
|
||||||
case UserDataTag::Server:
|
case UserDataTag::Server:
|
||||||
return this->ProcessForServer(holder);
|
return this->ProcessForServer(holder);
|
||||||
break;
|
|
||||||
case UserDataTag::MitmServer:
|
case UserDataTag::MitmServer:
|
||||||
return this->ProcessForMitmServer(holder);
|
return this->ProcessForMitmServer(holder);
|
||||||
break;
|
|
||||||
case UserDataTag::Session:
|
case UserDataTag::Session:
|
||||||
/* Try to process for session. */
|
return this->ProcessForSession(holder);
|
||||||
R_TRY_CATCH(this->ProcessForSession(holder)) {
|
|
||||||
R_CATCH(sf::ResultRequestDeferred) {
|
|
||||||
/* The session was deferred, so push it onto the deferred session list. */
|
|
||||||
std::scoped_lock lk(this->deferred_session_mutex);
|
|
||||||
this->deferred_session_list.push_back(*static_cast<ServerSession *>(holder));
|
|
||||||
return ResultSuccess();
|
|
||||||
}
|
|
||||||
} R_END_TRY_CATCH;
|
|
||||||
|
|
||||||
/* We successfully invoked a command...so let's see if anything can be undeferred. */
|
|
||||||
this->ProcessDeferredSessions();
|
|
||||||
return ResultSuccess();
|
|
||||||
break;
|
|
||||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user