package nachos.ag; import nachos.machine.Machine; import nachos.threads.KThread; import nachos.threads.Lock; import nachos.threads.PriorityScheduler; import nachos.threads.ThreadedKernel; /** * A grader for testing priority donation. * * @author Xiangru Chen * */ public class DonationGrader extends BasicTestGrader { @Override public void run () { assertTrue(ThreadedKernel.scheduler.getClass().getSimpleName().equals( "PriorityScheduler"), "This grader needs priority scheduler."); testLock(); testJoin(); done(); } private void testLock () { lock = new Lock(); lock.acquire(); boolean insStatus = Machine.interrupt().disable(); ThreadedKernel.scheduler.setPriority(lowPriority); forkNewThread(new Runnable() { @Override public void run () { lock.acquire(); lock.release(); } }, highPriority); forkNewThread(new Runnable() { @Override public void run () { alwaysYield(); assertTrue(false, "Maybe error in your priority donation."); } }, midPriority); Machine.interrupt().restore(insStatus); alwaysYield(); lock.release(); } private void testJoin () { boolean insStatus = Machine.interrupt().disable(); ThreadedKernel.scheduler.setPriority(highPriority); ThreadHandler low = forkNewThread(new Runnable() { @Override public void run () { alwaysYield(); } }, lowPriority); forkNewThread(new Runnable() { @Override public void run () { alwaysYield(); assertTrue(false, "Maybe error in your priority donation."); } }, midPriority); Machine.interrupt().restore(insStatus); low.thread.join(); } private void alwaysYield () { for (int i = 0; i < 10000; ++i) { KThread.yield(); } } private Lock lock = null; public static final int highPriority = PriorityScheduler.priorityMaximum; public static final int midPriority = PriorityScheduler.priorityMaximum - 1; public static final int lowPriority = PriorityScheduler.priorityMaximum - 2; }