if S.счетчик < 0 then WAIT(S); {Вставить обратившийся процесс в список по S.указатель и установить на процессор готовый к выполнению процесс }
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ;
End;
Procedure V (var S : Semaphore):
Begin
ЗАПРЕТИТЬ ПРЕРЫВАНИЯ;
S.счетчик:= S.счетчик+1;
if S.счетчик <= 0 then RELEASE (S); {Деблокировать первый процесс из списка по S.указатель}
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ;
End;
Procedure InitSem (var S : Semaphore);
Begin
S.счетчик:=1;
S.указатель:=nil;
End;
Реализация семафоров в мультипроцессорных системах более сложна, чем в однопроцессорных. Одновременный доступ к семафору S двух процессов, выполняющихся на однопроцессорной вычислительной системе, предотвращается запретом прерываний. Однако этот механизм не подходит для мультипроцессорных систем, так как он не препятствует двум или более процессам одновременно обращаться к одному семафору. В силу того, что такой доступ должен реализовываться как критический интервал, необходимо дополнительное аппаратное взаимное исключение доступа для различных процессоров. Одним из решений является использование уже знакомых нам неделимых команд типа «ПРОВЕРКА И УСТАНОВКА» (TS). Двухкомпонентный семафор в этом случае расширяется включением третьего компонента – логического признака ВзаимоИскл (листинг 6.10).
Листинг 6.10. Реализация Р- и V-операций для мультипроцессорной системы
type
Semaphore = record
счетчик : integer:
указатель : pointer;
взаимоискл : boolean;
end;
var
S : Semaphore;
Procedure InitSem (var S : Semaphore);
Begin
With S do
Begin
счетчик:=1;
указатель:=nil;
взаимоискл:=true;
End;
End;
Procedure P (var S : Semaphore):
Var
разрешено : boolean;
Begin
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
repeat
TS(разрешено, S.взаимоискл)
Until разрешено;
S.счетчик:=S.счетчик-1;
if S.счетчик < 0 then WAIT(S): {Вставить обратившийся процесс в список по s.указатель и установить на cpu готовый процесс}
S.взаимоискл:= true;
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ
End;
Procedure V (var S : Semaphore );
Var
разрешено : boolean;
Begin
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
Repeat
TS(разрешено, S.взаимоискл)
until разрешено;
S.счетчик:=S. счетчик + l;
if S.счетчик <= 0 then RELEASE(S); {Деблокировать первый процесс из списка по S.указатель}
S.взаимоискл:=true:
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ;
End;
Обратите внимание, что в данном тексте команда типа «проверка и установка» – ТS(разрешено, S.взаимоискл) – работает не с целочисленными, а с булевыми значениями. Практически это ничего не меняет, ибо текст программы и ее машинная (двоичная) реализация – это все-таки разные вещи.