win32 programming lesson 9: jobs & thread basics

22
Win32 Programming Lesson 9: Jobs & Thread Basics

Upload: peregrine-rodgers

Post on 26-Dec-2015

231 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Win32 Programming Lesson 9: Jobs & Thread Basics

Win32 ProgrammingLesson 9: Jobs & Thread Basics

Page 2: Win32 Programming Lesson 9: Jobs & Thread Basics

Where are we? We’ve got processes sort of worked out… But every process must have a thread

associated with it This lesson, we’ll work on threads –

understanding threads is critical to understanding Windows programming

Also, a little bit on jobs…

Page 3: Win32 Programming Lesson 9: Jobs & Thread Basics

What is a Job A collection of processes For example, imagine interrupting the build in

Visual Studio Windows 2000 offered a new kernel object to

allow this

Page 4: Win32 Programming Lesson 9: Jobs & Thread Basics

Basic Idea Create a Job Kernel Object

CreateJobObject Place restrictions on the job object

SetInformationJobObject Start up some processes…

CreateProcess But, set CREATE_SUSPENDED flag Assign processes to job Start the primary thread of each process

Page 5: Win32 Programming Lesson 9: Jobs & Thread Basics

Termination You can stop all processes in a job simply by

terminating the Job Object TerminateJobObject(HANDLE hJob, UInt

uExitCode)

Page 6: Win32 Programming Lesson 9: Jobs & Thread Basics

Threads Each thread is made up of two objects

A kernel object used by the Operating System to manage the thread

A thread stack that maintains local variables and function parameters as the thread executes

Page 7: Win32 Programming Lesson 9: Jobs & Thread Basics

Threads v. Processes Processes take up a lot more system resources

than threads Processes are inert – they are simply a

container for one or more threads Always solve a problem by adding threads

not processes if you possibly can!

Page 8: Win32 Programming Lesson 9: Jobs & Thread Basics

When to Create Threads Many applications only have one thread The process terminates when the primary

thread finishes However, processes can have as many threads

are you like… and there’s no reason for the CPU to be idle (unless you’re on a laptop!) Example: Web browsers have separate threads for

IO so the UI remains responsive

Page 9: Win32 Programming Lesson 9: Jobs & Thread Basics

When Not to Create Threads Some things really do need to happen in

sequence Word processor, with its own thread for

printing… why not? UI’s – have one GetMessage loop, with multiple

worker threads Moral: Don’t use multiple threads just

because you can

Page 10: Win32 Programming Lesson 9: Jobs & Thread Basics

Creating Threads Once you’ve got one thread running (i.e.

you’ve executed your program) you can start more

See MSDN for an example application Based upon a thread function which gets

called, of form: DWORD WINAPI ThreadFunc(PVOID

pvParam)

Page 11: Win32 Programming Lesson 9: Jobs & Thread Basics

Caveat Emptor Use Local variables in threads wherever you

can – static and global variables can be modified at any time by other threads, leading to all sorts of interesting race conditions

Your thread function must return a DWORD value

Page 12: Win32 Programming Lesson 9: Jobs & Thread Basics

CreateThread HANDLE CreateThread(    

PSECURITY_ATTRIBUTES psa,    DWORD cbStack,    

PTHREAD_START_ROUTINE pfnStartAddr,    

PVOID pvParam,    DWORD fdwCreate,    PDWORD pdwThreadID);

Page 13: Win32 Programming Lesson 9: Jobs & Thread Basics

Parms psa: Security attributes – usually NULL if you

want the default cbStack: The amount of stack space to

reserve; 0 gets you the default pfnStartAddr: Pointer to the function to call to

start the thread pvParam: Pointer to any parameters you wish

to pass

Page 14: Win32 Programming Lesson 9: Jobs & Thread Basics

Bugs DWORD WINAPI FirstThread(PVOID pvParam) {    

// Initialize a stack-based variable    int x = 0;    DWORD dwThreadID;    // Create a new thread.    HANDLE hThread = CreateThread(NULL, 0, SecondThread, (PVOID) &x,

      0, &dwThreadId);    // We don't reference the new thread anymore,     // so close our handle to it.    CloseHandle(hThread);   // Our thread is done.    // BUG: our stack will be destroyed, but      //      SecondThread might try to access it.    return(0);

} DWORD WINAPI SecondThread(PVOID pvParam) {    

// Do some lengthy processing here.        // Attempt to access the variable on FirstThread's stack.    // NOTE: This may cause an access violation _ it depends on timing!    * ((int *) pvParam) = 5;        return(0);

}

Page 15: Win32 Programming Lesson 9: Jobs & Thread Basics

How to Solve this Problem Hokey: create a static variable so the memory is

allocated away from the thread stack Better: use proper thread synchronization techniques

– but that’s another story

Page 16: Win32 Programming Lesson 9: Jobs & Thread Basics

Parms (cntd) fdwCreate: 0 (get on with it) and

CREATE_SUSPENDED (create it paused). See JobLab example for how to use this flag

pdwThreadID: the address of a DWORD in which CreateThread stores the ID assigned to the new thread

Page 17: Win32 Programming Lesson 9: Jobs & Thread Basics

Terminating a Thread Four ways:

The thread function returns (good) The thread kills itself by calling ExitThread (bad) Another thread calls TerminateThread (bad) The process containing the thread terminates (bad)

Can use function to get exit code: BOOL GetExitCodeThread(    

HANDLE hThread,      PDWORD pdwExitCode);

Page 18: Win32 Programming Lesson 9: Jobs & Thread Basics

Thread Startup

Page 19: Win32 Programming Lesson 9: Jobs & Thread Basics

Thread Context Each thread has its own set of CPU registers Saved in a CONTEXT structure contained in

the thread’s kernel object IP and SP are the most important BaseThreadStart is called internally by the OS

Page 20: Win32 Programming Lesson 9: Jobs & Thread Basics

BaseThreadStart Sets up default SEH System calls the function pointed to in

CreateThread, passing in pvParam On Thread exit, return return code If an exception is caught, handle it; this

involves terminating the entire process not just the offending thread

Page 21: Win32 Programming Lesson 9: Jobs & Thread Basics

C/C++ Considerations Beware: You’re reading about how the OS

handles threads. Missing logical “sugar” when considering the C/C++ RTLs

Read the MSDN section on threads – it’s very useful!

Also: _beginthreadex

Page 22: Win32 Programming Lesson 9: Jobs & Thread Basics

A Sense of Self Threads can learn about themselves via:

HANDLE GetCurrentProcess() HANDLE GetCurrentThread() Return pseudo-handles not true unique identifiers See also GetProcessTimes and GetThreadTimes Can use DuplicateHandle to get a real handle to

the thread