Win32 Synchronization CS Spring 2002
Overview Kernel Synchronization - Spinlocks Executive Synchronization - Dispatcher Objects Wait Operations Dispatcher Objects - Events, Semaphores, Mutex objects, Waitable Timers
Kernel Synchronization Manipulating IRQL selectively disables interrupts -- controls context switching IRQL only works on a single processor Spinlocks, based e.g. on test & set instructions, work for multiprocessors Busy-wait wastes cycles - so holder is never preempted, is not allowed to cause page faults, do system calls, cause interrupts or exceptions, etc.
Executive Synchronization Executive also uses spinlocks Also uses dispatcher objects Dispatcher objects also available to user programs - Win32 calls include WaitForSingleObject and WaitForMultipleObjects applicable to processes, threads, events, semaphores, mutex objects, waitable timers, file objects, etc.
Thread Dispatcher States Terminated-4 Ready-1 Standby-3 Transition-6 Waiting-5 Running-2 Initialized-0 Create Destroy Done Wait for Object Reinitialize Preempt Select Context-Switch Need Resource Get resource All Set Ready to run
Dispatcher Database Thread 1 Thread 2 Thread 3 Thread 4 Process 5 Timer 0 KWAIT_BLOCKS Dispatchers
Wait Operations (1 of 2) DWORD WaitForSingleObjectEx( HANDLE hHandle, DWORD dwMilliseconds BOOL bAlertable); Returns WAIT_OBJECT_0 (zero), WAIT_TIMEOUT, WAIT_FAILED, or WAIT_IO_COMPLETION If object non-signaled, block thread. When signaled, one or more threads are readied - can change state of object.
Wait Operations (2 of 2) DWORD WaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE *lpHandles BOOL fWaitAll, DWORD dwMilliseconds, BOOL bAlertable); WAIT_OBJECT_0 to WAIT_OBJECT_n-1 to specify first signaled handle (if fWaitAll if false).
Events (1 of 2) HANDLE CreateEvent ( LPSECURITY_ATTRIBUTES lpSA, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName); HANDLE OpenEvent ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
Events (2 of 2) BOOL SetEvent ( HANDLE hEvent ); BOOL ResetEvent ( HANDLE hEvent ); BOOL PulseEvent ( HANDLE hEvent ); manual-reset versus auto-reset events setting versus pulsing CloseHandle used to close events
Mutual Exclusion (Events) Initialization: hEvent = CreateEvent( NULL, FALSE, TRUE, NULL); Critical Section Entry: WaitForSingleObjectEx( hEvent, INFINITE, FALSE); Critical Section Exit: SetEvent(hEvent);
Semaphores (1 of 2) HANDLE CreateSemaphore ( LPSECURITY_ATTRIBUTES lpSA, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName ); HANDLE OpenSemaphore ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );
Semaphores (2 of 2) BOOL ReleaseSemaphore ( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount ); lReleaseCount is 1 to release semaphore or larger in order to set an initial value. CloseHandle to close semaphore handle
Mutual Exclusion (Semaphore) Initialization: hSemaphore = CreateSemaphore( NULL, 1, 1, NULL); Critical Section Entry: WaitForSingleObjectEx( hSemaphore, INFINITE, FALSE); Critical Section Exit: ReleaseSemaphore( hSemaphore, 1, &previous);
Mutex Objects (1 of 2) HANDLE CreateMutex ( LPSECURITY_ATTRIBUTES lpSA, BOOL bInitialOwner, LPCTSTR lpName ); HANDLE OpenMutex ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );
Mutex Objects (2 of 2) BOOL ReleaseMutex ( HANDLE hMutex ); Owner can make additional calls Wait calls without blocking, but must call ReleaseMutex the same number of times. Use CloseHandle to close mutex handles.
Mutual Exclusion (Mutex) Initialization: hMutex = CreateMutex( NULL, FALSE, NULL); Critical Section Entry: WaitForSingleObject( hMutex, INFINITE, FALSE); Critical Section Exit: ReleaseMutex(hMutex);
Waitable Timers (1 of 2) HANDLE CreateWaitableTimer ( LPSECURITY_ATTRIBUTES lpSA, BOOL bManualReset, LPCTSTR lpTimerName ); HANDLE OpenWaitableTimer ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpTimerName );
Waitable Timers (2 of 2) BOOL SetWaitableTimer ( HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume ); BOOL CancelWaitableTimer (HANDLE);
Mutual Exclusion (Timer) 1 of 2 Initialization: LARGE_INTEGER dueTime = {-1, -1}; hTimer = (HANDLE) CreateWaitableTimer( NULL, FALSE, NULL); SetWaitableTimer( hTimer, &dueTime, 0, NULL, NULL, FALSE);
Mutual Exclusion (Timer) 2 of 2 Critical Section Entry: WaitForSingleObjectEx(hTimer, INFINITE, FALSE); Critical Section Exit: LARGE_INTEGER dueTime = {-1, -1}; SetWaitableTimer(hTimer, &dueTime, 0, NULL, NULL, FALSE);