82 lines
2.3 KiB
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>();
|
|
}
|
|
|