package nachos.threads;
import nachos.machine.*;
/**
* An implementation of condition variables that disables interrupt()s for
* synchronization.
*
* <p>
* You must implement this.
*
* @see nachos.threads.Condition
*/
public class Condition2 {
/**
* Allocate a new condition variable.
*
* @param conditionLock the lock associated with this condition
* variable. The current thread must hold this
* lock whenever it uses <tt>sleep()</tt>,
* <tt>wake()</tt>, or <tt>wakeAll()</tt>.
*/
public Condition2(Lock conditionLock) {
this.conditionLock = conditionLock;
this.waitingThreads = ThreadedKernel.scheduler.newThreadQueue(true);
}
/**
* Atomically release the associated lock and go to sleep on this condition
* variable until another thread wakes it using <tt>wake()</tt>. The
* current thread must hold the associated lock. The thread will
* automatically reacquire the lock before <tt>sleep()</tt> returns.
*/
public void sleep() {
boolean intStatus = Machine.interrupt().disable();
/* If the current thread doesn't hold the lock, then abort */
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
// Add thread to waitingThreads
waitingThreads.waitForAccess(KThread.currentThread());
// Release lock
conditionLock.release();
// Go to sleep
KThread.sleep();
// Get lock upon awakening
conditionLock.acquire();
Machine.interrupt().restore(intStatus);
}
/**
* Wake up at most one thread sleeping on this condition variable. The
* current thread must hold the associated lock.
*/
public void wake() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
boolean intStatus = Machine.interrupt().disable();
KThread thread = waitingThreads.nextThread();
if(thread != null) {
thread.ready();
}
Machine.interrupt().restore(intStatus);
}
/**
* Wake up all threads sleeping on this condition variable. The current
* thread must hold the associated lock.
*/
public void wakeAll() {
Lib.assertTrue(conditionLock.isHeldByCurrentThread());
boolean intStatus = Machine.interrupt().disable();
/* Wake all threads that are waiting on the condition variable */
KThread thread = null;
do {
thread = waitingThreads.nextThread();
if(thread != null) {
thread.ready();
}
} while(thread != null);
Machine.interrupt().restore(intStatus);
}
/**
* Tests whether this module is working.
*/
public static void selfTest() {
Condition2Test.runTest();
}
private static final char dbgCondition = 'c';
/** Lock associated with this condition variable */
private Lock conditionLock;
/** Threads waiting for this condition to be signaled */
private ThreadQueue waitingThreads = null;
}