new-ipc: implement deferral. sm now works.

This commit is contained in:
Michael Scire authored and SciresM committed 2019-12-07 12:41:28 -08:00
1 parent f4dcd1db9b
commit c8ed190e5c
13 files changed
+193 -157

No files matched your search

@@ -127,6 +127,10 @@ namespace sts::sf::hipc {
os::Mutex waitlist_mutex;
os::WaitableManager 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::WaitableHolder *holder);
@@ -138,6 +142,8 @@ namespace sts::sf::hipc {
Result ProcessForMitmServer(os::WaitableHolder *holder);
Result ProcessForSession(os::WaitableHolder *holder);
void ProcessDeferredSessions();
template<typename ServiceImpl, auto MakeShared = std::make_shared<ServiceImpl>>
void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) {
/* Allocate server memory. */
@@ -32,6 +32,7 @@ namespace sts::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;
@@ -936,10 +936,15 @@ namespace sts::sf::impl {
if constexpr (Info.arg_type == ArgumentType::InData) {
/* New in rawdata. */
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index];
return *reinterpret_cast<const T *>(in_raw_data.GetAddress() + Offset);
if constexpr (!std::is_same<T, bool>::value) {
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) {
/* 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>());
} else if constexpr (Info.arg_type == ArgumentType::InHandle) {
/* New InHandle. */
@@ -127,6 +127,27 @@ namespace sts::sf::hipc {
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) {
switch (static_cast<UserDataTag>(holder->GetUserData())) {
case UserDataTag::Server:
@@ -136,8 +157,19 @@ namespace sts::sf::hipc {
return this->ProcessForMitmServer(holder);
break;
case UserDataTag::Session:
/* TODO: Process deferred. */
return this->ProcessForSession(holder);
/* Try to process for session. */
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;
STS_UNREACHABLE_DEFAULT_CASE();
}