p1/threads/Alarm.java

82 lines
2.3 KiB
Java

package nachos.threads;
import nachos.machine.*;
import java.util.PriorityQueue;
/**
* 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();
long curTime=Machine.timer().getTime();
while(true)
{
Condition curThread=waitQueue.peek();
if(waitQueue.peek()!=null&&waitQueue.peek().extra<=curTime)
{
waitQueue.poll();
Lock condLock=curThread.getLock();
condLock.acquire();
curThread.wakeAll();
condLock.release();
}
else break;
}
}
/**
* 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)
/* Code for busy waiting
long wakeTime=Machine.timer().getTime()+x;
while(wakeTime>Machine.timer().getTime()) KThread.yield();
*/
long wakeTime=Machine.timer().getTime()+x;
Lock condLock=new Lock();
Condition cond=new Condition(condLock,wakeTime);
condLock.acquire();
waitQueue.add(cond);
cond.sleep();
condLock.release();
}
private PriorityQueue<Condition> waitQueue=new PriorityQueue<Condition>();
}