mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Thread: update timeout when rerunning WaitSynch
This commit is contained in:
		
							parent
							
								
									63557e3fc1
								
							
						
					
					
						commit
						7d56e88369
					
				
					 1 changed files with 49 additions and 0 deletions
				
			
		|  | @ -181,6 +181,48 @@ static void PriorityBoostStarvedThreads() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Gets the registers for timeout parameter of the next WaitSynchronization call. | ||||||
|  |  * @param thread a pointer to the thread that is ready to call WaitSynchronization | ||||||
|  |  * @returns a tuple of two register pointers to low and high part of the timeout parameter | ||||||
|  |  */ | ||||||
|  | static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* thread) { | ||||||
|  |     bool thumb_mode = (thread->context.cpsr & TBIT) != 0; | ||||||
|  |     u16 thumb_inst = Memory::Read16(thread->context.pc & 0xFFFFFFFE); | ||||||
|  |     u32 inst = Memory::Read32(thread->context.pc & 0xFFFFFFFC) & 0x0FFFFFFF; | ||||||
|  | 
 | ||||||
|  |     if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { | ||||||
|  |         // svc #0x24 (WaitSynchronization1)
 | ||||||
|  |         return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); | ||||||
|  |     } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { | ||||||
|  |         // svc #0x25 (WaitSynchronizationN)
 | ||||||
|  |         return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     UNREACHABLE(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Updates the WaitSynchronization timeout paramter according to the difference | ||||||
|  |  * between ticks of the last WaitSynchronization call and the incoming one. | ||||||
|  |  * @param timeout_low a pointer to the register for the low part of the timeout parameter | ||||||
|  |  * @param timeout_high a pointer to the register for the high part of the timeout parameter | ||||||
|  |  * @param last_tick tick of the last WaitSynchronization call | ||||||
|  |  */ | ||||||
|  | static void UpdateTimeoutParameter(u32* timeout_low, u32* timeout_high, u64 last_tick) { | ||||||
|  |     s64 timeout = ((s64)*timeout_high << 32) | *timeout_low; | ||||||
|  | 
 | ||||||
|  |     if (timeout != -1) { | ||||||
|  |         timeout -= cyclesToUs(CoreTiming::GetTicks() - last_tick) * 1000; // in nanoseconds
 | ||||||
|  | 
 | ||||||
|  |         if (timeout < 0) | ||||||
|  |             timeout = 0; | ||||||
|  | 
 | ||||||
|  |         *timeout_low = timeout & 0xFFFFFFFF; | ||||||
|  |         *timeout_high = timeout >> 32; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Switches the CPU's active thread context to that of the specified thread |  * Switches the CPU's active thread context to that of the specified thread | ||||||
|  * @param new_thread The thread to switch to |  * @param new_thread The thread to switch to | ||||||
|  | @ -219,6 +261,13 @@ static void SwitchContext(Thread* new_thread) { | ||||||
| 
 | 
 | ||||||
|             // SVC instruction is 2 bytes for THUMB, 4 bytes for ARM
 |             // SVC instruction is 2 bytes for THUMB, 4 bytes for ARM
 | ||||||
|             new_thread->context.pc -= thumb_mode ? 2 : 4; |             new_thread->context.pc -= thumb_mode ? 2 : 4; | ||||||
|  | 
 | ||||||
|  |             // Get the register for timeout parameter
 | ||||||
|  |             u32* timeout_low, *timeout_high; | ||||||
|  |             std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); | ||||||
|  | 
 | ||||||
|  |             // Update the timeout parameter
 | ||||||
|  |             UpdateTimeoutParameter(timeout_low, timeout_high, new_thread->last_running_ticks); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Clean up the thread's wait_objects, they'll be restored if needed during
 |         // Clean up the thread's wait_objects, they'll be restored if needed during
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue