200 likes | 357 Views
Win32 Programming. Lesson 12: Kernel-mode Thread Sync (aka: Why I love Gentoo). Where are we?. Yay! We can communicate between threads But, we’ve only talked about doing this in User-mode until now Sometimes, you need to go kernel-mode Why should we avoid this?. Limitations.
E N D
Win32 Programming Lesson 12: Kernel-mode Thread Sync (aka: Why I love Gentoo)
Where are we? • Yay! We can communicate between threads • But, we’ve only talked about doing this in User-mode until now • Sometimes, you need to go kernel-mode • Why should we avoid this?
Limitations • Interlocked functions never put the thread in a WAIT state • Critical Sections only work within a particular process – don’t work between processes • But… kernel-objects take a lot of effort… and I do mean a lot
Signaled/Non-signaled Objects • Can use almost any kernel object as a method of thread synchronization • Each object can be in a signaled or non-signaled state • State change is controlled by what type of object it is • Can put a thread in a wait state and wait for a signaling event
Signaling • Powerful, as you can make sure you don’t execute until a particular event happens • Thread puts itself into the WAIT state and won’t be scheduled until the object is signaled
Wait Functions • Voluntarily go into a WAIT state until OBJECT is signaled • WaitForSingleObject( HANDLE hObject, DWORD dwMilliseconds); • Can use INFINITE • E.g. WaitForSingleObject(hProcess, INFINITE) • Waits forever until a process exits
Example • DWORD dw = WaitForSingleObject(hProcess, 5000); switch (dw) { case WAIT_OBJECT_0: // The process terminated. break; case WAIT_TIMEOUT: // The process did not terminate within 5000 milliseconds. break; case WAIT_FAILED: // Bad call to function (invalid handle?) break; }
Multiple Objects… • DWORD WaitForMultipleObjects( DWORD dwCount, CONST HANDLE* phObjects, BOOL fWaitAll, DWORD dwMilliseconds); • phObject points to an array of Objects • Wait until one gets signaled or wait for all
Oops • WaitForMultipleObjects works atomically • So, if two threads are waiting on the same objects what happens?
Event Kernel Objects • Most basic of objects • Two kinds: manual (reset all waiting threads) and auto (reset only one waiting thread) • HANDLE CreateEvent( PSECURITY_ATTRIBUTES psa, BOOL fManualReset, BOOL fInitialState, PCTSTR pszName);
Example • Look at the Event example in the book… • Then let’s look at the next one…
Waitable Timer Kernel Objects • Used when you want to pause for a period of time (or regular intervals) • Easy to create: • HANDLE CreateWaitableTimer( PSECURITY_ATTRIBUTES psa, BOOL fManualReset, PCTSTR pszName);
Setting the Timer… • BOOL SetWaitableTimer( HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, PVOID pvArgToCompletionRoutine, BOOL fResume);
Semaphore Kernel Objects • Used for Resource counting • Contains • Maximum resource count • Current resource count • Consider • Server which can only handle 5 connections • Need to keep track of how many connections are open
Creating a Semaphore • Fairly simple: • HANDLE CreateSemaphore( PSECURITY_ATTRIBUTE psa, LONG lInitialCount, LONG lMaximumCount, PCTSTR pszName); • Examples are a little tricky – look this up in the book…
MutEx • Lets a thread have mutually-exclusive access to a particular resource • HANDLE CreateMutex( PSECURITY_ATTRIBUTES psa, BOOL fInitialOwner, PCTSTR pszName); • BOOL ReleaseMutex(HANDLE hMutex);
Other Thread Sync Functions • DWORD WaitForInputIdle( HANDLE hProcess, DWORD dwMilliseconds); • Suspend yourself until hProcess has no input to deal with • Can be used (sneakily) to feed messages into another process… *hehe*
SignalObjectAndWait • Signal a kernel object and wait on another kernel object • DWORD SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL fAlertable);
Assignment • Create a simple console application which calculates the prime factors of a given 32-bit unsigned int • You should prompt for input from the console window and the command line • However… you may use a maximum of 3 threads in your program, so you can be working out the answers in parallel • Output for 8 should be 2\n2\n2\n • And the entry/answer thread must always remain responsive • Output must be printed VERTICALLY… if there’s more than 10 lines, you should pause and wait for keyboard input • At no point when both threads are waiting to output should you be using CPU time – everything should be in the WAIT state