p1/threads/Lock.java

80 lines
2.0 KiB
Java

package nachos.threads;
import nachos.machine.*;
/**
* A <tt>Lock</tt> is a synchronization primitive that has two states,
* <i>busy</i> and <i>free</i>. There are only two operations allowed on a
* lock:
*
* <ul>
* <li><tt>acquire()</tt>: atomically wait until the lock is <i>free</i> and
* then set it to <i>busy</i>.
* <li><tt>release()</tt>: set the lock to be <i>free</i>, waking up one
* waiting thread if possible.
* </ul>
*
* <p>
* Also, only the thread that acquired a lock may release it. As with
* semaphores, the API does not allow you to read the lock state (because the
* value could change immediately after you read it).
*/
public class Lock {
/**
* Allocate a new lock. The lock will initially be <i>free</i>.
*/
public Lock() {
}
/**
* Atomically acquire this lock. The current thread must not already hold
* this lock.
*/
public void acquire() {
Lib.assertTrue(!isHeldByCurrentThread());
boolean intStatus = Machine.interrupt().disable();
KThread thread = KThread.currentThread();
if (lockHolder != null) {
waitQueue.waitForAccess(thread);
KThread.sleep();
}
else {
waitQueue.acquire(thread);
lockHolder = thread;
}
Lib.assertTrue(lockHolder == thread);
Machine.interrupt().restore(intStatus);
}
/**
* Atomically release this lock, allowing other threads to acquire it.
*/
public void release() {
Lib.assertTrue(isHeldByCurrentThread());
boolean intStatus = Machine.interrupt().disable();
if ((lockHolder = waitQueue.nextThread()) != null)
lockHolder.ready();
Machine.interrupt().restore(intStatus);
}
/**
* Test if the current thread holds this lock.
*
* @return true if the current thread holds this lock.
*/
public boolean isHeldByCurrentThread() {
return (lockHolder == KThread.currentThread());
}
private KThread lockHolder = null;
private ThreadQueue waitQueue =
ThreadedKernel.scheduler.newThreadQueue(true);
}