mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Services/GSP: Assign a thread id to each connected session when the session is created.
Most applications call AcquireRight before calling RegisterInterruptRelayQueue so we can't assign the thread id there. This fixes the bug with LLE applets not launching properly.
This commit is contained in:
		
							parent
							
								
									fbef978b98
								
							
						
					
					
						commit
						d17f148e48
					
				
					 2 changed files with 24 additions and 9 deletions
				
			
		|  | @ -53,6 +53,17 @@ constexpr ResultCode ERR_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorM | |||
| /// Maximum number of threads that can be registered at the same time in the GSP module.
 | ||||
| constexpr u32 MaxGSPThreads = 4; | ||||
| 
 | ||||
| /// Thread ids currently in use by the sessions connected to the GSPGPU service.
 | ||||
| static std::array<bool, MaxGSPThreads> used_thread_ids = {false, false, false, false}; | ||||
| 
 | ||||
| static u32 GetUnusedThreadId() { | ||||
|     for (u32 id = 0; id < MaxGSPThreads; ++id) { | ||||
|         if (!used_thread_ids[id]) | ||||
|             return id; | ||||
|     } | ||||
|     ASSERT_MSG(false, "All GSP threads are in use"); | ||||
| } | ||||
| 
 | ||||
| /// Gets a pointer to a thread command buffer in GSP shared memory
 | ||||
| static inline u8* GetCommandBuffer(Kernel::SharedPtr<Kernel::SharedMemory> shared_memory, | ||||
|                                    u32 thread_id) { | ||||
|  | @ -327,11 +338,7 @@ void GSP_GPU::RegisterInterruptRelayQueue(Kernel::HLERequestContext& ctx) { | |||
| 
 | ||||
|     interrupt_event->name = "GSP_GSP_GPU::interrupt_event"; | ||||
| 
 | ||||
|     u32 thread_id = next_thread_id++; | ||||
|     ASSERT_MSG(thread_id < MaxGSPThreads, "GSP thread id overflow"); | ||||
| 
 | ||||
|     SessionData* session_data = GetSessionData(ctx.Session()); | ||||
|     session_data->thread_id = thread_id; | ||||
|     session_data->interrupt_event = std::move(interrupt_event); | ||||
|     session_data->registered = true; | ||||
| 
 | ||||
|  | @ -345,7 +352,7 @@ void GSP_GPU::RegisterInterruptRelayQueue(Kernel::HLERequestContext& ctx) { | |||
|         rb.Push(RESULT_SUCCESS); | ||||
|     } | ||||
| 
 | ||||
|     rb.Push(thread_id); | ||||
|     rb.Push(session_data->thread_id); | ||||
|     rb.PushCopyObjects(shared_memory); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_GSP, "called, flags=0x%08X", flags); | ||||
|  | @ -752,5 +759,14 @@ GSP_GPU::GSP_GPU() : ServiceFramework("gsp::Gpu", 2) { | |||
| 
 | ||||
|     first_initialization = true; | ||||
| }; | ||||
| 
 | ||||
| SessionData::SessionData() { | ||||
|     // Assign a new thread id to this session when it connects. Note: In the real GSP service this
 | ||||
|     // is done through a real thread (svcCreateThread) but we have to simulate it since our HLE
 | ||||
|     // services don't have threads.
 | ||||
|     thread_id = GetUnusedThreadId(); | ||||
|     used_thread_ids[thread_id] = true; | ||||
| } | ||||
| 
 | ||||
| } // namespace GSP
 | ||||
| } // namespace Service
 | ||||
|  |  | |||
|  | @ -180,10 +180,12 @@ struct CommandBuffer { | |||
| static_assert(sizeof(CommandBuffer) == 0x200, "CommandBuffer struct has incorrect size"); | ||||
| 
 | ||||
| struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase { | ||||
|     SessionData(); | ||||
| 
 | ||||
|     /// Event triggered when GSP interrupt has been signalled
 | ||||
|     Kernel::SharedPtr<Kernel::Event> interrupt_event; | ||||
|     /// Thread index into interrupt relay queue
 | ||||
|     u32 thread_id = 0; | ||||
|     u32 thread_id; | ||||
|     /// Whether RegisterInterruptRelayQueue was called for this session
 | ||||
|     bool registered = false; | ||||
| }; | ||||
|  | @ -363,9 +365,6 @@ private: | |||
|     /// Returns the session data for the specified registered thread id, or nullptr if not found.
 | ||||
|     SessionData* FindRegisteredThreadData(u32 thread_id); | ||||
| 
 | ||||
|     /// Next threadid value to use when RegisterInterruptRelayQueue is called.
 | ||||
|     u32 next_thread_id = 0; | ||||
| 
 | ||||
|     /// GSP shared memory
 | ||||
|     Kernel::SharedPtr<Kernel::SharedMemory> shared_memory; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue