sm: implement accurate request deferral semantics

This commit is contained in:
Michael Scire 2020-12-31 00:29:06 -08:00
parent b05ba02f04
commit ced1312dc7
3 changed files with 2 additions and 57 deletions

View File

@ -128,10 +128,6 @@ namespace ams::sf::hipc {
os::Mutex waitlist_mutex;
os::WaitableManagerType waitlist;
os::Mutex deferred_session_mutex;
using DeferredSessionList = typename util::IntrusiveListMemberTraits<&ServerSession::deferred_list_node>::ListType;
DeferredSessionList deferred_session_list;
private:
virtual void RegisterSessionToWaitList(ServerSession *session) override final;
void RegisterToWaitList(os::WaitableHolderType *holder);
@ -143,8 +139,6 @@ namespace ams::sf::hipc {
Result ProcessForMitmServer(os::WaitableHolderType *holder);
Result ProcessForSession(os::WaitableHolderType *holder);
void ProcessDeferredSessions();
template<typename Interface, auto MakeShared>
void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) {
/* Allocate server memory. */
@ -176,7 +170,7 @@ namespace ams::sf::hipc {
ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count) :
ServerDomainSessionManager(entry_storage, entry_count),
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. */
os::InitializeWaitableManager(std::addressof(this->waitable_manager));

View File

@ -45,7 +45,6 @@ namespace ams::sf::hipc {
NON_COPYABLE(ServerSession);
NON_MOVEABLE(ServerSession);
private:
util::IntrusiveListNode deferred_list_node;
cmif::ServiceObjectHolder srv_obj_holder;
cmif::PointerAndSize pointer_buffer;
cmif::PointerAndSize saved_message;

View File

@ -147,62 +147,14 @@ namespace ams::sf::hipc {
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) {
switch (static_cast<UserDataTag>(os::GetWaitableHolderUserData(holder))) {
case UserDataTag::Server:
return this->ProcessForServer(holder);
break;
case UserDataTag::MitmServer:
return this->ProcessForMitmServer(holder);
break;
case UserDataTag::Session:
/* Try to process for session. */
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;
return this->ProcessForSession(holder);
AMS_UNREACHABLE_DEFAULT_CASE();
}
}