mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 22:02:15 +00:00
tipc: server processor fixes (compiles!)
This commit is contained in:
parent
affeeb2724
commit
58776f5ba8
2 changed files with 40 additions and 24 deletions
|
@ -282,6 +282,9 @@ namespace ams::tipc {
|
||||||
/* Acquire exclusive server manager access. */
|
/* Acquire exclusive server manager access. */
|
||||||
std::scoped_lock lk(m_server_manager->GetMutex());
|
std::scoped_lock lk(m_server_manager->GetMutex());
|
||||||
|
|
||||||
|
/* Increment our session count. */
|
||||||
|
++m_num_sessions;
|
||||||
|
|
||||||
/* Send information about the session as a message. */
|
/* Send information about the session as a message. */
|
||||||
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(MessageType_AddSession) | (static_cast<u64>(session_handle) << BITSIZEOF(u32)));
|
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(MessageType_AddSession) | (static_cast<u64>(session_handle) << BITSIZEOF(u32)));
|
||||||
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(port_index));
|
os::SendMessageQueue(std::addressof(m_message_queue), static_cast<uintptr_t>(port_index));
|
||||||
|
@ -335,7 +338,7 @@ namespace ams::tipc {
|
||||||
|
|
||||||
using PortManagerTuple = decltype([]<size_t... Ix>(std::index_sequence<Ix...>) {
|
using PortManagerTuple = decltype([]<size_t... Ix>(std::index_sequence<Ix...>) {
|
||||||
return std::tuple<PortManager<Ix>...>{};
|
return std::tuple<PortManager<Ix>...>{};
|
||||||
}(std::make_index_sequence(NumPorts)));
|
}(std::make_index_sequence<NumPorts>()));
|
||||||
|
|
||||||
using PortAllocatorTuple = std::tuple<typename PortInfos::Allocator...>;
|
using PortAllocatorTuple = std::tuple<typename PortInfos::Allocator...>;
|
||||||
private:
|
private:
|
||||||
|
@ -369,7 +372,7 @@ namespace ams::tipc {
|
||||||
template<size_t Ix>
|
template<size_t Ix>
|
||||||
void InitializePortThread(s32 priority) {
|
void InitializePortThread(s32 priority) {
|
||||||
/* Create the thread. */
|
/* Create the thread. */
|
||||||
R_ABORT_UNLESS(os::CreateThread(m_port_threads + Ix, LoopAutoForPortThreadFunction, this, m_port_stacks + Ix, ThreadStackSize, priority));
|
R_ABORT_UNLESS(os::CreateThread(m_port_threads + Ix, &LoopAutoForPortThreadFunction<Ix>, this, m_port_stacks + Ix, ThreadStackSize, priority));
|
||||||
|
|
||||||
/* Start the thread. */
|
/* Start the thread. */
|
||||||
os::StartThread(m_port_threads + Ix);
|
os::StartThread(m_port_threads + Ix);
|
||||||
|
@ -390,7 +393,7 @@ namespace ams::tipc {
|
||||||
/* Initialize our port managers. */
|
/* Initialize our port managers. */
|
||||||
[this]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
[this]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||||
(this->GetPortManager<Ix>().Initialize(static_cast<s32>(Ix), this), ...);
|
(this->GetPortManager<Ix>().Initialize(static_cast<s32>(Ix), this), ...);
|
||||||
}(std::make_index_sequence(NumPorts));
|
}(std::make_index_sequence<NumPorts>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Ix>
|
template<size_t Ix>
|
||||||
|
@ -406,7 +409,7 @@ namespace ams::tipc {
|
||||||
[thread_priority, this]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
[thread_priority, this]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||||
/* Create all threads. */
|
/* Create all threads. */
|
||||||
(this->InitializePortThread<Ix>(thread_priority), ...);
|
(this->InitializePortThread<Ix>(thread_priority), ...);
|
||||||
}(std::make_index_sequence(NumPorts - 1));
|
}(std::make_index_sequence<NumPorts - 1>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process for the last port. */
|
/* Process for the last port. */
|
||||||
|
@ -419,7 +422,7 @@ namespace ams::tipc {
|
||||||
|
|
||||||
/* Try to allocate from each port, in turn. */
|
/* Try to allocate from each port, in turn. */
|
||||||
tipc::ServiceObjectBase *allocated = nullptr;
|
tipc::ServiceObjectBase *allocated = nullptr;
|
||||||
return [this, port_index, &allocated]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
[this, port_index, &allocated]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||||
(this->TryAllocateObject<Ix>(port_index, allocated), ...);
|
(this->TryAllocateObject<Ix>(port_index, allocated), ...);
|
||||||
}(std::make_index_sequence<NumPorts>());
|
}(std::make_index_sequence<NumPorts>());
|
||||||
|
|
||||||
|
@ -466,7 +469,7 @@ namespace ams::tipc {
|
||||||
R_TRY_CATCH(port_manager.ReplyAndReceive(std::addressof(signaled_holder), std::addressof(signaled_object), reply_target)) {
|
R_TRY_CATCH(port_manager.ReplyAndReceive(std::addressof(signaled_holder), std::addressof(signaled_object), reply_target)) {
|
||||||
R_CATCH(os::ResultSessionClosedForReceive, os::ResultReceiveListBroken) {
|
R_CATCH(os::ResultSessionClosedForReceive, os::ResultReceiveListBroken) {
|
||||||
/* Close the object and continue. */
|
/* Close the object and continue. */
|
||||||
port_manager.CloseObject(signaled_object);
|
port_manager.CloseSession(signaled_object);
|
||||||
|
|
||||||
/* We have nothing to reply to. */
|
/* We have nothing to reply to. */
|
||||||
reply_target = svc::InvalidHandle;
|
reply_target = svc::InvalidHandle;
|
||||||
|
@ -523,7 +526,7 @@ namespace ams::tipc {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Our message queue was signaled. */
|
/* Our message queue was signaled. */
|
||||||
port_manager.ProcessMessages(this);
|
port_manager.ProcessMessages();
|
||||||
|
|
||||||
/* We have nothing to reply to. */
|
/* We have nothing to reply to. */
|
||||||
reply_target = svc::InvalidHandle;
|
reply_target = svc::InvalidHandle;
|
||||||
|
@ -538,7 +541,7 @@ namespace ams::tipc {
|
||||||
/* Select the best port manager. */
|
/* Select the best port manager. */
|
||||||
PortManagerBase *best_manager = nullptr;
|
PortManagerBase *best_manager = nullptr;
|
||||||
s32 best_sessions = -1;
|
s32 best_sessions = -1;
|
||||||
const auto session_counts = [this, &best_manager, &best_sessions]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
[this, &best_manager, &best_sessions]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
|
||||||
(this->TrySelectBetterPort<Ix>(best_manager, best_sessions), ...);
|
(this->TrySelectBetterPort<Ix>(best_manager, best_sessions), ...);
|
||||||
}(std::make_index_sequence<NumPorts>());
|
}(std::make_index_sequence<NumPorts>());
|
||||||
|
|
||||||
|
@ -548,22 +551,20 @@ namespace ams::tipc {
|
||||||
|
|
||||||
template<size_t Ix> requires (Ix < NumPorts)
|
template<size_t Ix> requires (Ix < NumPorts)
|
||||||
void TrySelectBetterPort(PortManagerBase *&best_manager, s32 &best_sessions) {
|
void TrySelectBetterPort(PortManagerBase *&best_manager, s32 &best_sessions) {
|
||||||
if constexpr (Ix == 0) {
|
|
||||||
best_manager = std::addressof(this->GetPortManager<Ix>());
|
|
||||||
best_sessions = std::min(best_manager->GetSessionCount(), static_cast<s32>(SessionsPerPortManager<Ix>));
|
|
||||||
} else if constexpr (Ix < NumPorts - 1) {
|
|
||||||
auto &cur_manager = this->GetPortManager<Ix>();
|
|
||||||
const auto cur_sessions = std::min(cur_manager.GetSessionCount(), static_cast<s32>(SessionsPerPortManager<Ix>));
|
|
||||||
|
|
||||||
if (cur_sessions < best_sessions) {
|
|
||||||
best_manager = std::addressof(cur_manager);
|
|
||||||
best_sessions = cur_sessions;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto &cur_manager = this->GetPortManager<Ix>();
|
auto &cur_manager = this->GetPortManager<Ix>();
|
||||||
const auto cur_sessions = cur_manager.GetSessionCount();
|
const auto cur_sessions = cur_manager.GetSessionCount();
|
||||||
|
|
||||||
if (cur_sessions < best_sessions) {
|
/* NOTE: It's unknown how nintendo handles the case where the last manager has more sessions (to cover the remainder). */
|
||||||
|
/* Our algorithm diverges from theirs (it does not do std::min bounds capping), to accommodate remainder ports. */
|
||||||
|
/* If we learn how they handle this edge case, we can change our ways to match theirs. */
|
||||||
|
|
||||||
|
if constexpr (Ix == 0) {
|
||||||
|
best_manager = std::addressof(cur_manager);
|
||||||
|
best_sessions = cur_sessions;
|
||||||
|
} else {
|
||||||
|
static_assert(SessionsPerPortManager<Ix - 1> == SessionsPerPortManager<0>);
|
||||||
|
static_assert(SessionsPerPortManager<Ix - 1> <= SessionsPerPortManager<Ix>);
|
||||||
|
if (cur_sessions < best_sessions || best_sessions >= static_cast<s32>(SessionsPerPortManager<Ix - 1>)) {
|
||||||
best_manager = std::addressof(cur_manager);
|
best_manager = std::addressof(cur_manager);
|
||||||
best_sessions = cur_sessions;
|
best_sessions = cur_sessions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,15 +52,30 @@ namespace ams::_test {
|
||||||
|
|
||||||
using UserInterfaceObject = ::ams::tipc::ServiceObject<impl::IUserInterface, UserInterfaceFacade>;
|
using UserInterfaceObject = ::ams::tipc::ServiceObject<impl::IUserInterface, UserInterfaceFacade>;
|
||||||
|
|
||||||
|
using ManagerInterfaceObject = ::ams::tipc::ServiceObject<impl::IManagerInterface, ManagerInterfaceFacade>;
|
||||||
|
|
||||||
Result TestAutomaticDispatch(UserInterfaceObject *object) {
|
Result TestAutomaticDispatch(UserInterfaceObject *object) {
|
||||||
return object->ProcessRequest();
|
return object->ProcessRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
using ManagerInterfaceObject = ::ams::tipc::ServiceObject<impl::IManagerInterface, ManagerInterfaceFacade>;
|
|
||||||
|
|
||||||
Result TestManagerDispatch(ManagerInterfaceObject *object) {
|
Result TestManagerDispatch(ManagerInterfaceObject *object) {
|
||||||
return object->ProcessRequest();
|
return object->ProcessRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using UserPortMeta = tipc::PortMeta<69, impl::IUserInterface, UserInterfaceFacade, tipc::SlabAllocator>;
|
||||||
|
using ManagerPortMeta = tipc::PortMeta< 1, impl::IManagerInterface, ManagerInterfaceFacade, tipc::SingletonAllocator>;
|
||||||
|
|
||||||
|
using TestServerManager = tipc::ServerManager<ManagerPortMeta, UserPortMeta>;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TestServerManager g_test_server_manager;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestLoop() {
|
||||||
|
g_test_server_manager.LoopAuto();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue