2014-10-13 3 views
0

Я пытаюсь реализовать 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(); 
    } 
+2

Я думаю, что у вас могут возникнуть проблемы с прерываниями, которые прерываются в ожидании. Возможно, вы захотите вернуть прерывания после добавления ожидающего потока в очередь. – Greyson

+0

Я думаю, что реализация мьютекса неверна. Поток, который блокирует мьютекс, должен разблокировать мьютекс, который не относится к семафору. – bjskishore123

+0

@ Greyson .. или, иначе говоря, отключение прерываний - это полная катастрофа для любого превентивного многозадачного. sleep() будет работать только при таком условии, если интервал настолько короткий, что компилятор вставляет цикл опроса на высокочастотный таймер (или эквивалент) вместо изменения состояния потока на [ничего, что не работает]. –

ответ

0

Проблема была в том, что я не передавал блокировку следующему потоку, ожидающему очереди. Это не имеет никакого отношения к статусу прерывания. Правильная разблокировка(), показанная ниже ...

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(); 
    } 
Смежные вопросы