nachos priority scheduler with nonation

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.
     *
     * @param	transferPriority	<tt>true</tt> if this queue should
     *					transfer priority from waiting threads
     *					to the owning thread.
     * @return	a 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.
     *
     * @param	thread	the thread whose scheduling state to return.
     * @return	the 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.
	 *
	 * @return	the 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.
     *
     * @see	nachos.threads.KThread#schedulingState
     */
    protected class ThreadState {
	/**
	 * Allocate a new <tt>ThreadState</tt> object and associate it with the
	 * specified thread.
	 *
	 * @param	thread	the thread this state belongs to.
	 */
	public ThreadState(KThread thread) {
	    this.thread = thread;
	    
	    setPriority(priorityDefault);
	}

	/**
	 * Return the priority of the associated thread.
	 *
	 * @return	the priority of the associated thread.
	 */
	public int getPriority() {
		
	    return priority;
	}

	/**
	 * Return the effective priority of the associated thread.
	 *
	 * @return	the 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.
	 *
	 * @param	priority	the 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.
	 *
	 * @param	waitQueue	the queue that the associated thread is
	 *				now waiting on.
	 *
	 * @see	nachos.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>.
	 *
	 * @see	nachos.threads.ThreadQueue#acquire
	 * @see	nachos.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 at
		LinkedList<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 owner		
				if(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 donation
				lo = getThreadState(ts.waitIn.lockOwner);//lock owner	
				if(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值