I am trying to implement a Mutex WITHOUT busy-waiting. Basically, if a thread wants the lock, it checks to see if the Mutex is already locked, if so, put the thread to sleep and add it to a FIFO queue. When the thread holding the lock goes to unlock the Mutex, it checks to see if any threads are waiting to gain access to the critical region, if so, remove the thread from the queue and add it to a 'ready' queue which controls the order of the threads being used.
I cannot get the Mutex to work, but the Semaphore below it works fine. Any ideas? Thanks.
// DOESN'T WORK
class Mutex {
Thread * thisThread;
Thread * threadWithLock;
lock() {
// disable interrupts
interrupts.disable();
// if no-one has lock, give lock to the current thread and set the lock
// else put the thread to sleep and add it to the waiting thread queue
if (lockStatus == 0) {
lock = 1
threadWithLock = thisThread;
} else {
sleepingThreads.enqueue(thisThread);
thisThread.sleep();
}
// re-enable previous interrupt status
interrupts.revert();
}
unlock() {
// disable interrupts
interrupts.disable();
// if there is a thread waiting for the lock, add it to the ready list
if (sleepingThreads.isEmpty() == false) {
Thread * t = sleepingThreads.dequeue();
t.updateStatus(READY);
threadReadyList.enqueue(t);
}
// release lock
threadWithLock = null;
lock = 0;
// re-enable previous interrupt status
interrupts.revert();
}
}
// WORKS
class Semaphore {
Thread * thisThread;
down() {
// disable interrupts
interrupts.disable();
readyCount -= 1;
if (readyCount < 0) {
sleepingThreads.enqueue(thisThread);
thisThread.sleep();
}
// re-enable previous interrupt status
interrupts.revert();
}
up () {
// disable interrupts
interrupts.disable();
readyCount += + 1;
if (readyCount <= 0) {
Thread * t = null;
t = sleepingThreads.dequeue();
t.updateStatus(READY);
threadReadyList.enqueue(t);
}
// re-enable previous interrupt status
interrupts.revert();
}
}
EDIT: The problem was that I was not handing the lock over to the next thread waiting in the queue. It had nothing to do with the interrupt status. Correct unlock() shown below...
unlock() {
// disable interrupts
interrupts.disable();
// if there is a thread waiting for the lock, add it to the ready list,
// and hand the lock over
if (sleepingThreads.isEmpty() == false) {
Thread * t = sleepingThreads.dequeue();
t.updateStatus(READY);
threadReadyList.enqueue(t);
threadWithLock = t;
} else {
//release the lock
threadWithLock = null;
lock = 0
}
// re-enable previous interrupt status
interrupts.revert();
}