mirror of
https://github.com/Atmosphere-NX/Atmosphere-libs.git
synced 2025-06-29 14:32:58 +02:00
new-ipc: implement deferral. sm now works.
This commit is contained in:
parent
15f3adb8d2
commit
461ed913ef
@ -127,6 +127,10 @@ namespace sts::sf::hipc {
|
|||||||
|
|
||||||
os::Mutex waitlist_mutex;
|
os::Mutex waitlist_mutex;
|
||||||
os::WaitableManager waitlist;
|
os::WaitableManager 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::WaitableHolder *holder);
|
void RegisterToWaitList(os::WaitableHolder *holder);
|
||||||
@ -138,6 +142,8 @@ namespace sts::sf::hipc {
|
|||||||
Result ProcessForMitmServer(os::WaitableHolder *holder);
|
Result ProcessForMitmServer(os::WaitableHolder *holder);
|
||||||
Result ProcessForSession(os::WaitableHolder *holder);
|
Result ProcessForSession(os::WaitableHolder *holder);
|
||||||
|
|
||||||
|
void ProcessDeferredSessions();
|
||||||
|
|
||||||
template<typename ServiceImpl, auto MakeShared = std::make_shared<ServiceImpl>>
|
template<typename ServiceImpl, auto MakeShared = std::make_shared<ServiceImpl>>
|
||||||
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. */
|
||||||
|
@ -32,6 +32,7 @@ namespace sts::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;
|
||||||
|
@ -936,10 +936,15 @@ namespace sts::sf::impl {
|
|||||||
if constexpr (Info.arg_type == ArgumentType::InData) {
|
if constexpr (Info.arg_type == ArgumentType::InData) {
|
||||||
/* New in rawdata. */
|
/* New in rawdata. */
|
||||||
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index];
|
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index];
|
||||||
|
if constexpr (!std::is_same<T, bool>::value) {
|
||||||
return *reinterpret_cast<const T *>(in_raw_data.GetAddress() + Offset);
|
return *reinterpret_cast<const T *>(in_raw_data.GetAddress() + Offset);
|
||||||
|
} else {
|
||||||
|
/* Special case bools. */
|
||||||
|
return *reinterpret_cast<const u8 *>(in_raw_data.GetAddress() + Offset) & 1;
|
||||||
|
}
|
||||||
} else if constexpr (Info.arg_type == ArgumentType::OutData) {
|
} else if constexpr (Info.arg_type == ArgumentType::OutData) {
|
||||||
/* New out rawdata. */
|
/* New out rawdata. */
|
||||||
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index];
|
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.out_raw_data_index];
|
||||||
return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>());
|
return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>());
|
||||||
} else if constexpr (Info.arg_type == ArgumentType::InHandle) {
|
} else if constexpr (Info.arg_type == ArgumentType::InHandle) {
|
||||||
/* New InHandle. */
|
/* New InHandle. */
|
||||||
|
@ -127,6 +127,27 @@ namespace sts::sf::hipc {
|
|||||||
return this->ProcessRequest(session, tls_message);
|
return this->ProcessRequest(session, tls_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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(ResultServiceFrameworkRequestDeferredByUser) {
|
||||||
|
/* Session is still deferred, so let's continue. */
|
||||||
|
it++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* TODO: N has a result that undefers without success. */
|
||||||
|
} R_END_TRY_CATCH_WITH_ASSERT;
|
||||||
|
|
||||||
|
/* We succeeded! Remove from deferred list. */
|
||||||
|
it = this->deferred_session_list.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Result ServerManagerBase::Process(os::WaitableHolder *holder) {
|
Result ServerManagerBase::Process(os::WaitableHolder *holder) {
|
||||||
switch (static_cast<UserDataTag>(holder->GetUserData())) {
|
switch (static_cast<UserDataTag>(holder->GetUserData())) {
|
||||||
case UserDataTag::Server:
|
case UserDataTag::Server:
|
||||||
@ -136,8 +157,19 @@ namespace sts::sf::hipc {
|
|||||||
return this->ProcessForMitmServer(holder);
|
return this->ProcessForMitmServer(holder);
|
||||||
break;
|
break;
|
||||||
case UserDataTag::Session:
|
case UserDataTag::Session:
|
||||||
/* TODO: Process deferred. */
|
/* Try to process for session. */
|
||||||
return this->ProcessForSession(holder);
|
R_TRY_CATCH(this->ProcessForSession(holder)) {
|
||||||
|
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) {
|
||||||
|
/* 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;
|
break;
|
||||||
STS_UNREACHABLE_DEFAULT_CASE();
|
STS_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user