new-ipc: implement deferral. sm now works.

This commit is contained in:
Michael Scire 2019-10-11 02:15:14 -07:00
parent 15f3adb8d2
commit 461ed913ef
4 changed files with 48 additions and 4 deletions

View File

@ -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. */

View File

@ -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;

View File

@ -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];
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) { } 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. */

View File

@ -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();
} }