Project 3 Tutorial - McMaster University

Download Report

Transcript Project 3 Tutorial - McMaster University

Project 3 Tutorial
yuanhaoYU
Project Task
Implement class PriorityScheduler
complete an inner class PriorityQueue, whose instance stores queued thread
complete an inner class ThreadState utilized to record associated priority
make class PriorityScheduler functional.
solve Priority Donation problem
Scheduler
Scheduler is responsible for scheduling threads for all limited
resources, CPU, Lock, and Semaphore
Black Box Perspective:
the resource (e.g. class Lock) is responsible for adding thread to a queue of
scheduler
the resource requests scheduler return a thread from the queue
the queue here means a data structure storing threads waiting for the
resource
Scheduler
Resource, Queue, and Scheduler
Resource Lock
Lock
C
Thread C holds
the resource
queue
Resource Lock
contains a queue
instance
Z
When thread C releases the Lock,
Scheduler is utilized to decide which thread
in the queue should be the next one
H
Thread H waits for the
Lock; it actually
becomes a element of
the queue
RoundRobinScheduler
What’s Round Robin scheduler?
RoundRobinScheduler
public class RoundRobinScheduler extends Scheduler {
public RoundRobinScheduler() {
}
public ThreadQueue newThreadQueue(boolean transferPriority) {
return new FifoQueue();
}
private class FifoQueue extends ThreadQueue {
public void waitForAccess(KThread thread) {
Lib.assertTrue(Machine.interrupt().disabled());
waitQueue.add(thread);
}
public KThread nextThread() {
Lib.assertTrue(Machine.interrupt().disabled());
if (waitQueue.isEmpty())
return null;
return (KThread) waitQueue.removeFirst();
}
 Construct a new FifoQueue
Instance in memory. It is usually
called by initialization of
resource
 Basically, each kind scheduler
needs to design its own
corresponding queue;
 Round Robin Scheduler makes
use of a FIFO queue: the
FifoQueue class is declared in
the Scheduler class;
 Most importantly, the data
structure storing threads should
be a member of this class
 called by resource and enqueuer
a thread
 called by resource and request a
waiting thread
RoundRobinScheduler
public void acquire(KThread thread) {
Lib.assertTrue(Machine.interrupt().disabled());
Lib.assertTrue(waitQueue.isEmpty());
}
public void print() {
Lib.assertTrue(Machine.interrupt().disabled());
for (Iterator i=waitQueue.iterator(); i.hasNext(); )
System.out.print((KThread) i.next() + " ");
}
private LinkedList<KThread> waitQueue = new
LinkedList<KThread>();
}
}
 resource inform queue that it is
occupied by a thread
 In RR, just check some
conditions and do nothing
 All threads waiting are actually
stored here in waitQueue
 This data structure is
implemented by LinkedList
 the whole class fifoQueue is
designed to make this
waitQueue act like a FIFO queue
RoundRobinScheduler
Resource, Queue, and Scheduler in RR
Lock
C
this queue is actually
a FIFO queue; All
threads are actually
stored in the
member variable
waitQueue of the
class FifoQueue
queue
Z
When thread C releases the Lock,
nextThread() function will be called by
resource. The FifoQueue will dequeuer
thread Z at front
H
Thread H and Z both
wait for the Lock; they
actually wait in the
waitQueue; We can
assume Z comes first
and H comes last.
Priority Scheduler
When resource requests a thread, priority scheduler should return
the one with the highest priority
Features:
each thread is assigned with a priority
always select the highest priority thread
FCFS with the same priority level
Priority Scheduler
When request a thread in queue, priority scheduler should return
the one with highest priority
Features:
each thread is assigned with a priority
always select the highest priority thread
FCFS with the same priority level
P3
P0
P2
P1
Priority Scheduling
0
5
11
14
22
Round Robin Scheduling
Priority Scheduler
There should be a place to store
the associated priority for each
thread
Thread with
priority 1
Thread Z with
priority 3
Lock
C
The data structure
acting the queue to
store threads should
be implemented;
The data structure
should be a member
of the queue class
queue
Z:3
1
1
1
1
H:4
When thread C releases the Lock, nextThread()
function will be called. Priority Scheduler should
return the one with highest priority H.
Thread H with priority 4
and Z both wait for the
Lock; We can still
assume Z comes first
and H comes last.
PriorityScheduler
There are two inner class in PriorityScheduler
Class PriorityQueue is responsible for storing waiting threads
Class ThreadState is responsible to record associated priority
PriorityScheduler
public class PriorityScheduler extends Scheduler {
public PriorityScheduler() {..}
public ThreadQueue newThreadQueue(boolean transferPriority) {..}
public int getPriority(KThread thread) {..}
public int getEffectivePriority(KThread thread) {..}
public void setPriority(KThread thread, int priority) {..}
public boolean increasePriority() {..}
public boolean decreasePriority() {..}
public static final int priorityDefault = 1;
public static final int priorityMinimum = 0;
public static final int priorityMaximum = 7;
protected ThreadState getThreadState(KThread thread) {..}
protected class PriorityQueue extends ThreadQueue {..}
protected class ThreadState {...}
}
 called by resource and return a
instance of priority queue
 Priority operation
 In these functions, methods
(functions) of ThreadState will be
called to actually operate
priority, since the priority is
stored there
 Inner class PriorityQueue
 The data structure storing
threads should be a member
variable in the class
 Inner class ThreadState
 The data structure storing
priority should be a member
variable in the class
PriorityScheduler
protected class PriorityQueue extends ThreadQueue {
PriorityQueue(boolean transferPriority) {..}
public void waitForAccess(KThread thread) {..}
public void acquire(KThread thread) {..}
public KThread nextThread() {
Lib.assertTrue(Machine.interrupt().disabled());
// implement me
return null;
}
protected ThreadState pickNextThread() {
// implement me
return null;
}
public boolean transferPriority;
}
 Implement these two functions to
make sure that it returns the
thread with highest priority
 Attention: the data structure
storing threads needs to be
implemented
 You could choose any suitable
data structure like heap,
linkedlist, but have to make sure
it act like priority queue
 So, there may be some
additional functions you need to
implement
PriorityScheduler
protected class ThreadState {
public ThreadState(KThread thread) {..}
public int getPriority() {..}
public int getEffectivePriority() {} // implement me
public void setPriority(int priority) {} // implement me
public void waitForAccess(PriorityQueue waitQueue) {}
// implement me
public void acquire(PriorityQueue waitQueue) { } // implement me
protected KThread thread;
protected int priority;
}
 The data structure storing priority
 Consider how to store donated
priority
 You can implement priority
donation here, since the priority
is stored here.
 To donate priority, you may need
to find another thread holding a
queue; consider how to find that
thread
Priority Donation
When will it happen?
L:2
Lock 1
Iter2: C donates to L
2->7
queue
1
C:3
Z:4
1
C:3
1
1
Lock 2
Iter1: H donates to C
3->7
queue
1
1
1
1
1
H:3
Change priority from 3 to 7
Priority Donation
In Nachos, we can assume a thread only waits in one queue.
Logic:
Starts from a thread t0
Check if it waits in a queue
Donate its real priority to the thread t1 holding the queue
Restore priority
 in the dequeue part (why?)
Compile and Execute
When Nachos initializes, a particular scheduler will be created
according to the configure file.
ThreadedKernel.scheduler = nachos.threads.PriorityScheduler
Under Proj2
Eclipse with Input:
-nachos.ag.ThreadGrader5
-nachos.ag.ThreadGrader6