1 / 47

Programming with Windows* Threads

Programming with Windows* Threads. Intel Software College. Objectives. At the completion of this module you will be able to: Write code to create and terminate threads Use synchronization objects to coordinate thread execution and memory access. Agenda. Explore Win32 Threading API functions

tamera
Download Presentation

Programming with Windows* Threads

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programming with Windows* Threads Intel Software College

  2. Objectives • At the completion of this module you will be able to: • Write code to create and terminate threads • Use synchronization objects to coordinate thread execution and memory access Programming with Windows Threads

  3. Agenda • Explore Win32 Threading API functions • Create threads • Wait for threads to terminate • Synchronize shared access between threads • Labs to give hands-on experience Programming with Windows Threads

  4. Windows* HANDLE type • Each Windows object is referenced by HANDLEtype variables • Pointer to kernel objects • Thread, process, file, event, mutex, semaphore, etc. • Object creation functions return HANDLE • Object controlled through its handle • Don’t manipulate objects directly Programming with Windows Threads

  5. Windows* Thread Creation HANDLE CreateThread( LPSECURITY_ATTRIBUTES ThreadAttributes, DWORD StackSize, LPTHREAD_START_ROUTINE StartAddress, LPVOID Parameter, DWORD CreationFlags, LPDWORD ThreadId ); // Out Programming with Windows Threads

  6. LPTHREAD_START_ROUTINE • CreateThread() expects pointer to global function • Returns DWORD • Calling convention WINAPI • Single LPVOID (void *) parameter • Thread begins execution of function DWORD WINAPI MyThreadStart(LPVOID p); Programming with Windows Threads

  7. Using Explicit Threads • Identify portions of code to thread • Encapsulate code into function • If code is already a function, a driver function may need to be written to coordinate work of multiple threads • Add CreateThread call to assign thread(s) to execute function Programming with Windows Threads

  8. Destroying Threads • Frees OS resources • Clean-up if done with thread before program completes • Process exit does this for you • BOOL CloseHandle(HANDLE hObject); Programming with Windows Threads

  9. #include <stdio.h> #include <windows.h> DWORD WINAPI helloFunc(LPVOID arg ) { printf(“Hello Thread\n”); return 0; } main() { HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); } Example: Thread Creation What Happens? Programming with Windows Threads

  10. Example Explained • Main thread is process • When process goes, all threads go • Need some method of waiting for a thread to finish Programming with Windows Threads

  11. #include <stdio.h> #include <windows.h> BOOL threadDone = FALSE ; DWORD WINAPI helloFunc(LPVOID arg ) { printf(“Hello Thread\n”); threadDone = TRUE ; return 0; } main() { HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); while (!threadDone); } Waiting for Windows* Thread Not a good idea! // wasted cycles! Programming with Windows Threads

  12. Waiting for a Thread • Wait for one object (thread) • DWORD WaitForSingleObject( • HANDLE hHandle, • DWORD dwMilliseconds ); • Calling thread waits (blocks) until • Time expires • Return code used to indicate this • Thread exits (handle is signaled) • Use INFINITE to wait until thread termination • Does not use CPU cycles Programming with Windows Threads

  13. Waiting for Many Threads • Wait for up to 64 objects (threads) • DWORD WaitForMultipleObjects( • DWORD nCount, • CONST HANDLE *lpHandles, // array • BOOL fWaitAll, // wait for one or all • DWORD dwMilliseconds) • Wait for all: fWaitAll==TRUE • Wait for any: fWaitAll==FALSE • Return value is first array index found Programming with Windows Threads

  14. Notes on WaitFor* Functions • Handle as parameter • Used for different types of objects • Kernel objects have two states • Signaled • Non-signaled • Behavior is defined by object referred to by handle • Thread: signaled means terminated Programming with Windows Threads

  15. #include <stdio.h> #include <windows.h> const int numThreads = 4; DWORD WINAPI helloFunc(LPVOID arg ) { printf(“Hello Thread\n”); return 0; } main() { HANDLE hThread[numThreads]; for (int i = 0; i < numThreads; i++) hThread[i] = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); } Example: Multiple Threads Programming with Windows Threads

  16. Activity 1 - “HelloThreads” • Modify the previous example code to print out • Appropriate “Hello Thread” message • Unique thread number • Use for-loop variable of CreateThread loop • Sample output: • Hello from Thread #0 • Hello from Thread #1 • Hello from Thread #2 • Hello from Thread #3 Programming with Windows Threads

  17. What’s wrong? • What is printed for myNum? DWORD WINAPI threadFunc(LPVOID pArg) { int* p = (int*)pArg; int myNum = *p; printf( “Thread number %d\n”, myNum); } . . . // from main(): for (int i = 0; i < numThreads; i++) { hThread[i] = CreateThread(NULL, 0, threadFunc, &i, 0, NULL); } Programming with Windows Threads

  18. Hello Threads Timeline Programming with Windows Threads

  19. Race Conditions • Concurrent access of same variable by multiple threads • Read/Write conflict • Write/Write conflict • Most common error in concurrent programs • May not be apparent at all times Programming with Windows Threads

  20. How to Avoid Data Races • Scope variables to be local to threads • Variables declared within threaded functions • Allocate on thread’s stack • TLS (Thread Local Storage) • Control shared access with critical regions • Mutual exclusion and synchronization • Lock, semaphore, event, critical section, mutex… Programming with Windows Threads

  21. Solution – “Local” Storage DWORD WINAPI threadFunc(LPVOID pArg) { int myNum = *((int*)pArg); printf( “Thread number %d\n”, myNum); } . . . // from main(): for (int i = 0; i < numThreads; i++) { tNum[i] = i; hThread[i] = CreateThread(NULL, 0, threadFunc, &tNum[i], 0, NULL); } Programming with Windows Threads

  22. Windows* Mutexes • Kernel object reference by handle • “Signaled” when available • Operations: • CreateMutex(…) // create new • WaitForSingleObject // wait & lock • ReleaseMutex(…) // unlock • Available between processes Programming with Windows Threads

  23. Windows* Critical Section • Lightweight, intra-process only mutex • Most useful and most used • New type • CRITICAL_SECTION cs; • Create and destroy operations • InitializeCriticalSection(&cs) • DeleteCriticalSection(&cs); Programming with Windows Threads

  24. Windows* Critical Section • CRITICAL_SECTIONcs ; • Attempt to enter protected code • EnterCriticalSection(&cs) • Blocks if another thread is in critical section • Returns when no thread is in critical section • Upon exit of critical section • LeaveCriticalSection(&cs) • Must be from obtaining thread Programming with Windows Threads

  25. #define NUMTHREADS 4 CRITICAL_SECTION g_cs; // why does this have to be global? int g_sum = 0; DWORD WINAPI threadFunc(LPVOID arg ) { int mySum = bigComputation(); EnterCriticalSection(&g_cs); g_sum += mySum; // threads access one at a time LeaveCriticalSection(&g_cs); return 0; } main() { HANDLE hThread[NUMTHREADS]; InitializeCriticalSection(&g_cs); for (int i = 0; i < NUMTHREADS; i++) hThread[i] = CreateThread(NULL,0,threadFunc,NULL,0,NULL); WaitForMultipleObjects(NUMTHREADS, hThread, TRUE, INFINITE); DeleteCriticalSection(&g_cs); } Example: Critical Section Programming with Windows Threads

  26. f(x) = 1  4.0 dx =  (1+x2) 0 4.0 (1+x2) Numerical Integration Example 4.0 static long num_steps=100000; double step, pi; void main() { int i; double x, sum = 0.0; step = 1.0/(double) num_steps; for (i=0; i< num_steps; i++){ x = (i+0.5)*step; sum = sum + 4.0/(1.0 + x*x); } pi = step * sum; printf(“Pi = %f\n”,pi); } 2.0 0.0 1.0 X Programming with Windows Threads

  27. Activity 2 - Computing Pi • Parallelize the numerical integration code using Windows* Threads • How can the loop iterations be divided among the threads? • What variables can be local? • What variables need to be visible to all threads? static long num_steps=100000; double step, pi; void main() { int i; double x, sum = 0.0; step = 1.0/(double) num_steps; for (i=0; i< num_steps; i++){ x = (i+0.5)*step; sum = sum + 4.0/(1.0 + x*x); } pi = step * sum; printf(“Pi = %f\n”,pi); } Programming with Windows Threads

  28. Windows* Semaphores • Synchronization object that keeps a count • Represents the number of available resources • Formalized by Edsger Dijkstra (1968) • Two operations on semaphores • Wait [P(s)]: Thread waits until s > 0, then s = s-1 • Post [V(s)]: s = s + 1 • Semaphore is in signaled state if count > 0 Programming with Windows Threads

  29. Win32* Semaphore Creation • HANDLE CreateSemaphore( • LPSECURITY_ATTRIBUTES lpEventAttributes, • LONG lSemInitial, // Initial count value • LONG lSemMax, // Maximum value for count • LPCSTR lpSemName); // text name for object • Value of lSemMax must be 1 or greater • Value of lSemInitialmust be • greater than or equal to zero, • less than or equal to lSemMax,and • cannot go outside of range Programming with Windows Threads

  30. Wait and Post Operations • Use WaitForSingleObjectto wait on semaphore • If count is == 0, thread waits • Decrement count by 1 when count > 0 • Increment semaphore (Post operation) • BOOL ReleaseSemaphore( • HANDLE hSemaphore, • LONG cReleaseCount, • LPLONG lpPreviousCount ); • Increase semaphore count by cReleaseCount • Returns the previous count through lpPreviousCount Programming with Windows Threads

  31. Semaphore Uses • Control access to data structures of limited size • Queues, stacks, deques • Use count to enumerate available elements • Control access to finite number of resourse • File descriptors, tape drives… • Throttle number of active threads within a region • Binary semaphore [0,1] can act as mutex Programming with Windows Threads

  32. Semaphore Cautions • No ownership of semaphore • Any thread can release a semaphore, not just the last thread that waits • Use good programming practice to avoid this • No concept of abandoned semaphore • If thread terminates before post, semaphore increment may be lost • Deadlock Programming with Windows Threads

  33. Example: Semaphore as Mutex • Main thread opens input file, waits for thread termination • Threads will • Read line from input file • Count all five-letter words in line Programming with Windows Threads

  34. Example: Main HANDLE hSem1, hSem2; FILE *fd; int fiveLetterCount = 0; • main() • { HANDLE hThread[NUMTHREADS]; • hSem1 = CreateSemaphore(NULL, 1, 1, NULL); // Binary semaphore • hSem2 = CreateSemaphore(NULL, 1, 1, NULL); // Binary semaphore • fd = fopen(“InFile”, “r”); // Open file for read • for (int i = 0; i < NUMTHREADS; i++) • hThread[i] = CreateThread(NULL,0,CountFives,NULL,0,NULL); • WaitForMultipleObjects(NUMTHREADS, hThread, TRUE, INFINITE); • fclose(fd); • printf(“Number of five letter words is %d\n”, fiveLetterCount); • } Programming with Windows Threads

  35. Example: Semaphores • DWORD WINAPI CountFives(LPVOID arg) { • BOOL bDone = FALSE ; • char inLine[132]; int lCount = 0; • while (!bDone) • { • WaitForSingleObject(hSem1, INFINITE); // access to input • bDone = (GetNextLine(fd, inLine) == EOF); • ReleaseSemaphore(hSem1, 1, NULL); • if (!bDone) • if (lCount = GetFiveLetterWordCount(inLine)) { • WaitForSingleObject(hSem2, INFINITE); // update global • fiveLetterCount += lCount; • ReleaseSemaphore(hsem2, 1, NULL); • } • } • } Programming with Windows Threads

  36. Activity 3 – Using Semaphores • Use binary semaphores to control access to shared variables Programming with Windows Threads

  37. Windows* Events • Used to signal other threads that some event has occurred • Data is available, message is ready • Threads wait for signal with WaitFor* function • Two kinds of events • Auto-reset • Manual-reset Programming with Windows Threads

  38. Event stays signaled until any one thread waits and is released If no threads waiting, state stays signaled Once thread is released, state reset to non-signaled Event remains signaled until reset by API call Multiple threads can wait and be released Threads not originally waiting may start wait and be released Types of Events Auto-reset Manual-reset Caution: Be careful when using WaitForMultipleObjects to wait for ALL events Programming with Windows Threads

  39. Windows* Event Creation • HANDLE CreateEvent( • LPSECURITY_ATTRIBUTES lpEventAttributes, • BOOL bManualReset, // TRUE => manual reset • BOOL bInitialState, // TRUE => begin signaled • LPCSTR lpName); // text name for object • Set bManualReset to TRUE for manual-reset event; FALSE for auto-reset event • Set bInitialState to TRUE for event to begin in signaled state; FALSE to begin unsignaled Programming with Windows Threads

  40. Event Set and Reset • Set an event to signaled state • BOOL SetEvent( HANDLE event ); • Reset manual-reset event • BOOL ResetEvent( HANDLE event ); • Pulse event • BOOL PulseEvent( HANDLE event ); Programming with Windows Threads

  41. Example: Thread Search • Created thread searches for item • Signals if item is found • Main thread waits for signal and thread termination • Print message if item found • Print message upon thread termination • Illustrates • Using generic HANDLE type • Not waiting for every object to signal Programming with Windows Threads

  42. Example: Events • DWORD WINAPI threadFunc(LPVOID arg) { • BOOL bFound = bigFind() ; • if (bFound) • { • SetEvent(hObj[0]); // signal data was found • bigFound() ; • } • moreBigStuff() ; • return 0; • } HANDLE hObj[2]; // 0 is event, 1 is thread Programming with Windows Threads

  43. Example: Main function • . . . • hObj[0] = CreateEvent(NULL, FALSE, FALSE, NULL); • hObj[1] = CreateThread(NULL,0,threadFunc,NULL,0,NULL); • /* Do some other work while thread executes search */ • DWORD waitRet = • WaitForMultipleObjects(2, hObj, FALSE, INFINITE); • switch(waitRet) { • case WAIT_OBJECT_0: // event signaled • printf("found it!\n"); • WaitForSingleObject(hObj[1], INFINITE) ; • // fall thru • case WAIT_OBJECT_0+1: // thread signaled • printf("thread done\n"); • break ; • default: • printf("wait error: ret %u\n", waitRet); • break ; • } • . . . Programming with Windows Threads

  44. Example: Main function • . . . • hObj[0] = CreateEvent(NULL, FALSE, FALSE, NULL); • hObj[1] = CreateThread(NULL,0,threadFunc,NULL,0,NULL); • /* Do some other work while thread executes search */ • DWORD waitRet = • WaitForMultipleObjects(2, hObj, FALSE, INFINITE); • switch(waitRet) { • case WAIT_OBJECT_0: // event signaled • printf("found it!\n"); • WaitForSingleObject(hObj[1], INFINITE) ; • // fall thru • case WAIT_OBJECT_0+1: // thread signaled • printf("thread done\n"); • break ; • default: • printf("wait error: ret %u\n", waitRet); • break ; • } • . . . Programming with Windows Threads

  45. Activity 4 – Using Events • Replace spin-wait and thread counting variable with events to signal thread completion of computational piece Programming with Windows Threads

  46. Programming with Windows ThreadsWhat’s Been Covered • Create threads to execute work encapsulated within functions • Typical to wait for threads to terminate • Coordinate shared access between threads to avoid race conditions • Local storage to avoid conflicts • Synchronization objects to organize use Programming with Windows Threads

  47. Programming with Windows Threads

More Related