Я пытаюсь реализовать Mutex WITHOUT busy-waiting. В принципе, если поток хочет блокировку, он проверяет, заблокирован ли Mutex, если да, поставьте поток в режим сна и добавьте его в очередь FIFO. Когда поток, удерживающий блокировку, переходит к разблокировке Mutex, он проверяет, ждут ли какие-либо потоки, чтобы получить доступ к критическому региону, если это так, удалите поток из очереди и добавьте его в «готовую» очередь, которая управляет порядок использования нитей.Невозможно реализовать Mutex правильно
Я не могу заставить Mutex работать, но семафор под ним отлично работает. Есть идеи? Благодарю.
// 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: Проблема в том, что я не передавал блокировку следующей очереди, ожидающей очереди. Это не имеет никакого отношения к статусу прерывания. Правильная разблокировка(), показанная ниже ...
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();
}
Я думаю, что у вас могут возникнуть проблемы с прерываниями, которые прерываются в ожидании. Возможно, вы захотите вернуть прерывания после добавления ожидающего потока в очередь. – Greyson
Я думаю, что реализация мьютекса неверна. Поток, который блокирует мьютекс, должен разблокировать мьютекс, который не относится к семафору. – bjskishore123
@ Greyson .. или, иначе говоря, отключение прерываний - это полная катастрофа для любого превентивного многозадачного. sleep() будет работать только при таком условии, если интервал настолько короткий, что компилятор вставляет цикл опроса на высокочастотный таймер (или эквивалент) вместо изменения состояния потока на [ничего, что не работает]. –