mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Bill Tutt:
Calling Sleep(0) for a spinlock can cause a priority inversion, adding comments to explain what's going on.
This commit is contained in:
		
							parent
							
								
									65e69002a2
								
							
						
					
					
						commit
						ede8c6eea1
					
				
					 1 changed files with 24 additions and 1 deletions
				
			
		|  | @ -50,9 +50,32 @@ static PVOID WINAPI interlocked_cmp_xchg(PVOID *dest, PVOID exc, PVOID comperand | ||||||
| { | { | ||||||
| 	static LONG spinlock = 0 ; | 	static LONG spinlock = 0 ; | ||||||
| 	PVOID result ; | 	PVOID result ; | ||||||
|  | 	DWORD dwSleep = 0; | ||||||
| 
 | 
 | ||||||
| 	/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */ | 	/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */ | ||||||
| 	while(InterlockedExchange(&spinlock, 1)) Sleep(0) ; | 	while(InterlockedExchange(&spinlock, 1)) | ||||||
|  | 	{ | ||||||
|  | 		// Using Sleep(0) can cause a priority inversion.
 | ||||||
|  | 		// Sleep(0) only yields the processor if there's
 | ||||||
|  | 		// another thread of the same priority that's
 | ||||||
|  | 		// ready to run.  If a high-priority thread is
 | ||||||
|  | 		// trying to acquire the lock, which is held by
 | ||||||
|  | 		// a low-priority thread, then the low-priority
 | ||||||
|  | 		// thread may never get scheduled and hence never
 | ||||||
|  | 		// free the lock.  NT attempts to avoid priority
 | ||||||
|  | 		// inversions by temporarily boosting the priority
 | ||||||
|  | 		// of low-priority runnable threads, but the problem
 | ||||||
|  | 		// can still occur if there's a medium-priority
 | ||||||
|  | 		// thread that's always runnable.  If Sleep(1) is used,
 | ||||||
|  | 		// then the thread unconditionally yields the CPU.  We
 | ||||||
|  | 		// only do this for the second and subsequent even
 | ||||||
|  | 		// iterations, since a millisecond is a long time to wait
 | ||||||
|  | 		// if the thread can be scheduled in again sooner
 | ||||||
|  | 		// (~100,000 instructions).
 | ||||||
|  | 		// Avoid priority inversion: 0, 1, 0, 1,...
 | ||||||
|  | 		Sleep(dwSleep); | ||||||
|  | 		dwSleep = !dwSleep; | ||||||
|  | 	} | ||||||
| 	result = *dest ; | 	result = *dest ; | ||||||
| 	if (result == comperand) | 	if (result == comperand) | ||||||
| 		*dest = exc ; | 		*dest = exc ; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum