package nachos.ag;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import nachos.machine.Lib;
import nachos.machine.Machine;
import nachos.threads.KThread;
import nachos.threads.PriorityScheduler;
import nachos.threads.ThreadedKernel;
/**
* A naive grader for priority scheduling.
*
* @author Xiangru Chen
*/
public class PriorityGrader extends BasicTestGrader
{
Set<ThreadHandler> ready;
Set<ThreadHandler> handlers;
Map<ThreadHandler, Long> timeMap;
@Override
public void run ()
{
assertTrue(ThreadedKernel.scheduler instanceof PriorityScheduler,
"This test need PriorityScheduler.");
final long threads = getIntegerArgument("threads");
final long times = getIntegerArgument("times");
final long length = getIntegerArgument("length");
assertTrue(threads > 0, "invalid argument: number of threads");
assertTrue(times > 0, "invalid argument: times of test");
for (int i = 0; i < times; ++i)
{
ready = new HashSet<ThreadHandler>();
handlers = new HashSet<ThreadHandler>();
timeMap = new HashMap<ThreadHandler, Long>();
boolean intStatus = Machine.interrupt().disable();
for (int j = 0; j < threads; ++j)
{
ThreadHandler handler = forkNewThread(new Runnable()
{
@Override
public void run ()
{
for (int i = 0; i < length; ++i)
KThread.yield();
}
});
handler.thread.setName("testThread" + j);
int p = Lib.random(PriorityScheduler.priorityMaximum);
ThreadedKernel.scheduler.setPriority(handler.thread, p);
// System.out.println(handler.thread.getName() + " " + p);
handlers.add(handler);
}
Machine.interrupt().restore(intStatus);
for (ThreadHandler handler : handlers)
{
handler.thread.join();
}
ready.clear();
handlers.clear();
timeMap.clear();
}
done();
}
@Override
public void readyThread (KThread thread)
{
super.readyThread(thread);
if (ready != null)
{
ThreadHandler handler = getThreadHandler(thread);
ready.add(handler);
timeMap.put(handler, Machine.timer().getTime());
}
}
@Override
public void runningThread (KThread thread)
{
if (ready != null)
{
assertTrue(ready.contains(getThreadHandler(thread)), thread.getName()
+ " is not in the ready queue");
}
super.runningThread(thread);
if (ready != null)
{
ThreadHandler handler = getThreadHandler(thread);
ready.remove(handler);
int ep = ThreadedKernel.scheduler.getEffectivePriority(handler.thread);
long time = timeMap.get(handler);
for (ThreadHandler other : ready)
{
int oep = ThreadedKernel.scheduler.getEffectivePriority(other.thread);
long otime = timeMap.get(other);
assertTrue(ep >= oep, "Wrong scheduling! There is another thread ("
+ other.thread.getName() + ") with higher priority than "
+ handler.thread.getName() + " in the ready queue");
if (ep == oep)
{
assertTrue(time <= otime,
"Wrong scheduling! There is another thread ("
+ other.thread.getName() + ") has equal priority as "
+ handler.thread.getName() + " but came earlier.");
}
}
}
}
}