mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #4069 from B3n30/wait_for_service_register
Service::SM: Wait till client is registered
This commit is contained in:
		
						commit
						ae6007bf9d
					
				
					 2 changed files with 47 additions and 5 deletions
				
			
		|  | @ -3,7 +3,6 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <tuple> | #include <tuple> | ||||||
| 
 |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/hle/ipc.h" | #include "core/hle/ipc.h" | ||||||
|  | @ -11,10 +10,12 @@ | ||||||
| #include "core/hle/kernel/client_port.h" | #include "core/hle/kernel/client_port.h" | ||||||
| #include "core/hle/kernel/client_session.h" | #include "core/hle/kernel/client_session.h" | ||||||
| #include "core/hle/kernel/errors.h" | #include "core/hle/kernel/errors.h" | ||||||
|  | #include "core/hle/kernel/event.h" | ||||||
| #include "core/hle/kernel/hle_ipc.h" | #include "core/hle/kernel/hle_ipc.h" | ||||||
| #include "core/hle/kernel/semaphore.h" | #include "core/hle/kernel/semaphore.h" | ||||||
| #include "core/hle/kernel/server_port.h" | #include "core/hle/kernel/server_port.h" | ||||||
| #include "core/hle/kernel/server_session.h" | #include "core/hle/kernel/server_session.h" | ||||||
|  | #include "core/hle/lock.h" | ||||||
| #include "core/hle/service/sm/sm.h" | #include "core/hle/service/sm/sm.h" | ||||||
| #include "core/hle/service/sm/srv.h" | #include "core/hle/service/sm/srv.h" | ||||||
| 
 | 
 | ||||||
|  | @ -99,12 +100,44 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) { | ||||||
| 
 | 
 | ||||||
|     // TODO(yuriks): Permission checks go here
 |     // TODO(yuriks): Permission checks go here
 | ||||||
| 
 | 
 | ||||||
|  |     auto get_handle = [name, this](Kernel::SharedPtr<Kernel::Thread> thread, | ||||||
|  |                                    Kernel::HLERequestContext& ctx, ThreadWakeupReason reason) { | ||||||
|  |         LOG_ERROR(Service_SRV, "called service={} wakeup", name); | ||||||
|  |         auto client_port = service_manager->GetServicePort(name); | ||||||
|  | 
 | ||||||
|  |         auto session = client_port.Unwrap()->Connect(); | ||||||
|  |         if (session.Succeeded()) { | ||||||
|  |             LOG_DEBUG(Service_SRV, "called service={} -> session={}", name, | ||||||
|  |                       (*session)->GetObjectId()); | ||||||
|  |             IPC::RequestBuilder rb(ctx, 0x5, 1, 2); | ||||||
|  |             rb.Push(session.Code()); | ||||||
|  |             rb.PushMoveObjects(std::move(session).Unwrap()); | ||||||
|  |         } else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED) { | ||||||
|  |             LOG_ERROR(Service_SRV, "called service={} -> ERR_MAX_CONNECTIONS_REACHED", name); | ||||||
|  |             UNREACHABLE(); | ||||||
|  |         } else { | ||||||
|  |             LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, session.Code().raw); | ||||||
|  |             IPC::RequestBuilder rb(ctx, 0x5, 1, 0); | ||||||
|  |             rb.Push(session.Code()); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     auto client_port = service_manager->GetServicePort(name); |     auto client_port = service_manager->GetServicePort(name); | ||||||
|     if (client_port.Failed()) { |     if (client_port.Failed()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         if (wait_until_available && client_port.Code() == ERR_SERVICE_NOT_REGISTERED) { | ||||||
|         rb.Push(client_port.Code()); |             LOG_INFO(Service_SRV, "called service={} delayed", name); | ||||||
|         LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, client_port.Code().raw); |             Kernel::SharedPtr<Kernel::Event> get_service_handle_event = | ||||||
|         return; |                 ctx.SleepClientThread(Kernel::GetCurrentThread(), "GetServiceHandle", | ||||||
|  |                                       std::chrono::nanoseconds(-1), get_handle); | ||||||
|  |             get_service_handle_delayed_map[name] = std::move(get_service_handle_event); | ||||||
|  |             return; | ||||||
|  |         } else { | ||||||
|  |             IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  |             rb.Push(client_port.Code()); | ||||||
|  |             LOG_ERROR(Service_SRV, "called service={} -> error 0x{:08X}", name, | ||||||
|  |                       client_port.Code().raw); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto session = client_port.Unwrap()->Connect(); |     auto session = client_port.Unwrap()->Connect(); | ||||||
|  | @ -199,6 +232,12 @@ void SRV::RegisterService(Kernel::HLERequestContext& ctx) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     auto it = get_service_handle_delayed_map.find(name); | ||||||
|  |     if (it != get_service_handle_delayed_map.end()) { | ||||||
|  |         it->second->Signal(); | ||||||
|  |         get_service_handle_delayed_map.erase(it); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushMoveObjects(port.Unwrap()); |     rb.PushMoveObjects(port.Unwrap()); | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <unordered_map> | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
| 
 | 
 | ||||||
|  | @ -32,6 +33,8 @@ private: | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<ServiceManager> service_manager; |     std::shared_ptr<ServiceManager> service_manager; | ||||||
|     Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore; |     Kernel::SharedPtr<Kernel::Semaphore> notification_semaphore; | ||||||
|  |     std::unordered_map<std::string, Kernel::SharedPtr<Kernel::Event>> | ||||||
|  |         get_service_handle_delayed_map; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace SM
 | } // namespace SM
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue