Зачем отключать прерывание перед переключением контекста - PullRequest
0 голосов
/ 01 февраля 2020

Я читал учебник по ОС, в главе о синхронизации написано:

В частности, большинство реализаций потоковых систем применяют инвариант, что поток всегда отключает прерывания перед выполнением переключения контекста

Следовательно, при записи Aquire() перед go в спящий режим сначала отключается прерывание.

Мой вопрос: почему отключение прерывания необходимо перед переключением контекста, используется ли оно для защиты регистрирует и хранит Aquire () atomi c?

Aquire() используется перед критической секцией следующим образом:

Aquire(){
 disable interrupt;
 if (is busy){
    put on wait queue;
    sleep();
 }
 else set_busy;
 enable interrupt;
}

Go для сна будет реализовано переключение контекста, почему мы должны отключить прерывание во время переключения контекста? Можем ли мы изменить код to:

Aquire(){
 disable interrupt;
 if (is busy){
    enable interrupt;
    put on wait queue;
    sleep();
 }
 else set_busy;
 enable interrupt;
}

То есть включает прерывание в потоке A вместо того, чтобы позволить другому потоку B после переключения контекста (после A go для сна) разрешить прерывание?

1 Ответ

1 голос
/ 02 февраля 2020

Как правило, примитив синхронизации требует обновления нескольких местоположений данных одновременно . Например, для семафора Acquire может потребоваться изменить состояние текущего потока на заблокированное, обновить счетчик семафора, удалить текущий поток из очереди и поместить его в другую очередь. Поскольку одновременно невозможно (*), необходимо разработать протокол доступа для имитации этого. В системе с одним процессором самый простой способ сделать это - отключить прерывания, выполнить обновления, а затем снова включить прерывания. Все программное обеспечение, соответствующее этому протоколу, сразу увидит обновления.

В системах с несколькими процессорами обычно требуется что-то дополнительное, чтобы синхронизировать потоки на отдельных процессорах от вмешательства. Отключение прерываний недостаточно, поскольку это влияет только на текущий процессор. что-то дополнительное , как правило, является спин-блокировкой, которая во многом похожа на мьютекс или двоичный семафор, за исключением того, что вызывающая сторона находится в повторном режиме l oop до тех пор, пока она не станет доступной.

Даже в В системе с несколькими процессорами операция должна выполняться с отключенными прерываниями. Представьте, что поток № 0 получил спин-блокировку на процессоре № 0; затем прерывание на процессоре № 0 приводит к вытеснению потока № 1, а затем поток № 1 пытается получить тот же спин-блокировку. Существует множество сценариев ios, которые составляют это.

(*) Transaction-al Memory предоставляет что-то наподобие this, но с ограниченной применимостью, и реализация должна обеспечивать независимую реализацию обеспечить поступательный прогресс. Кроме того, поскольку транзакции не являются вложенными, им действительно необходимо отключать прерывания.

...