package nachos.threads;

import nachos.machine.*;

/**
 * Uses the hardware timer to provide preemption, and to allow threads to sleep
 * until a certain time.
 */
public class Alarm {
    /**
     * Allocate a new Alarm. Set the machine's timer interrupt handler to this
     * alarm's callback.
     *
     * <p>
     * <b>Note</b>: Nachos will not function correctly with more than one alarm.
     */
    public Alarm() {
        Machine.timer().setInterruptHandler(new Runnable() {
            public void run() {
                timerInterrupt();
            }
        });
    }

    /**
     * The timer interrupt handler. This is called by the machine's timer
     * periodically (approximately every 500 clock ticks). Causes the current
     * thread to yield, forcing a context switch if there is another thread that
     * should be run.
     */
    public void timerInterrupt() {
        KThread.currentThread().yield();
    }

    /**
     * Put the current thread to sleep for at least <i>x</i> ticks, waking it up
     * in the timer interrupt handler. The thread must be woken up (placed in
     * the scheduler ready set) during the first timer interrupt where
     *
     * <p>
     * <blockquote> (current time) >= (WaitUntil called time)+(x) </blockquote>
     *
     * @param x
     *            the minimum number of clock ticks to wait.
     *
     * @see nachos.machine.Timer#getTime()
     */
    public void waitUntil(long x) {
        // for now, cheat just to get something working (busy waiting is bad)
        long wakeTime = Machine.timer().getTime() + x;
        while (wakeTime > Machine.timer().getTime())
            KThread.yield();
    }
}

@@ -45,16 +45,79 @@
 hine.*;%0D
+%0Aimport java.util.PriorityQueue;%0D%0Aimport java.util.Comparator;%0D
 %0A%0D%0A/**%0D%0A
@@ -246,24 +246,800 @@
 ss Alarm %7B%0D%0A
+    private static class KThreadWaitingPair %7B%0D%0A        KThreadWaitingPair(KThread thread, long finishTime) %7B%0D%0A            this.thread = thread;%0D%0A            this.finishTime = finishTime;%0D%0A        %7D%0D%0A%0D%0A        KThread getThread() %7B%0D%0A            return thread;%0D%0A        %7D%0D%0A%0D%0A        long getFinishTime() %7B%0D%0A            return finishTime;%0D%0A        %7D%0D%0A%0D%0A        private KThread thread;%0D%0A        private long finishTime;%0D%0A    %7D%0D%0A%0D%0A    private static class KThreadWaitingPairComparator implements Comparator%3CKThreadWaitingPair%3E %7B%0D%0A        @Override%0D%0A        public int compare(KThreadWaitingPair x, KThreadWaitingPair y) %7B%0D%0A            long delta = x.getFinishTime() - y.getFinishTime();%0D%0A            %0D%0A            return delta == 0 ? 0 : (delta %3E 0 ? 1 : -1);%0D%0A        %7D%0D%0A    %7D%0D%0A%0D%0A
     /**%0D%0A   
@@ -1750,24 +1750,533 @@
 errupt() %7B%0D%0A
+        boolean intStatus = Machine.interrupt().disable();%0D%0A%0D%0A        long currentTime = Machine.timer().getTime();%0D%0A        while (true) %7B%0D%0A            KThreadWaitingPair top = waitQueue.peek();%0D%0A            if (top != null) %7B%0D%0A                if (top.getFinishTime() %3C= currentTime) %7B%0D%0A                    waitQueue.poll().getThread().ready();                    %0D%0A                %7D%0D%0A            %7D else %7B%0D%0A                break;%0D%0A            %7D%0D%0A        %7D%0D%0A%0D%0A        Machine.interrupt().restore(intStatus);%0D%0A
         KThr
@@ -2989,90 +2989,468 @@
     
-while (wakeTime %3E Machine.timer().getTime())%0D%0A            KThread.yield();%0D%0A    %7D
+KThreadWaitingPair pair = new KThreadWaitingPair(KThread.currentThread(), wakeTime);%0D%0A    %0D%0A        boolean intStatus = Machine.interrupt().disable();%0D%0A%0D%0A        waitQueue.add(pair);%0D%0A        KThread.sleep();%0D%0A%0D%0A        Machine.interrupt().restore(intStatus);%0D%0A    %7D%0D%0A%0D%0A    KThreadWaitingPairComparator pqComparator = new KThreadWaitingPairComparator();%0D%0A    PriorityQueue%3CKThreadWaitingPair%3E waitQueue = new PriorityQueue%3CKThreadWaitingPair%3E(pqComparator);
 %0D%0A%7D%0D%0A
+%0D%0A

fin. alarm, call for test