project 3 tutorial yuanhaoyu. project task implement class priorityscheduler complete an inner...
TRANSCRIPT
Project 3 TutorialyuanhaoYU
Project Task
Implement class PrioritySchedulercomplete an inner class PriorityQueue, whose instance stores queued threadcomplete an inner class ThreadState utilized to record associated prioritymake 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 sc
hedulerthe resource requests scheduler return a thread from the queuethe queue here means a data structure storing threads waiting for the
resource
Scheduler
Resource, Queue, and Scheduler
queue HH
Lock CCThread C holds
the resource
Resource Lock
Resource Lock contains a queue
instance
Thread H waits for the Lock; it actually
becomes a element of the queueWhen thread C releases the Lock,
Scheduler is utilized to decide which thread in the queue should be the next
one
Z
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
queue Z HH
Lock CC
this queue is actually a FIFO queue; All
threads are actually stored in the
member variable waitQueue of the class FifoQueue
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.When thread C releases the Lock,
nextThread() function will be called by resource. The FifoQueue will dequeuer
thread Z at front
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 threadFCFS 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 threadFCFS with the same priority level
Round Robin Scheduling
P0 P1P3 P2
0 5 11 14 22
Priority Scheduling
Priority Scheduler
queue Z:3 1 1 H:4H:411
Lock CC
The data structure acting the queue to
store threads should be implemented;
The data structure should be a member
of the queue class
Thread H with priority 4 and Z both wait for the
Lock; We can still assume Z comes first
and H comes last.
When thread C releases the Lock, nextThread() function will be called. Priority Scheduler should
return the one with highest priority H.
Thread Z with priority 3
Thread with priority 1
There should be a place to store the associated priority for each
thread
PriorityScheduler
There are two inner class in PrioritySchedulerClass PriorityQueue is responsible for storing waiting threadsClass ThreadState is responsible to record associated priority
PrioritySchedulerpublic 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
PrioritySchedulerprotected 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;
}
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
Implement these two functions to make sure that it returns the thread with highest priority
PriorityScheduler
protected class ThreadState {public ThreadState(KThread thread) {..}public int getPriority() {..}public int getEffectivePriority() {} // implement mepublic void setPriority(int priority) {} // implement mepublic void waitForAccess(PriorityQueue waitQueue) {}
// implement mepublic void acquire(PriorityQueue waitQueue) { } // implement me protected KThread thread;protected int 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
The data structure storing priority Consider how to store donated
priority
When will it happen?
queue
queue
Priority Donation
1 Z:4 C:3C:3 111
1 1 1 H:3H:3113->7
2->7
Lock 1
Lock 2Iter1: H donates to C
Iter2: C donates to LL:2
C:3C: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 t0Check if it waits in a queueDonate 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.PrioritySchedulerUnder Proj2Eclipse with Input:
--nachos.ag.ThreadGrader5
--nachos.ag.ThreadGrader6