228________ Глава 7. Организация параллельных взаимодействующих вычислений
Листинг 7.9(продолжение)
end; var S :Semaphore;
procedure P ( var S : Semaphore); begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; Б.счетчик:= Б.счетчик-].: if S.счетчик < 0 then
WAIT(S); { вставить обратившийся процесс в список по S.указатель и передать
на процессор готовый к выполнению процесс } РАЗРЕШИТЬ_ПРЕРЫВАНИЯ end;
procedure V ( var S : Semaphore): begin ЗАПРЕТИТЬ ПРЕРЫВАНИЯ;
З.счетчик::= S.счетчик+1;
if S.счетчик <= 0 then RELEASE (S); { деблокировать первый процесс из списка по S.указатель }
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ end:
procedure InitSem (var S ; Semaphore): begin
5.счетчик:=1;
5.указатель:=nil: end;
Реализация семафоров в мультипроцессорных системах сложнее, чем в однопроцессорных. Одновременный доступ к семафору S двух процессов, выполняющихся на однопроцессорной вычислительной системе, предотвращается запретом прерываний. Однако этот механизм не подходит для мультипроцессорных систем, так как он не препятствует двум или более процессам одновременно обращаться к одному семафору. В силу того что такой доступ должен реализовываться через критическую секцию, необходимо дополнительное аппаратное взаимное исключение доступа для различных процессоров. Одним из решений является использование уже знакомых нам неделимых команд проверки и установки (TS). Двухкомпонент-ный семафор в этом случае расширяется включением третьего компонента — логического признака взаимоискл (листинг 7.10).
Листинг 7.10.Реализация операций Р и V для мультипроцессорной системы
type Semaphore = record
счетчик : integer;
указатель : pointer;
взаимоискл : boolean: end; var S : Semaphore;
procedure InitSem (var S : Semaphore): begin With S do begin
Средства синхронизации и связи взаимодействующих процессов_______________ 229
procedure Р ( var S : Semaphore): var разрешено : boolean: begin
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
repeat ТS(разрешено, S.взаимоискл) until разрешено:
S.счетчик:=S.счетчик-1:
if S.счетчик < 0 then WAIT(S): { вставить обратившийся процесс в список по S.указатель
и передать на процессор готовый к выполнению процесс }
S.взаимоискл:=true;
РАЗРЕШИТЬ_ПРЕРЫВАНИЯ end:
procedure V ( var S : Semaphore ):
var разрешено : boolean:
begin
ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;
repeat ТS(разрешено.S.взаимоискл) until разрешено:
5.Счетчик:=5.Счетчик+1;
if S.счетчик <= 0 then RELEASE(S): { деблокировать первый процесс из списка
по S.указатель }
S. взаимоискл:=true:
РАЗРЕШИТЬ__ПРЕРЫВАНИЯ: end:
Обратите внимание, что в данном тексте команда проверки и установки — TS(pa3-решено,S.взаимоискл) — работает не с целочисленными, а с булевыми значениями. Практически это ничего не меняет, ибо текст программы и ее машинная (двоичная) реализация — это разные вещи.