80 lines
2.0 KiB
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);
|
|
}
|