Chapter 9
Scheduling Processes
How does the O/S select a process (thread) from
the ready queue to execute? This depends to a large degree on our goals. Some
possibilities:
- Minimize turnaround time -- Complete the users' programs in the shortest
possible time.
- Minimize variance of average turnaround time -- In an interactive system,
predictability may be more important than a low average with high variance.
- Maximize throughput -- Two components:
- Minimize overhead (O/S overhead, context switching).
- Efficient use of system resources.
- Fairness -- Share the CPU in an equitable fashion. It turns out that
fairness involves a trade-off with average turnaround time. We can get better
turnaround time
by making the system less fair.
The standard scheduling disciplines were all developed in the 1970's. However,
they are based on some simplifying assumptions that were valid in the days of
single-process, single CPU scheduling. They are not completely realistic for
present multithreaded, multiprocessor systems. How best to relax these
assumptions is still an open research problem.
Some of the standard disciplines:
- FIFO: First In, First Out (a.k.a. FCFS -- First Come, First Served)
- The scheduler executes jobs to completion in arrival order.
- In early FIFO schedulers, the job did not relinquish the CPU even when
it was doing I/O.
- We will assume a FIFO scheduler that runs when processes are blocked,
but that is non-preemptive, i.e. the job keeps the CPU until it blocks or
terminates.
Advantage of FIFO: Simplicity.
Disadvantages of FIFO: Not fair; short jobs have to wait behind long jobs.
May lead to poor overlap of CPU and I/O.
- Round Robin: Most time sharing systems use some variation on this
policy.
- Shortest Job First: Schedule the job that has the least amount
of work (CPU
time) left to do.
- Optimal algorithm for minimizing average waiting time.
- Works for preemptive and non-preemptive schedulers.
- Preemptive SJF is called SRTF -- Shortest Remaining Time First.
Advantage of SJF: Gets short jobs out of the system quickly.
Disadvantage of SJF: May lead to starvation of long jobs. Impossible to
implement because we can't predict the future.
- Multi-Level Feedback Queues: Using the past to predict the future.
- If a process was I/O bound in the past, it is likely to be I/O bound
in the future (programs are not random).
- To exploit this behavior, the scheduler can favor jobs that have used
the least amount of CPU time, approximating SRTF.
- This policy is adaptive because it relies on past behavior; changes
in behavior result in changes in scheduling decisions.
Approximating Shortest Remaining Time First:
How do we predict the amount of CPU time a job has remaining? We can't.
So how do we approximate this knowledge? Use the past to predict the future.
- Jobs are made up of CPU and I/O time (basically).
- Keyboard and monitor I/O are interactive; need good turnaround time.
- Principle: Favor I/O bound jobs since they need the smallest amount
of CPU time.
- Problem: Long running CPU bound jobs can starve.
Using Multilevel Feedback Queues to Approximate SRTF:
- Use multiple queues with different priorities.
- O/S uses RR scheduling at each priority level.
- Jobs in highest priority queue are run first.
- Once queue is empty, scheduler moves to the next lowest priority queue.
- RR time slice increases exponentially at lower priorities.
Adjusting Priorities:
- Job starts in highest priority queue.
- If job's time slice expires, drop its priority one level.
- If job's time slice does not expire, then increase its priority one level
(but not above the top level).
In practice, CPU-bound jobs drop like a rock in priority, while I/O-bound
jobs stay at a high priority.
Scheduler Example -- Windows NT 4.0
Windows 3.1 has a simple non-preemptive scheduler. Application programmers
must insert an occasional Yield in their code to give the O/S a chance to take
over.
Windows XP has a much more elaborate scheduling policy:
- Basic scheduling unit is the thread.
- Each thread has a priority number in the range 1 to 31, the higher the
number the higher the priority.
- Priorities 16-31 are realtime priorities for time-critical
operations; they can be assigned only by someone with Administrator
privileges.
- Priorities 1-15 (the dynamic priorities) are used for applications.
- There is a special thread with priority 0; it is the idle thread, that
executes when no other thread is ready to run.
How does the scheduler choose the next thread to run?
- Scheduler is Round-Robin, priority-based, and preemptive.
- Scheduler makes a decision every time one of the three following events
occurs:
- A thread's quantum expires. (On NT Server the quantum is 120 ms; on
NT Workstation it is 20 or 40 or 60 ms, depending on systems settings and
whether the thread is a background or foreground thread.)
- A thread blocks waiting for some event to occur.
- A thread becomes ready to execute.
- When a thread's quantum expires or the thread is blocked, the scheduler
executes a FindReadyThread algorithm that finds the highest-priority ready
thread.
- When a new thread arrives or a blocked thread becomes ready, the scheduler
executes a ReadyThread algorithm. If the newly ready thread has a higher priority
than the running thread, then then the current thread is preempted.
Avoiding Starvation:
- Low-priority threads can be "boosted" by the Balance Set Manager
if they are in danger of starvation.
- ScanReadyQueues scans Dispacher Ready List, working down from priority
31, looking for a thread that hasn't executed in more than 3 seconds.
- When it finds such a thread, ScanReadyQueues gives the thread an
anti-starvation boost to the top of the dynamic range, doubles its quantum and calls
ReadyThread with that thread as parameter.
- Thread returns to previous priority level and quantum after it runs.
Bug (Feature?) in the Windows NT scheduler:
In NT a thread gets its quantum refreshed every time its thread or process
priority is set. That means that the thread can reset its quantum by calling
SetThreadPriority (without changing its priority) before its quantum expires.
By continuing this practice, it can give itself an effectively infinite quantum!
Scheduler Example -- Unix
- Traditional Unix scheduler uses multi-level feedback with round robin
within each priority queue.
- Original quantum was 1 sec. Beginning with 4.3BSD, quantum is 0.1 sec,
with priorities recomputed every 1 sec.
- Priority is based on process type and execution history.
- There were originally 40 priority levels; systems now have more than
that (Solaris has 160).
- An aging scheme is used to avoid starvation.
How priorities are computed:
P(j)(i) = Base(j) + CPU(j)(i-1)/2 + nice(j)
CPU(j)(i) = U(j)(i)/2 + CPU(j)(i-1)/2
P(j)(i) is the priority of process j at beginning of interval i.
Base(j) is the base priority of process j.
U(j)(i) is the processor utilization of process j in interval i.
CPU(j)(i) is the exponentially weighted average processor utilization by process j through interval i.
nice(j) is a user-controllable adjustment factor that can be used to lower a process's priority..