diff --git a/source/ams/ams_environment.cpp b/source/ams/ams_environment.cpp index 94cda326..9025615a 100644 --- a/source/ams/ams_environment.cpp +++ b/source/ams/ams_environment.cpp @@ -162,7 +162,3 @@ extern "C" { void abort() { ams::AbortImpl(); } - -void *__cxa_allocate_ecxeption(size_t thrown_size) { - abort(); -} \ No newline at end of file diff --git a/source/sf/hipc/sf_hipc_server_manager.cpp b/source/sf/hipc/sf_hipc_server_manager.cpp index 1e4236c2..cca7e9a8 100644 --- a/source/sf/hipc/sf_hipc_server_manager.cpp +++ b/source/sf/hipc/sf_hipc_server_manager.cpp @@ -147,24 +147,32 @@ namespace ams::sf::hipc { /* Iterate over the list of deferred sessions, and see if we can't do anything. */ std::scoped_lock lk(this->deferred_session_mutex); - auto it = this->deferred_session_list.begin(); - while (it != this->deferred_session_list.end()) { - ServerSession *session = static_cast(&*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); - continue; - } - } R_END_TRY_CATCH_WITH_ASSERT; + /* 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; - /* We succeeded! Remove from deferred list. */ - it = this->deferred_session_list.erase(it); + auto it = this->deferred_session_list.begin(); + while (it != this->deferred_session_list.end()) { + ServerSession *session = static_cast(&*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_ASSERT; + + /* We succeeded! Remove from deferred list. */ + it = this->deferred_session_list.erase(it); + needs_undefer_all = true; + } } } diff --git a/source/sm/sm_ams.c b/source/sm/sm_ams.c index 5f3268d8..713fd393 100644 --- a/source/sm/sm_ams.c +++ b/source/sm/sm_ams.c @@ -49,6 +49,18 @@ static Service g_smAtmosphereMitmSrv; NX_GENERATE_SERVICE_GUARD(smAtmosphereMitm); Result _smAtmosphereMitmInitialize(void) { + return smAtmosphereOpenSession(&g_smAtmosphereMitmSrv); +} + +void _smAtmosphereMitmCleanup(void) { + smAtmosphereCloseSession(&g_smAtmosphereMitmSrv); +} + +Service* smAtmosphereMitmGetServiceSession(void) { + return &g_smAtmosphereMitmSrv; +} + +Result smAtmosphereOpenSession(Service *out) { Handle sm_handle; Result rc = svcConnectToNamedPort(&sm_handle, "sm:"); while (R_VALUE(rc) == KERNELRESULT(NotFound)) { @@ -57,28 +69,24 @@ Result _smAtmosphereMitmInitialize(void) { } if (R_SUCCEEDED(rc)) { - serviceCreate(&g_smAtmosphereMitmSrv, sm_handle); + serviceCreate(out, sm_handle); } if (R_SUCCEEDED(rc)) { const u64 pid_placeholder = 0; - rc = serviceDispatchIn(&g_smAtmosphereMitmSrv, 0, pid_placeholder, .in_send_pid = true); + rc = serviceDispatchIn(out, 0, pid_placeholder, .in_send_pid = true); } return rc; } -void _smAtmosphereMitmCleanup(void) { - serviceClose(&g_smAtmosphereMitmSrv); +void smAtmosphereCloseSession(Service *srv) { + serviceClose(srv); } -Service* smAtmosphereMitmGetServiceSession(void) { - return &g_smAtmosphereMitmSrv; -} - -Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, SmServiceName name) { +Result smAtmosphereMitmInstall(Service *fwd_srv, Handle *handle_out, Handle *query_out, SmServiceName name) { Handle tmp_handles[2]; - Result rc = serviceDispatchIn(&g_smAtmosphereMitmSrv, 65000, name, + Result rc = serviceDispatchIn(fwd_srv, 65000, name, .out_handle_attrs = { SfOutHandleAttr_HipcMove, SfOutHandleAttr_HipcMove }, .out_handles = tmp_handles, ); @@ -92,11 +100,11 @@ Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, SmServiceN } Result smAtmosphereMitmUninstall(SmServiceName name) { - return _smAtmosphereCmdInServiceNameNoOut(name, &g_smAtmosphereMitmSrv, 65001); + return _smAtmosphereCmdInServiceNameNoOut(name, smGetServiceSession(), 65001); } Result smAtmosphereMitmDeclareFuture(SmServiceName name) { - return _smAtmosphereCmdInServiceNameNoOut(name, &g_smAtmosphereMitmSrv, 65006); + return _smAtmosphereCmdInServiceNameNoOut(name, smGetServiceSession(), 65006); } Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, u64 *tid_out, SmServiceName name) { diff --git a/source/sm/sm_ams.h b/source/sm/sm_ams.h index a18f3be2..7358e3a7 100644 --- a/source/sm/sm_ams.h +++ b/source/sm/sm_ams.h @@ -22,7 +22,10 @@ Result smAtmosphereMitmInitialize(void); void smAtmosphereMitmExit(void); Service *smAtmosphereMitmGetServiceSession(); -Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, SmServiceName name); +Result smAtmosphereOpenSession(Service *out); +void smAtmosphereCloseSession(Service *srv); + +Result smAtmosphereMitmInstall(Service *fwd_srv, Handle *handle_out, Handle *query_out, SmServiceName name); Result smAtmosphereMitmUninstall(SmServiceName name); Result smAtmosphereMitmDeclareFuture(SmServiceName name); Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, u64 *tid_out, SmServiceName name); diff --git a/source/sm/sm_mitm_api.cpp b/source/sm/sm_mitm_api.cpp index d65b610f..90503eb1 100644 --- a/source/sm/sm_mitm_api.cpp +++ b/source/sm/sm_mitm_api.cpp @@ -19,25 +19,25 @@ namespace ams::sm::mitm { /* Mitm API. */ Result InstallMitm(Handle *out_port, Handle *out_query, ServiceName name) { - return impl::DoWithMitmSession([&]() { - return smAtmosphereMitmInstall(out_port, out_query, impl::ConvertName(name)); + return impl::DoWithPerThreadSession([&](Service *fwd) { + return smAtmosphereMitmInstall(fwd, out_port, out_query, impl::ConvertName(name)); }); } Result UninstallMitm(ServiceName name) { - return impl::DoWithMitmSession([&]() { + return impl::DoWithUserSession([&]() { return smAtmosphereMitmUninstall(impl::ConvertName(name)); }); } Result DeclareFutureMitm(ServiceName name) { - return impl::DoWithMitmSession([&]() { + return impl::DoWithUserSession([&]() { return smAtmosphereMitmDeclareFuture(impl::ConvertName(name)); }); } Result AcknowledgeSession(Service *out_service, os::ProcessId *out_process_id, ncm::ProgramId *out_program_id, ServiceName name) { - return impl::DoWithMitmSession([&]() { + return impl::DoWithMitmAcknowledgementSession([&]() { return smAtmosphereMitmAcknowledgeSession(out_service, &out_process_id->value, &out_program_id->value, impl::ConvertName(name)); }); } diff --git a/source/sm/sm_utils.cpp b/source/sm/sm_utils.cpp index 5c920b00..6d9544da 100644 --- a/source/sm/sm_utils.cpp +++ b/source/sm/sm_utils.cpp @@ -21,7 +21,8 @@ namespace ams::sm::impl { /* Globals. */ os::RecursiveMutex g_user_session_mutex; - os::RecursiveMutex g_mitm_session_mutex; + os::RecursiveMutex g_mitm_ack_session_mutex; + os::RecursiveMutex g_per_thread_session_mutex; } @@ -30,8 +31,12 @@ namespace ams::sm::impl { return g_user_session_mutex; } - os::RecursiveMutex &GetMitmSessionMutex() { - return g_mitm_session_mutex; + os::RecursiveMutex &GetMitmAcknowledgementSessionMutex() { + return g_mitm_ack_session_mutex; + } + + os::RecursiveMutex &GetPerThreadSessionMutex() { + return g_per_thread_session_mutex; } } diff --git a/source/sm/sm_utils.hpp b/source/sm/sm_utils.hpp index 3b1804f0..4705f62e 100644 --- a/source/sm/sm_utils.hpp +++ b/source/sm/sm_utils.hpp @@ -22,7 +22,8 @@ namespace ams::sm::impl { /* Utilities. */ os::RecursiveMutex &GetUserSessionMutex(); - os::RecursiveMutex &GetMitmSessionMutex(); + os::RecursiveMutex &GetMitmAcknowledgementSessionMutex(); + os::RecursiveMutex &GetPerThreadSessionMutex(); template Result DoWithUserSession(F f) { @@ -36,8 +37,8 @@ namespace ams::sm::impl { } template - Result DoWithMitmSession(F f) { - std::scoped_lock lk(GetMitmSessionMutex()); + Result DoWithMitmAcknowledgementSession(F f) { + std::scoped_lock lk(GetMitmAcknowledgementSessionMutex()); { R_ASSERT(smAtmosphereMitmInitialize()); ON_SCOPE_EXIT { smAtmosphereMitmExit(); }; @@ -46,6 +47,19 @@ namespace ams::sm::impl { } } + template + Result DoWithPerThreadSession(F f) { + Service srv; + { + std::scoped_lock lk(GetPerThreadSessionMutex()); + R_ASSERT(smAtmosphereOpenSession(&srv)); + } + { + ON_SCOPE_EXIT { smAtmosphereCloseSession(&srv); }; + return f(&srv); + } + } + NX_CONSTEXPR SmServiceName ConvertName(sm::ServiceName name) { static_assert(sizeof(SmServiceName) == sizeof(sm::ServiceName)); SmServiceName ret = {};