Thread Scheduling

Download Report

Transcript Thread Scheduling

Win32 Programming
Lesson 10: Thread Scheduling and Priorities
Where are we?



We’ve got thread basics worked out…
But it’s very helpful to understand how the
OS deals with thread scheduling
This lesson, we’ll work on scheduling threads
– understanding how each one gets executed
on the machine
Thread Context

Remember the kernel keeps a copy of the
thread context which contains important
runtime information


Such as?
Every 20ms or so, Windows looks at the
thread contexts on the machine and decided
which to allow to run

This is known as a context switch – see a tool like
Spy++
Context Switch (cntd)



After about 20ms, the Operating System saves
the processor’s internal state to thread’s
context and looks for the next thread to
execute
This cycle continues until the system shuts
down
Only “schedulable” threads can be run
Example: Notepad


When Notepad is just sitting about as a
Window with nothing to do, it is not marked
schedulable
When the OS sees that the Windows has been
moved or typed in, the thread is marked as
schedulable

NB: This is not the same as actually running the
thread – that still depends on the OS scheduler
Ensuring you get run



Often, want to make sure that there is no
latency between a particular action (maybe
data arriving on a port) and response
How?
Sorry, can’t be done easily. Windows is not a
Real-time operating system
Suspending and Resuming Threads




DWORD ResumeThread(HANDLE hThread)
DWORD SuspendThread(HANDLE hThread)
NB: A thread can be suspended multiple
times. If a thread is suspended more than
once, it must be resumed more than once
before it becomes schedulable
Danger, Will Robinson!

Randomly suspending a thread can cause
deadlocks. Don’t do this unless you know exactly
what the thread is doing!
Example: Suspending a Process



Why is the idea of suspending a process
meaningless?
What do we mean when we do this?
Let’s look at an example from VS2013
Sleeping


A thread can tell the OS that it wants to go to sleep
(that is, be unscheduled for a certain amount of time)
VOID Sleep(DWORD dwMilliseconds)




Calling Sleep automatically gives up the rest of this time
slice
The time to sleep is approximate – remember, Windows is
not a real-time OS
You can call Sleep with the parameter INFINITE. This is
not useful.
You can call Sleep with the parameter 0 to give up the
remainder of this timeslice
Switching to another Thread


Imagine you have a low-priority thread
locking a resource…
Can use BOOL SwitchToThread()



See if another thread is CPU starved and waiting
Returns FALSE if no other thread can run
Similar to Sleep except lower-priority threads
also execute
Aside: ThreadExecution Times

Naively, most simply take the time at the start of a
code block and the end, and subtract


No guarantee there weren’t thread switches in there!
Instead, can use

BOOL GetThreadTimes(
HANDLE hThread,
PFILETIME pftCreationTime,
PFILETIME pftExitTime,
PFILETIME pftKernelTime,
PFILETIME pftUserTime);
Thread Context Revisited



There is actually a structure for the thread context
documented by Microsoft… ooh!
Declared in winnt.h (see here for details)
So, if we wanted to we could stop a running thread
and modify its context… well, let’s look at the
example in the book…
Thread Priorities




Each thread can execute at a different priority
Priorities are assigned from 0 (lowest) to 31
(highest)
When the scheduler assigns a thread it always
passes control to a priority 31 thread if there
are any available to run
And so on, down the priorities…
Caveat Emptor



Microsoft does not fully document the
behavior of the scheduler
Microsoft tells you the scheduler is subject to
change
Microsoft provides an abstraction layer – you
can’t talk to the scheduler directly
Windows Priorities

Six process levels






Real-time: respond immediately to time-critical messages.
This priority is higher than task manager – it you use it,
you can hang the machine! BE CAREFUL!
High: threads which must respond. This is how task
manager runs
Above normal: between high and normal
Normal: No special scheduling needs
Below normal: between normal and idle
Idle: Only run when the system is basically idle
And then threads



You can set the relative thread priorities too…
This sets the overall priority
So, this all sounds good, but how do you do
it?
Programming Priorities


Parameter to CreateProcess
REALTIME_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
ABOVE_NORMAL_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS
DIY




A process can also call BOOL
SetPriorityClass(HANDLE hProcess, DWORD
fwdPriority)
Example: SetPriorityClass(GetCurrentProcess(),
IDLE_PRIORITY_CLASS)
Also DWORD GetPriorityClass(HANDLE
hProcess)
Similarly SetThreadPriority(HANDLE hThread, int
nPriority)
Tweaking the Scheduler

Can optimize the foreground or background
processes
Affinities

Can control which processor a thread executes
on, on a multi-processor machine

Why does this matter?
Assignment







Threading is a very useful technique
Write a network server which listens on Port 31337
The server should handle multiple clients, creating a new
thread for each client
The server simply echoes back what you type (but waits for a
newline)
A session is closed when the string “close” is typed to the
server
The console should provide a simple output which details the
number of threads in use when asked
Also, the console should remain responsive to a “shutdown”
request