forked from eden-emu/eden
		
	Add implementation of svcCreateSession
This commit is contained in:
		
							parent
							
								
									6bcd676b61
								
							
						
					
					
						commit
						9b34afa588
					
				
					 2 changed files with 103 additions and 1 deletions
				
			
		|  | @ -29,6 +29,7 @@ | |||
| #include "core/hle/kernel/k_resource_limit.h" | ||||
| #include "core/hle/kernel/k_scheduler.h" | ||||
| #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||||
| #include "core/hle/kernel/k_session.h" | ||||
| #include "core/hle/kernel/k_shared_memory.h" | ||||
| #include "core/hle/kernel/k_synchronization_object.h" | ||||
| #include "core/hle/kernel/k_thread.h" | ||||
|  | @ -256,6 +257,93 @@ static Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u3 | |||
|     return UnmapMemory(system, dst_addr, src_addr, size); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u64 name) { | ||||
|     auto& process = *system.CurrentProcess(); | ||||
|     auto& handle_table = process.GetHandleTable(); | ||||
| 
 | ||||
|     // Declare the session we're going to allocate.
 | ||||
|     T* session; | ||||
| 
 | ||||
|     // Reserve a new session from the process resource limit.
 | ||||
|     // FIXME: LimitableResource_SessionCountMax
 | ||||
|     KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); | ||||
|     if (session_reservation.Succeeded()) { | ||||
|         session = T::Create(system.Kernel()); | ||||
|     } else { | ||||
|         return ResultLimitReached; | ||||
| 
 | ||||
|         // // We couldn't reserve a session. Check that we support dynamically expanding the
 | ||||
|         // // resource limit.
 | ||||
|         // R_UNLESS(process.GetResourceLimit() ==
 | ||||
|         //          &system.Kernel().GetSystemResourceLimit(), ResultLimitReached);
 | ||||
|         // R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), ResultLimitReached());
 | ||||
| 
 | ||||
|         // // Try to allocate a session from unused slab memory.
 | ||||
|         // session = T::CreateFromUnusedSlabMemory();
 | ||||
|         // R_UNLESS(session != nullptr, ResultLimitReached);
 | ||||
|         // ON_RESULT_FAILURE { session->Close(); };
 | ||||
| 
 | ||||
|         // // If we're creating a KSession, we want to add two KSessionRequests to the heap, to
 | ||||
|         // // prevent request exhaustion.
 | ||||
|         // // NOTE: Nintendo checks if session->DynamicCast<KSession *>() != nullptr, but there's
 | ||||
|         // // no reason to not do this statically.
 | ||||
|         // if constexpr (std::same_as<T, KSession>) {
 | ||||
|         //     for (size_t i = 0; i < 2; i++) {
 | ||||
|         //         KSessionRequest* request = KSessionRequest::CreateFromUnusedSlabMemory();
 | ||||
|         //         R_UNLESS(request != nullptr, ResultLimitReached);
 | ||||
|         //         request->Close();
 | ||||
|         //     }
 | ||||
|         // }
 | ||||
| 
 | ||||
|         // We successfully allocated a session, so add the object we allocated to the resource
 | ||||
|         // limit.
 | ||||
|         // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1);
 | ||||
|     } | ||||
| 
 | ||||
|     // Check that we successfully created a session.
 | ||||
|     R_UNLESS(session != nullptr, ResultOutOfResource); | ||||
| 
 | ||||
|     // Initialize the session.
 | ||||
|     session->Initialize(nullptr, fmt::format("{}", name)); | ||||
| 
 | ||||
|     // Commit the session reservation.
 | ||||
|     session_reservation.Commit(); | ||||
| 
 | ||||
|     // Ensure that we clean up the session (and its only references are handle table) on function
 | ||||
|     // end.
 | ||||
|     SCOPE_EXIT({ | ||||
|         session->GetClientSession().Close(); | ||||
|         session->GetServerSession().Close(); | ||||
|     }); | ||||
| 
 | ||||
|     // Register the session.
 | ||||
|     T::Register(system.Kernel(), session); | ||||
| 
 | ||||
|     // Add the server session to the handle table.
 | ||||
|     R_TRY(handle_table.Add(out_server, &session->GetServerSession())); | ||||
| 
 | ||||
|     // Add the client session to the handle table. */
 | ||||
|     const auto result = handle_table.Add(out_client, &session->GetClientSession()); | ||||
| 
 | ||||
|     if (!R_SUCCEEDED(result)) { | ||||
|         // Ensure that we maintaing a clean handle state on exit.
 | ||||
|         handle_table.Remove(*out_server); | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| static Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, | ||||
|                             u32 is_light, u64 name) { | ||||
|     if (is_light) { | ||||
|         // return CreateSession<KLightSession>(system, out_server, out_client, name);
 | ||||
|         return ResultUnknown; | ||||
|     } else { | ||||
|         return CreateSession<KSession>(system, out_server, out_client, name); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Connect to an OS service given the port name, returns the handle to the port to out
 | ||||
| static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) { | ||||
|     auto& memory = system.Memory(); | ||||
|  | @ -2860,7 +2948,7 @@ static const FunctionDef SVC_Table_64[] = { | |||
|     {0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"}, | ||||
|     {0x3E, nullptr, "Unknown3e"}, | ||||
|     {0x3F, nullptr, "Unknown3f"}, | ||||
|     {0x40, nullptr, "CreateSession"}, | ||||
|     {0x40, SvcWrap64<CreateSession>, "CreateSession"}, | ||||
|     {0x41, nullptr, "AcceptSession"}, | ||||
|     {0x42, nullptr, "ReplyAndReceiveLight"}, | ||||
|     {0x43, nullptr, "ReplyAndReceive"}, | ||||
|  |  | |||
|  | @ -346,6 +346,20 @@ void SvcWrap64(Core::System& system) { | |||
|     FuncReturn(system, retval); | ||||
| } | ||||
| 
 | ||||
| // Used by CreateSession
 | ||||
| template <Result func(Core::System&, Handle*, Handle*, u32, u64)> | ||||
| void SvcWrap64(Core::System& system) { | ||||
|     Handle param_1 = 0; | ||||
|     Handle param_2 = 0; | ||||
|     const u32 retval = func(system, ¶m_1, ¶m_2, static_cast<u32>(Param(system, 2)), | ||||
|                             static_cast<u32>(Param(system, 3))) | ||||
|                            .raw; | ||||
| 
 | ||||
|     system.CurrentArmInterface().SetReg(1, param_1); | ||||
|     system.CurrentArmInterface().SetReg(2, param_2); | ||||
|     FuncReturn(system, retval); | ||||
| } | ||||
| 
 | ||||
| // Used by WaitForAddress
 | ||||
| template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)> | ||||
| void SvcWrap64(Core::System& system) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Liam
						Liam