diff options
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/server_manager.cpp | 100 | ||||
| -rw-r--r-- | src/core/hle/service/server_manager.h | 16 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 29 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.h | 5 |
5 files changed, 151 insertions, 8 deletions
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 059b21991..6cbc974fe 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -358,6 +358,14 @@ public: | |||
| 358 | return manager.lock(); | 358 | return manager.lock(); |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | bool GetIsDeferred() const { | ||
| 362 | return is_deferred; | ||
| 363 | } | ||
| 364 | |||
| 365 | void SetIsDeferred(bool is_deferred_ = true) { | ||
| 366 | is_deferred = is_deferred_; | ||
| 367 | } | ||
| 368 | |||
| 361 | private: | 369 | private: |
| 362 | friend class IPC::ResponseBuilder; | 370 | friend class IPC::ResponseBuilder; |
| 363 | 371 | ||
| @@ -392,6 +400,7 @@ private: | |||
| 392 | u32 domain_offset{}; | 400 | u32 domain_offset{}; |
| 393 | 401 | ||
| 394 | std::weak_ptr<SessionRequestManager> manager{}; | 402 | std::weak_ptr<SessionRequestManager> manager{}; |
| 403 | bool is_deferred{false}; | ||
| 395 | 404 | ||
| 396 | KernelCore& kernel; | 405 | KernelCore& kernel; |
| 397 | Core::Memory::Memory& memory; | 406 | Core::Memory::Memory& memory; |
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 55788ddeb..1b3db3caf 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp | |||
| @@ -25,6 +25,7 @@ constexpr size_t MaximumWaitObjects = 0x40; | |||
| 25 | enum HandleType { | 25 | enum HandleType { |
| 26 | Port, | 26 | Port, |
| 27 | Session, | 27 | Session, |
| 28 | DeferEvent, | ||
| 28 | Event, | 29 | Event, |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| @@ -53,9 +54,18 @@ ServerManager::~ServerManager() { | |||
| 53 | session->Close(); | 54 | session->Close(); |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | for (const auto& request : m_deferrals) { | ||
| 58 | request.session->Close(); | ||
| 59 | } | ||
| 60 | |||
| 56 | // Close event. | 61 | // Close event. |
| 57 | m_event->GetReadableEvent().Close(); | 62 | m_event->GetReadableEvent().Close(); |
| 58 | m_event->Close(); | 63 | m_event->Close(); |
| 64 | |||
| 65 | if (m_deferral_event) { | ||
| 66 | m_deferral_event->GetReadableEvent().Close(); | ||
| 67 | // Write event is owned by ServiceManager | ||
| 68 | } | ||
| 59 | } | 69 | } |
| 60 | 70 | ||
| 61 | void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) { | 71 | void ServerManager::RunServer(std::unique_ptr<ServerManager>&& server_manager) { |
| @@ -142,6 +152,21 @@ Result ServerManager::ManageNamedPort(const std::string& service_name, | |||
| 142 | R_SUCCEED(); | 152 | R_SUCCEED(); |
| 143 | } | 153 | } |
| 144 | 154 | ||
| 155 | Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) { | ||
| 156 | // Create a new event. | ||
| 157 | m_deferral_event = Kernel::KEvent::Create(m_system.Kernel()); | ||
| 158 | ASSERT(m_deferral_event != nullptr); | ||
| 159 | |||
| 160 | // Initialize the event. | ||
| 161 | m_deferral_event->Initialize(nullptr); | ||
| 162 | |||
| 163 | // Set the output. | ||
| 164 | *out_event = m_deferral_event; | ||
| 165 | |||
| 166 | // We succeeded. | ||
| 167 | R_SUCCEED(); | ||
| 168 | } | ||
| 169 | |||
| 145 | void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) { | 170 | void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_threads) { |
| 146 | for (size_t i = 0; i < num_threads; i++) { | 171 | for (size_t i = 0; i < num_threads; i++) { |
| 147 | auto thread_name = fmt::format("{}:{}", name, i + 1); | 172 | auto thread_name = fmt::format("{}:{}", name, i + 1); |
| @@ -207,6 +232,11 @@ Result ServerManager::WaitAndProcessImpl() { | |||
| 207 | } | 232 | } |
| 208 | } | 233 | } |
| 209 | 234 | ||
| 235 | // Add the deferral wakeup event. | ||
| 236 | if (m_deferral_event != nullptr) { | ||
| 237 | AddWaiter(std::addressof(m_deferral_event->GetReadableEvent()), HandleType::DeferEvent); | ||
| 238 | } | ||
| 239 | |||
| 210 | // Add the wakeup event. | 240 | // Add the wakeup event. |
| 211 | AddWaiter(std::addressof(m_event->GetReadableEvent()), HandleType::Event); | 241 | AddWaiter(std::addressof(m_event->GetReadableEvent()), HandleType::Event); |
| 212 | 242 | ||
| @@ -270,6 +300,23 @@ Result ServerManager::WaitAndProcessImpl() { | |||
| 270 | // Finish. | 300 | // Finish. |
| 271 | R_RETURN(this->OnSessionEvent(session, std::move(manager))); | 301 | R_RETURN(this->OnSessionEvent(session, std::move(manager))); |
| 272 | } | 302 | } |
| 303 | case HandleType::DeferEvent: { | ||
| 304 | // Clear event. | ||
| 305 | ASSERT(R_SUCCEEDED(m_deferral_event->Clear())); | ||
| 306 | |||
| 307 | // Drain the list of deferrals while we process. | ||
| 308 | std::list<RequestState> deferrals; | ||
| 309 | { | ||
| 310 | std::scoped_lock ll{m_list_mutex}; | ||
| 311 | m_deferrals.swap(deferrals); | ||
| 312 | } | ||
| 313 | |||
| 314 | // Allow other threads to serve. | ||
| 315 | sl.unlock(); | ||
| 316 | |||
| 317 | // Finish. | ||
| 318 | R_RETURN(this->OnDeferralEvent(std::move(deferrals))); | ||
| 319 | } | ||
| 273 | case HandleType::Event: { | 320 | case HandleType::Event: { |
| 274 | // Clear event and finish. | 321 | // Clear event and finish. |
| 275 | R_RETURN(m_event->Clear()); | 322 | R_RETURN(m_event->Clear()); |
| @@ -308,7 +355,6 @@ Result ServerManager::OnPortEvent(Kernel::KServerPort* port, | |||
| 308 | Result ServerManager::OnSessionEvent(Kernel::KServerSession* session, | 355 | Result ServerManager::OnSessionEvent(Kernel::KServerSession* session, |
| 309 | std::shared_ptr<Kernel::SessionRequestManager>&& manager) { | 356 | std::shared_ptr<Kernel::SessionRequestManager>&& manager) { |
| 310 | Result rc{ResultSuccess}; | 357 | Result rc{ResultSuccess}; |
| 311 | Result service_rc{ResultSuccess}; | ||
| 312 | 358 | ||
| 313 | // Try to receive a message. | 359 | // Try to receive a message. |
| 314 | std::shared_ptr<Kernel::HLERequestContext> context; | 360 | std::shared_ptr<Kernel::HLERequestContext> context; |
| @@ -324,16 +370,43 @@ Result ServerManager::OnSessionEvent(Kernel::KServerSession* session, | |||
| 324 | } | 370 | } |
| 325 | ASSERT(R_SUCCEEDED(rc)); | 371 | ASSERT(R_SUCCEEDED(rc)); |
| 326 | 372 | ||
| 373 | RequestState request{ | ||
| 374 | .session = session, | ||
| 375 | .context = std::move(context), | ||
| 376 | .manager = std::move(manager), | ||
| 377 | }; | ||
| 378 | |||
| 379 | // Complete the sync request with deferral handling. | ||
| 380 | R_RETURN(this->CompleteSyncRequest(std::move(request))); | ||
| 381 | } | ||
| 382 | |||
| 383 | Result ServerManager::CompleteSyncRequest(RequestState&& request) { | ||
| 384 | Result rc{ResultSuccess}; | ||
| 385 | Result service_rc{ResultSuccess}; | ||
| 386 | |||
| 387 | // Mark the request as not deferred. | ||
| 388 | request.context->SetIsDeferred(false); | ||
| 389 | |||
| 327 | // Complete the request. We have exclusive access to this session. | 390 | // Complete the request. We have exclusive access to this session. |
| 328 | service_rc = manager->CompleteSyncRequest(session, *context); | 391 | service_rc = request.manager->CompleteSyncRequest(request.session, *request.context); |
| 392 | |||
| 393 | // If we've been deferred, we're done. | ||
| 394 | if (request.context->GetIsDeferred()) { | ||
| 395 | // Insert into deferral list. | ||
| 396 | std::scoped_lock ll{m_list_mutex}; | ||
| 397 | m_deferrals.emplace_back(std::move(request)); | ||
| 398 | |||
| 399 | // Finish. | ||
| 400 | R_SUCCEED(); | ||
| 401 | } | ||
| 329 | 402 | ||
| 330 | // Send the reply. | 403 | // Send the reply. |
| 331 | rc = session->SendReplyHLE(); | 404 | rc = request.session->SendReplyHLE(); |
| 332 | 405 | ||
| 333 | // If the session has been closed, we're done. | 406 | // If the session has been closed, we're done. |
| 334 | if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) { | 407 | if (rc == Kernel::ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) { |
| 335 | // Close the session. | 408 | // Close the session. |
| 336 | session->Close(); | 409 | request.session->Close(); |
| 337 | 410 | ||
| 338 | // Finish. | 411 | // Finish. |
| 339 | R_SUCCEED(); | 412 | R_SUCCEED(); |
| @@ -345,7 +418,7 @@ Result ServerManager::OnSessionEvent(Kernel::KServerSession* session, | |||
| 345 | // Reinsert the session. | 418 | // Reinsert the session. |
| 346 | { | 419 | { |
| 347 | std::scoped_lock ll{m_list_mutex}; | 420 | std::scoped_lock ll{m_list_mutex}; |
| 348 | m_sessions.emplace(session, std::move(manager)); | 421 | m_sessions.emplace(request.session, std::move(request.manager)); |
| 349 | } | 422 | } |
| 350 | 423 | ||
| 351 | // Signal the wakeup event. | 424 | // Signal the wakeup event. |
| @@ -355,4 +428,21 @@ Result ServerManager::OnSessionEvent(Kernel::KServerSession* session, | |||
| 355 | R_SUCCEED(); | 428 | R_SUCCEED(); |
| 356 | } | 429 | } |
| 357 | 430 | ||
| 431 | Result ServerManager::OnDeferralEvent(std::list<RequestState>&& deferrals) { | ||
| 432 | ON_RESULT_FAILURE { | ||
| 433 | std::scoped_lock ll{m_list_mutex}; | ||
| 434 | m_deferrals.splice(m_deferrals.end(), deferrals); | ||
| 435 | }; | ||
| 436 | |||
| 437 | while (!deferrals.empty()) { | ||
| 438 | RequestState request = deferrals.front(); | ||
| 439 | deferrals.pop_front(); | ||
| 440 | |||
| 441 | // Try again to complete the request. | ||
| 442 | R_TRY(this->CompleteSyncRequest(std::move(request))); | ||
| 443 | } | ||
| 444 | |||
| 445 | R_SUCCEED(); | ||
| 446 | } | ||
| 447 | |||
| 358 | } // namespace Service | 448 | } // namespace Service |
diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h index b26557172..57b954ae8 100644 --- a/src/core/hle/service/server_manager.h +++ b/src/core/hle/service/server_manager.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <atomic> | 6 | #include <atomic> |
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include <list> | ||
| 8 | #include <map> | 9 | #include <map> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | #include <string_view> | 11 | #include <string_view> |
| @@ -19,6 +20,7 @@ class System; | |||
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | namespace Kernel { | 22 | namespace Kernel { |
| 23 | class HLERequestContext; | ||
| 22 | class KEvent; | 24 | class KEvent; |
| 23 | class KServerPort; | 25 | class KServerPort; |
| 24 | class KServerSession; | 26 | class KServerSession; |
| @@ -42,6 +44,7 @@ public: | |||
| 42 | Result ManageNamedPort(const std::string& service_name, | 44 | Result ManageNamedPort(const std::string& service_name, |
| 43 | std::shared_ptr<Kernel::SessionRequestHandler>&& handler, | 45 | std::shared_ptr<Kernel::SessionRequestHandler>&& handler, |
| 44 | u32 max_sessions = 64); | 46 | u32 max_sessions = 64); |
| 47 | Result ManageDeferral(Kernel::KEvent** out_event); | ||
| 45 | 48 | ||
| 46 | Result LoopProcess(); | 49 | Result LoopProcess(); |
| 47 | void StartAdditionalHostThreads(const char* name, size_t num_threads); | 50 | void StartAdditionalHostThreads(const char* name, size_t num_threads); |
| @@ -49,12 +52,16 @@ public: | |||
| 49 | static void RunServer(std::unique_ptr<ServerManager>&& server); | 52 | static void RunServer(std::unique_ptr<ServerManager>&& server); |
| 50 | 53 | ||
| 51 | private: | 54 | private: |
| 55 | struct RequestState; | ||
| 56 | |||
| 52 | Result LoopProcessImpl(); | 57 | Result LoopProcessImpl(); |
| 53 | Result WaitAndProcessImpl(); | 58 | Result WaitAndProcessImpl(); |
| 54 | Result OnPortEvent(Kernel::KServerPort* port, | 59 | Result OnPortEvent(Kernel::KServerPort* port, |
| 55 | std::shared_ptr<Kernel::SessionRequestHandler>&& handler); | 60 | std::shared_ptr<Kernel::SessionRequestHandler>&& handler); |
| 56 | Result OnSessionEvent(Kernel::KServerSession* session, | 61 | Result OnSessionEvent(Kernel::KServerSession* session, |
| 57 | std::shared_ptr<Kernel::SessionRequestManager>&& manager); | 62 | std::shared_ptr<Kernel::SessionRequestManager>&& manager); |
| 63 | Result OnDeferralEvent(std::list<RequestState>&& deferrals); | ||
| 64 | Result CompleteSyncRequest(RequestState&& state); | ||
| 58 | 65 | ||
| 59 | private: | 66 | private: |
| 60 | Core::System& m_system; | 67 | Core::System& m_system; |
| @@ -65,6 +72,15 @@ private: | |||
| 65 | std::map<Kernel::KServerPort*, std::shared_ptr<Kernel::SessionRequestHandler>> m_ports{}; | 72 | std::map<Kernel::KServerPort*, std::shared_ptr<Kernel::SessionRequestHandler>> m_ports{}; |
| 66 | std::map<Kernel::KServerSession*, std::shared_ptr<Kernel::SessionRequestManager>> m_sessions{}; | 73 | std::map<Kernel::KServerSession*, std::shared_ptr<Kernel::SessionRequestManager>> m_sessions{}; |
| 67 | Kernel::KEvent* m_event{}; | 74 | Kernel::KEvent* m_event{}; |
| 75 | Kernel::KEvent* m_deferral_event{}; | ||
| 76 | |||
| 77 | // Deferral tracking | ||
| 78 | struct RequestState { | ||
| 79 | Kernel::KServerSession* session; | ||
| 80 | std::shared_ptr<Kernel::HLERequestContext> context; | ||
| 81 | std::shared_ptr<Kernel::SessionRequestManager> manager; | ||
| 82 | }; | ||
| 83 | std::list<RequestState> m_deferrals{}; | ||
| 68 | 84 | ||
| 69 | // Host state tracking | 85 | // Host state tracking |
| 70 | std::atomic<bool> m_stopped{}; | 86 | std::atomic<bool> m_stopped{}; |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 0de32b05d..6eba48f03 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -32,6 +32,10 @@ ServiceManager::~ServiceManager() { | |||
| 32 | port->GetClientPort().Close(); | 32 | port->GetClientPort().Close(); |
| 33 | port->GetServerPort().Close(); | 33 | port->GetServerPort().Close(); |
| 34 | } | 34 | } |
| 35 | |||
| 36 | if (deferral_event) { | ||
| 37 | deferral_event->Close(); | ||
| 38 | } | ||
| 35 | } | 39 | } |
| 36 | 40 | ||
| 37 | void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) { | 41 | void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) { |
| @@ -62,6 +66,9 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions, | |||
| 62 | 66 | ||
| 63 | service_ports.emplace(name, port); | 67 | service_ports.emplace(name, port); |
| 64 | registered_services.emplace(name, handler); | 68 | registered_services.emplace(name, handler); |
| 69 | if (deferral_event) { | ||
| 70 | deferral_event->Signal(); | ||
| 71 | } | ||
| 65 | 72 | ||
| 66 | return ResultSuccess; | 73 | return ResultSuccess; |
| 67 | } | 74 | } |
| @@ -88,7 +95,7 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name | |||
| 88 | std::scoped_lock lk{lock}; | 95 | std::scoped_lock lk{lock}; |
| 89 | auto it = service_ports.find(name); | 96 | auto it = service_ports.find(name); |
| 90 | if (it == service_ports.end()) { | 97 | if (it == service_ports.end()) { |
| 91 | LOG_ERROR(Service_SM, "Server is not registered! service={}", name); | 98 | LOG_WARNING(Service_SM, "Server is not registered! service={}", name); |
| 92 | return ERR_SERVICE_NOT_REGISTERED; | 99 | return ERR_SERVICE_NOT_REGISTERED; |
| 93 | } | 100 | } |
| 94 | 101 | ||
| @@ -113,6 +120,11 @@ void SM::Initialize(Kernel::HLERequestContext& ctx) { | |||
| 113 | 120 | ||
| 114 | void SM::GetService(Kernel::HLERequestContext& ctx) { | 121 | void SM::GetService(Kernel::HLERequestContext& ctx) { |
| 115 | auto result = GetServiceImpl(ctx); | 122 | auto result = GetServiceImpl(ctx); |
| 123 | if (ctx.GetIsDeferred()) { | ||
| 124 | // Don't overwrite the command buffer. | ||
| 125 | return; | ||
| 126 | } | ||
| 127 | |||
| 116 | if (result.Succeeded()) { | 128 | if (result.Succeeded()) { |
| 117 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 129 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 118 | rb.Push(result.Code()); | 130 | rb.Push(result.Code()); |
| @@ -125,6 +137,11 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { | |||
| 125 | 137 | ||
| 126 | void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) { | 138 | void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) { |
| 127 | auto result = GetServiceImpl(ctx); | 139 | auto result = GetServiceImpl(ctx); |
| 140 | if (ctx.GetIsDeferred()) { | ||
| 141 | // Don't overwrite the command buffer. | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | |||
| 128 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 145 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 129 | rb.Push(result.Code()); | 146 | rb.Push(result.Code()); |
| 130 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); | 147 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); |
| @@ -152,8 +169,9 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& | |||
| 152 | // Find the named port. | 169 | // Find the named port. |
| 153 | auto port_result = service_manager.GetServicePort(name); | 170 | auto port_result = service_manager.GetServicePort(name); |
| 154 | if (port_result.Failed()) { | 171 | if (port_result.Failed()) { |
| 155 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw); | 172 | LOG_INFO(Service_SM, "Waiting for service {} to become available", name); |
| 156 | return port_result.Code(); | 173 | ctx.SetIsDeferred(); |
| 174 | return ERR_SERVICE_NOT_REGISTERED; | ||
| 157 | } | 175 | } |
| 158 | auto& port = port_result.Unwrap(); | 176 | auto& port = port_result.Unwrap(); |
| 159 | 177 | ||
| @@ -228,8 +246,13 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_) | |||
| 228 | SM::~SM() = default; | 246 | SM::~SM() = default; |
| 229 | 247 | ||
| 230 | void LoopProcess(Core::System& system) { | 248 | void LoopProcess(Core::System& system) { |
| 249 | auto& service_manager = system.ServiceManager(); | ||
| 231 | auto server_manager = std::make_unique<ServerManager>(system); | 250 | auto server_manager = std::make_unique<ServerManager>(system); |
| 232 | 251 | ||
| 252 | Kernel::KEvent* deferral_event{}; | ||
| 253 | server_manager->ManageDeferral(&deferral_event); | ||
| 254 | service_manager.SetDeferralEvent(deferral_event); | ||
| 255 | |||
| 233 | server_manager->ManageNamedPort("sm:", std::make_shared<SM>(system.ServiceManager(), system)); | 256 | server_manager->ManageNamedPort("sm:", std::make_shared<SM>(system.ServiceManager(), system)); |
| 234 | ServerManager::RunServer(std::move(server_manager)); | 257 | ServerManager::RunServer(std::move(server_manager)); |
| 235 | } | 258 | } |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 22ca720f8..b7eeafdd6 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -71,6 +71,10 @@ public: | |||
| 71 | 71 | ||
| 72 | void InvokeControlRequest(Kernel::HLERequestContext& context); | 72 | void InvokeControlRequest(Kernel::HLERequestContext& context); |
| 73 | 73 | ||
| 74 | void SetDeferralEvent(Kernel::KEvent* deferral_event_) { | ||
| 75 | deferral_event = deferral_event_; | ||
| 76 | } | ||
| 77 | |||
| 74 | private: | 78 | private: |
| 75 | std::shared_ptr<SM> sm_interface; | 79 | std::shared_ptr<SM> sm_interface; |
| 76 | std::unique_ptr<Controller> controller_interface; | 80 | std::unique_ptr<Controller> controller_interface; |
| @@ -82,6 +86,7 @@ private: | |||
| 82 | 86 | ||
| 83 | /// Kernel context | 87 | /// Kernel context |
| 84 | Kernel::KernelCore& kernel; | 88 | Kernel::KernelCore& kernel; |
| 89 | Kernel::KEvent* deferral_event{}; | ||
| 85 | }; | 90 | }; |
| 86 | 91 | ||
| 87 | /// Runs SM services. | 92 | /// Runs SM services. |