[Python-checkins] CVS: python/dist/src/Python thread_nt.h,2.8,2.9

Guido van Rossum python-dev@python.org
Thu, 11 May 2000 08:53:54 -0400 (EDT)


Update of /projects/cvsroot/python/dist/src/Python
In directory eric:/projects/python/develop/guido/src/Python

Modified Files:
	thread_nt.h 
Log Message:
Bill Tutt:

Calling Sleep(0) for a spinlock can cause a priority inversion, adding
comments to explain what's going on.


Index: thread_nt.h
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Python/thread_nt.h,v
retrieving revision 2.8
retrieving revision 2.9
diff -C2 -r2.8 -r2.9
*** thread_nt.h	2000/05/05 14:29:59	2.8
--- thread_nt.h	2000/05/11 12:53:51	2.9
***************
*** 51,57 ****
  	static LONG spinlock = 0 ;
  	PVOID result ;
  
  	/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
! 	while(InterlockedExchange(&spinlock, 1)) Sleep(0) ;
  	result = *dest ;
  	if (result == comperand)
--- 51,80 ----
  	static LONG spinlock = 0 ;
  	PVOID result ;
+ 	DWORD dwSleep = 0;
  
  	/* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */
! 	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 ;
  	if (result == comperand)