Scheduling
Lecture Notes for CS 140
Winter 2012
John Ousterhout
- Readings for this topic from Operating System Concepts:
Section 3.2, Sections 5.1-5.3, Section 5.6.
- Resources fall into two classes:
- Non-preemptible: once given, it can't be reused until
thread gives it back. Examples are file space, terminal,
and maybe memory.
- Preemptible: processor or I/O channel. Can take resource
away, use it for something else, then give it back later.
- OS makes two related kinds of decisions about resources:
- Allocation: who gets what. Given a set of requests for
resources, which processes should be given which
resources in order to make most efficient use of the
resources?
- Scheduling: how long can they keep it. When more
resources are requested than can be granted immediately,
in which order should the requests be serviced?
Examples are processor scheduling (one processor, many
threads), memory scheduling in virtual memory systems.
- For the purpose of scheduling, a thread is in one of 3 states:
- Running
- Ready: waiting for CPU time
- Blocked: waiting for some other event (disk I/O, incoming
network packet, etc.)
Simple Scheduling Algorithms
- First-come-first-served (FCFS) scheduling (also called FIFO
or non-preemptive):
- Keep all of the ready threads in a single list called
the ready queue.
- When a thread becomes ready, add it to the back of
the ready queue.
- Run the first thread on the queue until it exits or
blocks.
- Problem: one thread can monopolize the CPU.
- Solution: limit maximum amount of time that a thread can
run without a context switch. This time is called a
time slice.
- Round robin scheduling: run thread for one time slice,
then return to back of ready queue. Each thread gets
equal share of the CPU. Most systems use some variant
of this.
- Typical time slice values: 10-100ms
- The length of a time slice is also called
the time quantum.
- How do we decide whether a scheduling algorithm is good?
- Make users happy (minimize response time).
- Use resources efficiently:
- Full utilization: keep CPUs and disks busy
- Low overhead: minimize context switches
- Fairness (distribute CPU cycles equitably)
- Is round-robin better than FCFS?
- Optimal scheduling: STCF (Shortest Time to Completion First);
also called SJF (Shortest Job First)
- Run the thread that will finish most quickly, run it without
interruptions.
- Another advantage of STCF: improves overall resource
utilization.
- Suppose some jobs CPU-bound, some I/O-bound.
- STCF will give priority to I/O-bound jobs,
which keeps the disks/network as busy as possible.
- Key idea: can use past performance to predict future
performance.
- Behavior tends to be consistent
- If a process has been executing for a long time without
blocking, it's likely to continue executing.
Priority-Based Scheduling
- Priorities: most real schedulers support a priority for each
thread:
- Always run the thread with highest priority.
- In case of tie, use round-robin among highest priority threads
- Use priorities to implement various scheduling policies
(e.g. approximate STCF)
- Exponential Queues (or Multi-Level Feedback Queues):
attacks both efficiency and response time problems.
- One ready queue for each priority level.
- Lower-priority queues have larger time slices
(time slice doubles with each reduction in priority)
- Newly runnable thread starts in highest priority queue
- If it reaches the end of its time slice without blocking
it moved to the next lower queue.
- Result: I/O-bound threads stay in the highest-priority
queues, CPU-bound threads migrate to lower-priority queues
- 4.4 BSD Scheduler (for first project):
- Keep information about recent CPU usage for each thread
- Give highest priority to thread that has used the least
CPU time recently.
- Interactive and I/O-bound threads will use little CPU time and
remain at high priority.
- CPU-bound threads like compiles will eventually get lower
priority as they accumulate CPU time.
Multiprocessor Scheduling
- Multiprocessor scheduling can be mostly the same as
uniprocessor scheduling:
- Share the scheduling data structures among all of
the processors.
- Run the k highest-priority threads on the k processors.
- When a thread becomes runnable, see if its priority
is higher than the lowest-priority thread currently
running. If so, displace that thread.
- However, a single ready queue can result in contention
problems if there are lots of CPUs.
- 2 special issues for multiprocessors:
- Processor affinity:
- Once a thread has been running on a particular processor
it is expensive to move it to a different processor
(hardware caches will have to be reloaded).
- Multiprocessor schedulers typically try to keep a
thread on the same processor as much as possible to
minimize these overheads.
- Gang scheduling:
- If the threads within a process are communicating frequently,
it won't make sense to run one thread without the others:
it will just block immediately on communication with
another thread.
- Solution: run all of the threads of a process simultaneously
on different processors, so they can communicate more
efficiently.
- This is called gang scheduling.
- Even if a thread blocks, it may make sense to leave it
loaded on its processor, on the assumption that it will
unblock in the near future.
Conclusion
- Scheduling algorithms should not affect the behavior of
the system (same results regardless of schedule).
- However, the algorithms do impact the system's
efficiency and response time.
- The best schemes are adaptive. To do absolutely
best, we'd have to be able to predict the future.