nachos priority scheduler with nonation

来源:互联网 发布:网络通信公司简介 编辑:程序博客网 时间:2024/05/30 20:09
package nachos.threads;import java.util.ArrayList;import java.util.LinkedList;import nachos.machine.*;/** * A scheduler that chooses threads based on their priorities. * * <p> * A priority scheduler associates a priority with each thread. The next thread * to be dequeued is always a thread with priority no less than any other * waiting thread's priority. Like a round-robin scheduler, the thread that is * dequeued is, among all the threads of the same (highest) priority, the * thread that has been waiting longest. * * <p> * Essentially, a priority scheduler gives access in a round-robin fassion to * all the highest-priority threads, and ignores all other threads. This has * the potential to * starve a thread if there's always a thread waiting with higher priority. * * <p> * A priority scheduler must partially solve the priority inversion problem; in * particular, priority must be donated through locks, and through joins. */public class PriorityScheduler extends Scheduler {    /**     * Allocate a new priority scheduler.     */    public PriorityScheduler() {    }        /**     * Allocate a new priority thread queue.     *     * @paramtransferPriority<tt>true</tt> if this queue should     *transfer priority from waiting threads     *to the owning thread.     * @returna new priority thread queue.     */    public ThreadQueue newThreadQueue(boolean transferPriority) {return new PriorityQueue(transferPriority);    }    public int getPriority(KThread thread) {Lib.assertTrue(Machine.interrupt().disabled());       return getThreadState(thread).getPriority();    }    public int getEffectivePriority(KThread thread) {Lib.assertTrue(Machine.interrupt().disabled());       return getThreadState(thread).getEffectivePriority();    }    public void setPriority(KThread thread, int priority) {Lib.assertTrue(Machine.interrupt().disabled());       Lib.assertTrue(priority >= priorityMinimum &&   priority <= priorityMaximum);getThreadState(thread).setPriority(priority);    }    public boolean increasePriority() {boolean intStatus = Machine.interrupt().disable();       KThread thread = KThread.currentThread();int priority = getPriority(thread);if (priority == priorityMaximum)    return false;setPriority(thread, priority+1);Machine.interrupt().restore(intStatus);return true;    }    public boolean decreasePriority() {boolean intStatus = Machine.interrupt().disable();       KThread thread = KThread.currentThread();int priority = getPriority(thread);if (priority == priorityMinimum)    return false;setPriority(thread, priority-1);Machine.interrupt().restore(intStatus);return true;    }    /**     * The default priority for a new thread. Do not change this value.     */    public static final int priorityDefault = 1;    /**     * The minimum priority that a thread can have. Do not change this value.     */    public static final int priorityMinimum = 0;    /**     * The maximum priority that a thread can have. Do not change this value.     */    public static final int priorityMaximum = 7;        /**     * Return the scheduling state of the specified thread.     *     * @paramthreadthe thread whose scheduling state to return.     * @returnthe scheduling state of the specified thread.     */    public ThreadState getThreadState(KThread thread) {if (thread.schedulingState == null)    thread.schedulingState = new ThreadState(thread);return (ThreadState) thread.schedulingState;    }    /**     * A <tt>ThreadQueue</tt> that sorts threads by priority.     */                            protected class PriorityQueue extends ThreadQueue {        /** The List which acts like a max heap/priority queue*/    public ArrayList<KThread> heap = new ArrayList<KThread>();    public KThread lockOwner;PriorityQueue(boolean transferPriority) {    this.transferPriority = transferPriority;}public void waitForAccess(KThread thread) {    Lib.assertTrue(Machine.interrupt().disabled());    getThreadState(thread).waitForAccess(this);}public void acquire(KThread thread) {    Lib.assertTrue(Machine.interrupt().disabled());    getThreadState(thread).acquire(this);}public void add(KThread kt){heap.add(kt);siftUp();}private void siftDown(){if (heap.size() <=1)return;int left,right;int me=0;int size=heap.size();int max;ThreadState leftTS, rightTS, myTS;myTS=getThreadState(heap.get(me));while(true){max=me;left=(me+1)*2-1;if (left<size){leftTS=getThreadState(heap.get(left));if(leftTS.getEffectivePriority() > myTS.getEffectivePriority())max=left;}else return;right=(me+1)*2;if(right<size){rightTS=getThreadState(heap.get(right));if (rightTS.getEffectivePriority() > myTS.getEffectivePriority()&& rightTS.getEffectivePriority() > leftTS.getEffectivePriority()){max=right;}}if (max==me)return;else{ThreadState childTS = getThreadState(heap.get(max));if (myTS.getEffectivePriority() == childTS.getEffectivePriority() &&myTS.thread.timeAddedToWaitQ > childTS.thread.timeAddedToWaitQ){swap(me,max);me = max;}else{if (myTS.getEffectivePriority() < childTS.getEffectivePriority()){swap(me,max);me = max;}else{break;}}swap(me,max);}}}private void siftUp(){if (heap.size() <=1)return;int me = heap.size()-1;ThreadState myTS, parentTS;while(me!=0){int parent=(me-1)/2;myTS=getThreadState(heap.get(me));parentTS=getThreadState(heap.get(parent));if (myTS.getEffectivePriority() == parentTS.getEffectivePriority() &&myTS.thread.timeAddedToWaitQ < parentTS.thread.timeAddedToWaitQ){swap(me,parent);me = parent;}else{if (myTS.getEffectivePriority() > parentTS.getEffectivePriority()){swap(me,parent);me = parent;}else{break;}}}}private void siftUp(int siftIndex){if (heap.size() <=1)return;int me = siftIndex;ThreadState myTS, parentTS;while(me!=0){int parent=(me-1)/2;myTS=getThreadState(heap.get(me));   parentTS=getThreadState(heap.get(parent));if (myTS.getEffectivePriority() == parentTS.getEffectivePriority() &&myTS.thread.timeAddedToWaitQ < parentTS.thread.timeAddedToWaitQ){swap(me,parent);me = parent;}else{if (myTS.getEffectivePriority() > parentTS.getEffectivePriority()){swap(me,parent);me = parent;}else{break;}}}}public void sort(){for (int i =0;i<heap.size();i++){siftUp(i);}}private void swap(int a, int b){ KThread temp = heap.get(a); heap.set(a, heap.get(b)); heap.set(b, temp);}private KThread dequeue(){if (heap.size()==0 || heap.get(0)==null) return null;swap(0,heap.size()-1);KThread returnThread=heap.get(heap.size()-1);heap.remove(heap.size()-1);siftDown();return returnThread;}private KThread peek(){return heap.get(0);}public KThread nextThread() {    Lib.assertTrue(Machine.interrupt().disabled());    KThread t = this.dequeue();    if(t!= null){        ThreadState ts = getThreadState(t);    ts.waitIn = null;    ts.donatedPriority = 0;    }    return t;   }/** * Return the next thread that <tt>nextThread()</tt> would return, * without modifying the state of this queue. * * @returnthe next thread that <tt>nextThread()</tt> would *return. */protected ThreadState pickNextThread() {       return getThreadState(this.peek());}public void print() {    Lib.assertTrue(Machine.interrupt().disabled());    // implement me (if you want) }/** * <tt>true</tt> if this queue should transfer priority from waiting * threads to the owning thread. */public boolean transferPriority;    }    /**     * The scheduling state of a thread. This should include the thread's     * priority, its effective priority, any objects it owns, and the queue     * it's waiting for, if any.     *     * @seenachos.threads.KThread#schedulingState     */    protected class ThreadState {/** * Allocate a new <tt>ThreadState</tt> object and associate it with the * specified thread. * * @paramthreadthe thread this state belongs to. */public ThreadState(KThread thread) {    this.thread = thread;        setPriority(priorityDefault);}/** * Return the priority of the associated thread. * * @returnthe priority of the associated thread. */public int getPriority() {    return priority;}/** * Return the effective priority of the associated thread. * * @returnthe effective priority of the associated thread. */public int getEffectivePriority() {    if (priority >=donatedPriority)    return priority;else return donatedPriority;}/** * Set the priority of the associated thread to the specified value. * * @paramprioritythe new priority. */public void setPriority(int priority) {    if (this.priority == priority)return;    if(waitIn != null && waitIn.transferPriority)computeDonations(thread);    this.priority = priority;    if (waitIn!=null)    {    if(!waitIn.heap.isEmpty())    {    waitIn.sort();    }    }  }/** * Called when <tt>waitForAccess(thread)</tt> (where <tt>thread</tt> is * the associated thread) is invoked on the specified priority queue. * The associated thread is therefore waiting for access to the * resource guarded by <tt>waitQueue</tt>. This method is only called * if the associated thread cannot immediately obtain access. * * @paramwaitQueuethe queue that the associated thread is *now waiting on. * * @seenachos.threads.ThreadQueue#waitForAccess */public void waitForAccess(PriorityQueue waitQueue) {thread.timeAddedToWaitQ = Machine.timer().getTime();waitQueue.add(thread);this.waitIn=waitQueue;//System.out.println("Waiting Thread = " + thread.getName());if(waitQueue.transferPriority)computeDonations(thread);}/** * Called when the associated thread has acquired access to whatever is * guarded by <tt>waitQueue</tt>. This can occur either as a result of * <tt>acquire(thread)</tt> being invoked on <tt>waitQueue</tt> (where * <tt>thread</tt> is the associated thread), or as a result of * <tt>nextThread()</tt> being invoked on <tt>waitQueue</tt>. * * @seenachos.threads.ThreadQueue#acquire * @seenachos.threads.ThreadQueue#nextThread */public void acquire(PriorityQueue waitQueue) {waitQueue.lockOwner=this.thread;//System.out.println("Got Access: " + thread.getName());}public void computeDonations(KThread t) {ThreadState ts=getThreadState(t);//current thread state we're looking atLinkedList<ThreadState> seenStates = new LinkedList<ThreadState>();while(!seenStates.contains(ts)){seenStates.add(ts);ThreadState lo = ts;if(ts.thread.joiningThread != null) //do join donation{lo = getThreadState(ts.thread.joiningThread);//lock ownerif(lo == ts) break;else if (ts.getEffectivePriority() > lo.getEffectivePriority()){lo.priority = ts.getEffectivePriority();if (lo.waitIn!=null)lo.waitIn.sort();}}else if(ts.waitIn != null && ts.waitIn.transferPriority && ts.waitIn.lockOwner != null){ //wait queue donationlo = getThreadState(ts.waitIn.lockOwner);//lock ownerif(lo == ts) break;else if (ts.getEffectivePriority() > lo.getEffectivePriority()){lo.donatedPriority = ts.getEffectivePriority();if (lo.waitIn!=null)lo.waitIn.sort();}}ts = lo;}}/** The thread with which this object is associated. */   protected KThread thread;/** The priority of the associated thread. */protected int priority;public PriorityQueue waitIn;public int donatedPriority=0;    }}

0 0