package nachos.threads;
import nachos.machine.*;
import java.util.LinkedList;
import java.util.TreeSet;
import java.util.HashSet;
import java.util.Iterator;
/**
* 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.
*///优先级反转问题,通过lock和joinpublicclassPrioritySchedulerextendsScheduler {/**
* Allocate a new priority scheduler.
*/publicPriorityScheduler() {
}
/**
* 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) {
returnnew PriorityQueue(transferPriority);
}
publicintgetPriority(KThread thread) {
Lib.assertTrue(Machine.interrupt().disabled());
return getThreadState(thread).getPriority();
}
publicintgetEffectivePriority(KThread thread) {
Lib.assertTrue(Machine.interrupt().disabled());
return getThreadState(thread).getEffectivePriority();
}
publicvoidsetPriority(KThread thread, int priority) {
Lib.assertTrue(Machine.interrupt().disabled());
Lib.assertTrue(priority >= priorityMinimum &&
priority <= priorityMaximum);
getThreadState(thread).setPriority(priority);
}
publicbooleanincreasePriority() {
boolean intStatus = Machine.interrupt().disable();
KThread thread = KThread.currentThread();
int priority = getPriority(thread);
if (priority == priorityMaximum)
returnfalse;
setPriority(thread, priority+1);
Machine.interrupt().restore(intStatus);
returntrue;
}
publicbooleandecreasePriority() {
boolean intStatus = Machine.interrupt().disable();
KThread thread = KThread.currentThread();
int priority = getPriority(thread);
if (priority == priorityMinimum)
returnfalse;
setPriority(thread, priority-1);
Machine.interrupt().restore(intStatus);
returntrue;
}
/**
* The default priority for a new thread. Do not change this value.
*/publicstaticfinalint priorityDefault = 1;
/**
* The minimum priority that a thread can have. Do not change this value.
*/publicstaticfinalint priorityMinimum = 0;
/**
* The maximum priority that a thread can have. Do not change this value.
*/publicstaticfinalint 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.
*/protected 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.
*/protectedclassPriorityQueueextendsThreadQueue {public ThreadState linkthread;//linkthread代表该线程的Schedulestatepublic LinkedList<ThreadState> link;//与该队列直接相连的线程privateint index;
PriorityQueue(boolean transferPriority) {
this.transferPriority = transferPriority;
link=new LinkedList<ThreadState>();
}
publicvoidwaitForAccess(KThread thread) {
// thread在等待资源
Lib.assertTrue(Machine.interrupt().disabled());
getThreadState(thread).waitForAccess(this);
}
publicvoidacquire(KThread thread) {
// thread获得了一个资源
Lib.assertTrue(Machine.interrupt().disabled());
getThreadState(thread).acquire(this);
}
public KThread nextThread() {
// 在等待队列linkList<ThreadState> link里选择一个有效优先级最大的线程去接收该资源,并将其移除
Lib.assertTrue(Machine.interrupt().disabled());
// implement me
print();
// System.out.println("##########################");
ThreadState temp,threadstate=null;
index=0;
int max=-1;
while((temp=pickNextThread())!=null)
{
if(max<temp.getEffectivePriority())
{
max=temp.getEffectivePriority();
threadstate=temp;
}
}
if(threadstate==null)
returnnull;
elsereturn link.remove(link.indexOf(threadstate)).thread;
}
/**
* 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() {
// 返回等待队列里线程的ThreadState// implement mewhile(index<link.size())
{
index++;
return link.get(index-1);
}
returnnull;
}
publicvoidprint() {
// 打印所有的在等待队列里的线程,即等待资源的线程
Lib.assertTrue(Machine.interrupt().disabled());
// ThreadState state=null;// for(int i=0;i<link.size();i++)// {// state=link.get(i);// System.out.println(state.thread.getName()+"*****"+state.priority);// }
}
/**
* <tt>true</tt> if this queue should transfer priority from waiting
* threads to the owning thread.
*/publicboolean 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
*/protectedclassThreadState {//使用ThreadState来将thread和优先级绑定在一起/**
* Allocate a new <tt>ThreadState</tt> object and associate it with the
* specified thread.
*
* @param thread the thread this state belongs to.
*/publicThreadState(KThread thread) {
this.thread = thread;
setPriority(priorityDefault);
waitQueue=new PriorityQueue(true);//存在优先级翻转现象,创建一个优先级队列
}
/**
* Return the priority of the associated thread.
*
* @return the priority of the associated thread.
*/publicintgetPriority() {
return priority;
}
/**
* Return the effective priority of the associated thread.
*
* @return the effective priority of the associated thread.
*/publicintgetEffectivePriority() {
//获得等待队列上的所有线程的最大优先级,得到最大优先级// implement me
effctivepriority=-1;
for(int i=0;i<waitQueue.link.size();i++)
{
// 从thread1的threadstate即schedulingState的waitQueue中选取线程进行优先级逆转,只有一个thread3if(effctivepriority<waitQueue.link.get(i).getEffectivePriority())
effctivepriority=waitQueue.link.get(i).getEffectivePriority();
}//have a questionif(effctivepriority>priority)
setPriority(effctivepriority);
return priority;
}
/**
* Set the priority of the associated thread to the specified value.
*
* @param priority the new priority.
*/publicvoidsetPriority(int priority) {//优先级传递if (this.priority == priority)
return;
this.priority = priority;
// implement me
}
/**
* 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
*/publicvoidwaitForAccess(PriorityQueue waitQueue) {
// 将需要等待获得资源的线程加入一个等待队列等待调度,即将此线程的状态传入等待队列// implement me
waitQueue.link.add(this);//将线程的ThreadState加入到优先级队列中if(waitQueue.linkthread!=null&&waitQueue.linkthread!=this)
// 如果linkthread!=null说明有与waitQueue直接相连的线程,且如果该线程不是this,就要把自己也添加到后续的ThreadState的link里
waitQueue.linkthread.waitQueue.waitForAccess(thread);
// 用在得到有效优先级上/*waitQueue.linkthread.waitQueue.waitForAccess(thread);这句代码是为了在获取优先优先级的时候使用的
* waitQueue.link.add(this);只是将thread3加入到thread1的waitQueue中,但是在之后的geteffectivePriority中就无法得知在thread1上挂起
* 的线程有哪些,当然,也可以通过得到thread1的waitQueue,从而得知在thread1上挂起的线程,从而得到他们中的最大的优先级,但是过去麻烦
* 可以在ThreadState中声明一个waitQueue,用它来保存挂在thread1上的线程,这样在得到优先优先级时,会比较方便
* 每个等待队列创建时都会注册一个线程作为linkthread,一旦有一个线程挂在waitQueue等待队列上,那么这个线程一定要挂在linkthread的waitQueue上,
* 这样在在发生优先级逆转的时候,可以通过thread1的schedulingState的waitQueue得到在thread1上挂起的线程
*/
}
/**
* 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
*/publicvoidacquire(PriorityQueue waitQueue) {
//队列中的线程共同持有的一个锁,即每一个waitQueue队里都会有一个锁,同时后面的waitforaccess方法会使线程挂在linkthread的waitQueue上// implement me
Lib.assertTrue(waitQueue.link.isEmpty());
waitQueue.linkthread=this;
}
/** The thread with which this object is associated. */protected KThread thread;
/** The priority of the associated thread. */protectedint priority;
protectedint effctivepriority;
protected PriorityQueue waitQueue;//等待该线程thread的线程队列,thread可以得到waitQueue上的最大优先级
}
}