31
Tema 4.- RCC, Monitores y Recursos ü 4.1.- Introducción ü 4.2.- Regiones Críticas y Regiones Críticas Condicionales ü 4.3.- Monitores ü 4.4.- Recursos

Ejemplos Para Tener en Cuenta

Embed Size (px)

Citation preview

Page 1: Ejemplos Para Tener en Cuenta

Tema 4.- RCC, Monitores y Recursos

ü 4.1.- Introducción

ü 4.2.- Regiones Críticas y Regiones CríticasCondicionales

ü 4.3.- Monitores

ü 4.4.- Recursos

Page 2: Ejemplos Para Tener en Cuenta

Introducción

1SemáforosØ No estructurados. El uso depende del programador

Ø No están relacionados con el recurso que protegen

Ø No especifica las operaciones que se deben hacer conel recurso.

1ProblemasØ Facilidad de error por parte del programador

Ø Dificultad para descubrir el objetivo del semáforopor la ausencia de significado semántico

Ø Posibilidad de uso incorrecto del recurso por parte delos procesos

1Otros Constructores para concurrencia:Para solucionar, en la medida de lo posible, estos problemas.

Ø Regiones Críticas (RC) y

Regiones Críticas Condicionales (RCC)

Ø Monitores

Ø Recursos o unidades protegidas

Page 3: Ejemplos Para Tener en Cuenta

Región Crítica (I)

1Definición (Brinch Hansen, 1972)Ø Una RC es un constructor que resuelve el problema

de Exclusión Mutua estableciendo un mecanismo deacceso a estos recursos.

Ø Cada recurso debe ser definido como compartido (shared).

Ø Existirá una región para cada recurso.

Ø No está permitido el acceso al recurso fuera de la región.

Ø Cada región tiene asociada una cola de procesos.

NOTA: No implementado en PASCAL FC

1DeclaraciónVAR <var-compartida> : SHARED <tipo> ;

1ConstructorREGION <var-compartida> DO

<Sección_crítica> ;

Page 4: Ejemplos Para Tener en Cuenta

Región Crítica (II)

1Ejemplo: Dos procesos que acceden a una sección crítica

PROGRAM RegionCritica;

VAR v : SHARED INTEGER;

PROCESS P1;

...

REGION v DO

<Sección_crítica> ;

...

END;

PROCESS P2;

...

REGION v DO

<Sección_crítica> ;

...

END;

1MejorasØ Estructura el acceso a la sección crítica

Ø Establece significado al constructor

1ProblemasØ Sincronización

Page 5: Ejemplos Para Tener en Cuenta

Regiones Críticas Condicionales (I)

1Sincronización con RC...

REPEAT

REGION v DO

BEGIN

ok := (v > 0) ;

IF ok THEN

v := v - 1;

END;

UNTIL ok;

...

Problema: Espera activa por lo tanto no es una buena solución

1Regiones Crítica Condicionales (RCC)Ø La misma idea que las RC

Ø Establecen una guarda (condición) a satisfacer para accedera la Región

Ø La región tiene asociada una cola con la guarda.

1ConstructorREGION <var-compartida> WHEN <guarda> DO

<Sección_crítica> ;

Page 6: Ejemplos Para Tener en Cuenta

Regiones Críticas Condicionales (II)

1Solución a ejemplos típicos

ØProductores - Consumidores

ØFilósofos

1Ejemplo: Pasar el puenteCruzar a 20 personas, 10 mayores y 10 niños, (procesos) unpuente colgante que tiene como limitación que no permite elpaso simultaneo de más de 4 personas pequeñas o de 2pequeñas y una mayor.

Page 7: Ejemplos Para Tener en Cuenta

RCC: Problema Productor-Consumidor (III)PROGRAM ProdCons;CONST MAX=...;TYPE

TDato = ... ;TBuffer = RECORD

sigent, sigsal, cont: INTEGER;eltos: ARRAY [1..MAX] OF TDato;

END;VAR buffer : SHARED TBuffer;

PROCESS Productor;VAR pdato: TDato;BEGIN

...pdato:=producir();REGION buffer WHEN buffer.cont<MAX DO

BEGINbuffer.elto[buffer.sigent ] := pdato;buffer.sigent := (buffer.sigent MOD MAX) + 1;buffer.cont := buffer.cont + 1;

END;...

END;PROCESS Consumidor;VAR cdato: TDato;BEGIN

...REGION buffer WHEN buffer.cont<>0 DO

BEGINcdato := buffer.elto[buffer.sigsal];buffer.sigsal := (buffer.sigsal MOD MAX) + 1;buffer.cont := buffer.cont - 1;

END;...

END;BEGIN (* Principal *)

REGION buffer WHEN true DObuffer.sigent:=1; buffer.sigsal:=1; buffer.cont := 0;

END;COBEGIN

Productores; Consumidores;COEND

END.

Page 8: Ejemplos Para Tener en Cuenta

RCC: Problema Filósofos (IV)PROGRAM Filosofos;

CONST NFILO = 5;

VAR

PalillosDisp : SHARED ARRAY [1..NFILO ] OF INTEGER;

i: INTEGER;

PROCESS TYPE filosofos(n. INTEGER);

BEGIN

REPEAT

(* PENSANDO *)

REGION PalillosDisp WHEN PalillosDisp[n ]=2 DO

BEGIN

PalillosDisp[ (n MOD NFILO) + 1 ] :=

PalillosDisp [ (n MOD NFILO) + 1 ] - 1;

PalillosDisp[ ((n+NFILO-2) MOD NFILO) + 1 ] :=

PalillosDisp [ ((n+NFILO-2) MOD NFILO) + 1 ] - 1;

END;

(* COMIENDO *)

REGION PalillosDisp WHEN true DO

BEGIN

PalillosDisp[ (n MOD NFILO) + 1 ] :=

PalillosDisp [ (n MOD NFILO) + 1 ] + 1;

PalillosDisp[ ((n+NFILO-2) MOD NFILO) + 1 ] :=

PalillosDisp [ ((n+NFILO-2) MOD NFILO) + 1 ] + 1;

END;

FOREVER

END;

VAR filo: ARRAY [1..NFILO ] OF Filosofos;

BEGIN (* Principal *)

REGION PalillosDisp WHEN true DO

FOR i:= 1 TO NFILO DO

PalillosDisp := 2;

COBEGIN

FOR i:=1 To NFILO DO filo[i ](i);

COEND

END.

Page 9: Ejemplos Para Tener en Cuenta

PROGRAM PuenteColgante;VAR puente: SHARED RECORD

npp :INTEGER;npg: INTEGER;

END;i : INTEGER;

PROCESS TYPE PersonasPequeñas(i: INTEGER);BEGIN

...REGION puente WHEN (npg=0 and npp<4) or (npg=1 and npp<2) DO

npp := npp + 1;(*Pasando el Puente*)REGION puente WHEN true DO

npp := npp - 1;...

END;VAR pp: ARRAY [1..10] OF PersonasPequeñas;:PROCESS TYPE PersonasMayores;BEGIN

...REGION puente WHEN (npg=0 and npp<=2) DO

npg := npg + 1;(* Pasando el puente *)REGION puente WHEN true DO

npg := npg - 1;...

END;VAR pg: ARRAY [1..10] OF Personasmayores;BEGIN (* Principal *)

REGION puente WHEN true DOBEGIN

npp:= 0; npg:= 0END;

COBEGINFOR i:=1 TO 10 DO

BEGINpp[i] (i); pg[i](i)

END;COEND;

END.

RCC: Problema Puente Colgante (V)

Page 10: Ejemplos Para Tener en Cuenta

RC y RCC: Análisis (VI)

1SolucionanØ Establece una estructura para la exclusión mutua y

sincronización.

Ø Asigna significado semántico a la estructura

1ProblemasØ No define las operaciones a realizar sobre el recurso.

Ø La protección puede realizarse en cualquier parte delprograma.

Ø El anidamiento de RCC puede ser muy problemático

REGION x DO REGION y DO

REGION y DO REGION x DO

x := y; x := y;

Page 11: Ejemplos Para Tener en Cuenta

Monitores (I)

1DefiniciónEs constructor o entidad pasiva externa, similar a un modulo o paquete,que establece acceso exclusivo a su código, a la vez que abstracción dedatos.

Está compuesto por un conjunto de atributos privados (datos críticos) yun conjunto de procedimientos o funciones unos públicos (accesiblesdesde los procesos) y otros privados únicamente utilizables desdedentro del propio monitor.

1Sintaxis. (En la zona de declaración de un programa).

MONITOR <NombreMonitor> ;EXPORT <ListaProcedimientosPúblicos>;(* Zona de Declaración *)

CONST / TYPE / VAR / PROCEDURES / FUNCTIONS(* Cuerpo Opcional *)BEGIN

(* Cuerpo generalmente para inicializar variables *)END;

1Uso desde procesos<NombreMonitor>.<ProcedimientoPúblico> ;

Page 12: Ejemplos Para Tener en Cuenta

Monitores (II)

1FuncionamientoØ El cuerpo del monitor se ejecuta al iniciar el programa

Ø Cuando un proceso realiza una llamada a un procedimiento seejecuta ese procedimiento impidiendo que cualquier otroproceso utilice el monitor

Ø Cualquier otro proceso que desee utilizar un monitor en usopor otro proceso queda suspendido en una cola de procesos enespera propia del monitor.

Ø Cuando un proceso finaliza el uso de un monitor se analiza lacola de procesos en espera de ese monitor permitiendo elacceso a alguno que estuviese esperando.

1EjemplosMONITOR Ejemplo1;EXPORT Increm, Decrem, Valor;VAR dato;

Procedure Increm (Cant : INTEGER);BEGIN

Dato := Dato + Cant;END;

Procedure Decrem (Cant : INTEGER);BEGIN

Dato := Dato - Cant;END;

Function Valor (Cant: INTEGER): INTEGER;BEGIN

Valor := Dato;END;

BEGINDato := 0;

END;

Page 13: Ejemplos Para Tener en Cuenta

1Ejemplo.(Dos procesos incrementan en 10 una variable).

program Ejemplo;

const

nprocs =2;

var

j: integer;

monitor contador; (* se define el monitor *)

export (* define los procedimientos a exportar *)

inc, escribe;

var (* variables locales al monitor *)

X: integer;

procedure inc;

begin

X := X + 1

end; (* inc *)

procedure escribe;

begin

writeln(’X = ',X:2)

end; (* escribe *)

begin (* cuerpo del monitor *)

nolineas := 0

end; (* monitor contador *)

Monitores (III)

process type Pi;var

i: integer;begin

for i := 1 to 20 docontador.inc

end; (* Pi *)

varp: array[1..nprocs] of Pi;

begincobegin

for j := 1 to nprocs doproceso[j]

coend;contador.escribe

end.

Page 14: Ejemplos Para Tener en Cuenta

Monitores (IV)

1Sincronización con MonitoresØUso de condiciones (CONDITION)

1DefiniciónVAR <nomb_var>: Condition;

<nomb_var>: ARRAY[1..MAX of CONDITION

1OperacionesDelay(c): Bloquea al proceso que la ejecute en una colade procesos asociada a la condición c.

Resume(c): Despierta al primer proceso bloqueado en lacondición c.

Empty(c): función que devuelve TRUE se la colaasociada a c está vacía.

1Implementación de ResumeØ Última sentencia

Obligar que sea la última sentencia antes de abandonar el monitor

Ø Reactivación retardadaCuando un proceso ejecuta un resume, envía al primer proceso dela cola a una segunda cola. El proceso que ejecutó resumecontinua y al abandonar el monitor se chequea la segunda coladando paso al primer proceso bloqueado en ella.

Ø Suspensión del proceso activoCuando un proceso ejecuta un resume, éste es bloqueado en unasegunda cola interna, dejando paso al primer proceso en la colade monitor. Cuando se ejecuta una nueva operación resume o unproceso abandona el monitor se evalúa esta cola interna dandopaso al primer proceso bloqueado en ella.

Page 15: Ejemplos Para Tener en Cuenta

Monitores (V)

1Productor-ConsumidorPROGRAM PCMonitor;

MONITOR Buffer;

EXPORT Poner, Coger;

CONST MAX = 4;

VAR

Almacen: ARRAY[0..MAX] OF CHAR;

cont: INTEGER;

NoLleno, NoVacio: CONDITION;

sigent, sigsal: INTEGER;

PROCEDURE Poner(c: CHAR);

BEGIN

IF cont > MAX THEN delay(NoLleno);

Almacen[sigent] := c;

cont := cont + 1;

sigent:= (sigent+ 1) mod (MAX + 1);

resume(NoVacio)

END; (* Poner *)

PROCEDURE Coger(var c: CHAR);

BEGIN

IF cont = 0 THEN delay(NoVacio);

c := Almacen[sigsal];

cont := cont - 1;

sigsal := (sigsal + 1) mod (MAX + 1);

resume(NoLleno)

END; (* Coger *)

BEGIN (* Cuerpo*)

cont := 0;

sigent := 0;

sigsal := 0

END; (* Monitor buffer*)

PROCESS Productor;VAR

Pdato: char;BEGIN

FOR Pdato := 'a' TO 'z' DOBuffer.Poner(Pdato);

END; (* PRODUCTOR *)

PROCESS Consumidor;VAR

Cdato: char;BEGIN

REPEATBuffer.Coger(Cdato);write(Cdato)

UNTIL Cdato = 'z';writeln

END; (* CONSUMIDOR *)

BEGIN (* main *)COBEGIN

PRODUCTOR;CONSUMIDOR

COENDEND.

Page 16: Ejemplos Para Tener en Cuenta

Monitores (VI)

1FilósofosPROGRAM FilosofoMon;

CONST NF = 5;

VAR j : INTEGER;

MONITOR Palillos;

EXPORT Coger, Dejar;

VAR palillos: ARRAY[1..NF] OF INTEGER;

comer: ARRAY [1..NF] OF CONDITION;

k: INTEGER

PROCEDURE Coger(i: INTEGER);

BEGIN

IF palillos[i]<>2 THEN delay(comer[i]);

PalillosDisp[ (n MOD NF) + 1 ] := PalillosDisp [ (n MOD NF) + 1 ] - 1;

PalillosDisp[ ((n+NF-2) MOD NF) + 1 ] := PalillosDisp [ ((n+NF-2) MOD NF) + 1 ]-1

END;

PROCEDURE Dejar(i:INTEGER);

BEGIN

PalillosDisp[ (n MOD NF) + 1 ] := PalillosDisp [ (n MOD NF) + 1 ] + 1;

PalillosDisp[ ((n+NFILO-2) MOD NF) + 1 ] := PalillosDisp [ ((n+NF-2) MOD NF) + 1 ] +1;

IF palillos[(n MOD NF) + 1] = 2 THEN resume(comer[(n MOD NF) + 1]);

IF palillos[((n+NF-2) MOD NF) + 1] = 2 THEN resume(comer[((n+NF-2) MOD NF) + 1]);

END;

BEGIN

FOR k:=1 TO NF DO Palillos[k] := 2;

END;

PROCESS TYPE Filosofos(n:INTEGER);

BEGIN

(* PENSANDO *)

Palillos.Coger(i);

(* COMIENDO *)

Palillos.Dejar(i);

END;

VAR filo : ARRAY[1..NF] OF Filosofos;

BEGIN

COBEGINFOR j:=1 TO NF DO

filo[j](j);COEND

END.

Page 17: Ejemplos Para Tener en Cuenta

Monitores (VII)Lectores - Escritores

PROGRAM LEMon;

MONITOR LectEscr:

EXPORT Entrar, Salir;

VAR NLect: INTEGER; Escribiendo: BOOLEAN; Leer, Escribir: CONDITION;

PROCEDURE Entrar(Lector : BOOLEAN);

BEGIN

IF Lector THEN BEGIN

IF Escribiendo OR NOT EMPTY(Escribir) THEN delay(leer);

Nlect := Nlect + 1;

resume(leer);

END

ELSE BEGIN

IF Escribiendo OR (Nlect<>0) THEN delay(Escribir);

Escribiendo:=TRUE;

END;

END;

PROCEDURE Salir(Lector : BOOLEAN);

BEGIN

IF Lector THEN

BEGIN

Nlect:=Nlect – 1;

IF Nlect=0 THEN resume(escribir);

END

ELSE

BEGIN

Escribiendo:=FALSE;

IF NOT EMPTY(leer) THEN resume(leer)

ELSE resume(Escribir);

END;

END;

BEGIN

Escribiendo := FALSE;

NLECT:=0;

END;

PROCESS Lectores;BEGIN...

LectEsc.Entrar(TRUE);LEERLectEsc.Salir(TRUE);

.....END;

PROCESS ESCRITORES;BEGIN.....

LectEsc.Entrar(FALSE);ESCRIBIR;LectEsc.Salir(FALSE);

.....END;

Page 18: Ejemplos Para Tener en Cuenta

Monitores (VIII)

Ø Reloj – Alarma (I)

program ALARMCLOCK;const PMAX = 3;

monitor ALARM;Export WAKEUP, TICK;var NOW: integer; WAKE: condition;

procedure WAKEUP(N, ALARMCALL: integer);beginwhile NOW < ALARMCALL dobegindelay(WAKE);resume(WAKE);end

end; (* WAKEUP *)

procedure TICK;beginNOW := NOW + 1;IF NOW=24 THEN then NOW=0;resume(WAKE)

end; (* TICK *)

begin (* body *)NOW := 0

end; (* ALARM *)

monitor SCREEN;export PRINT;procedure PRINT(N: integer);beginwriteln('Process ',N:1,' aWAKEs')

end; (* PRINT *)end; (* SCREEN *)

Page 19: Ejemplos Para Tener en Cuenta

Monitores (VIII)

Ø Reloj – Alarma (II)

process Reloj;(* provides the clock "ticks" *)beginrepeatsleep(1);ALARM.TICK

foreverend; (* Reloj *)

process type CLIENTTYPE(N: integer);VAR ALARMCALL:Intenger;beginrepeatALARMCALL:=RANDOM(24);ALARM.WAKEUP(n, ALARMCALL);SCREEN.PRINT(N)

foreverend; (* CLIENTTYPE *)

varDormilones: array[1..PMAX] of CLIENTTYPE;PLOOP: integer;

begincobeginRELOJ;for PLOOP := 1 to PMAX doDORMILONES[PLOOP](PLOOP)

coendend.

Page 20: Ejemplos Para Tener en Cuenta

Monitores (IX)

Ø Simulación de Semáforos con Monitores (Implementación)

program SEMMON;

(* Simulacion de un semáforo binario con un monitor *)

var SHARED: integer;

monitor SEM;export WAIT, SIGNAL;

var VALUE: integer;NOTZERO: condition;

procedure WAIT;beginif VALUE = 0 thendelay(NOTZERO);

VALUE := 0end; (* WAIT *)

procedure SIGNAL;beginVALUE := 1;resume(NOTZERO)

end; (* SIGNAL *)

begin (* body *)VALUE := 1

end; (* SEM *)

Page 21: Ejemplos Para Tener en Cuenta

Monitores (X)

Ø Simulación de Semáforos con Monitores (Uso)

program SEMMON;(* Simulacion de un semáforo binario con un monitor *)

var SHARED: integer;

monitor SEM;.... (* Monitor anterior *)end; (* SEM *)

process type INC;var LOOP: integer;beginfor LOOP := 1 to 20 dobeginSEM.WAIT;SHARED := SHARED + 1;SEM.SIGNALend

end; (* INC *)

varINC1,INC2: INC;

beginSHARED := 0;cobeginINC1;INC2

coend;writeln('Total admitted: ',SHARED:1)

end.

Page 22: Ejemplos Para Tener en Cuenta

Monitores (XI)

1Análisis de MonitoresØ Desventajas

Ø Mecanismo de sincronización a voluntad delprogramador

Page 23: Ejemplos Para Tener en Cuenta

Recursos (I)

1Definición: Monitores + RCCØ Funde la semántica de Monitores y RCC

aprovechando las ventajas de ellas

1Sintaxis. (En la zona de declaración de un programa).

RESOURCE <NombreRecurso> ;EXPORT <ListaProcedimientosPúblicos>;(* Zona de Declaración *)

CONST / TYPE / VAR / PROCEDURES / FUNCTIONSPROCEDIMIENTOS CON GUARDAS

(* Cuerpo Opcional *)BEGIN

(* Cuerpo generalmente para inicializar variables *)END;

1Procedimientos con GuardasGUARDED PROCEDURE <nombre> WHEN <cond>;

(* Zona de Declaración Local*)

BEGIN

(* Cuerpo *)

END;

1Llamada a un procedimiento públiconom_recurso. nomb_proc(list_para);

Page 24: Ejemplos Para Tener en Cuenta

Recursos (II)

1Funcionamiento1. Un proceso que intenta entrar en un recurso que en ese momento está

ocupado, se "suspende" en la cola del recurso.

2. Un proceso que llama a un procedimiento cuya guarda se evalúa afalse se pone en estado "suspendido" en la cola de ese procedimiento.

3. Un proceso suspendido en la cola de un procedimiento pasará aejecutable cuando un proceso deje el recurso y la guarda tome elvalor de true.

4. Un proceso suspendido en la cola de un recurso pasará a ejecutablecuando un proceso deje el recurso y no haya procesos suspendidos enun procedimiento con guarda del recurso, cuya guarda toma el valorde true.

1Facilidad REQUEUELa instrucción REQUEUE se utiliza para abandonar el procedimiento conguarda actual y transferir la llamada a otro, dentro del mismo recurso odentro de otro. Su sintaxis es:

requeue [nomb_recurso.]nom_procedure(lis-para)

Page 25: Ejemplos Para Tener en Cuenta

Recursos (III)

1Productor - ConsumidorPROGRAM PCMonitor;

RESOURCE Buffer;

EXPORT

Poner, Coger;

CONST

MAX = 5;

VAR

Almacen: ARRAY[0..MAX-1] OF CHAR;

cont: INTEGER;

sigent, sigsal: INTEGER;

Guarded Procedure Poner(c: CHAR) WHEN cont<MAX;

BEGIN

Almacen[sigent] := c;

cont := cont + 1;

sigent:= (sigent+ 1) mod (MAX + 1);

END; (* Poner *)

Guarded procedure Coger(var c: CHAR) when cont <>0;

BEGIN

c := Almacen[sigsal];

cont := cont - 1;

sigsal := (sigsal + 1) mod (MAX + 1);

END; (* Coger *)

BEGIN (* Cuerpo*)

cont := 0;

sigent := 0;

sigsal := 0

END; (* Recurso buffer*)

PROCESS Productor;VAR Pdato: char;BEGIN

FOR Pdato := 'a' TO 'z' DOBuffer.Poner(Pdato);

END; (* PRODUCTOR *)

PROCESS Consumidor;VAR Cdato: char;BEGIN

REPEATBuffer.Coger(Cdato);write(Cdato)

UNTIL Cdato = 'z';writeln

END; (* CONSUMIDOR *)

BEGIN (* main *)COBEGIN

PRODUCTOR;CONSUMIDOR

COENDEND.

Page 26: Ejemplos Para Tener en Cuenta

Recursos (IV)

1 Reloj-Alarma (I)PROGRAM ALARMCLOCK;

const PMAX = 3;

resource ALARM;

export SLUMBER, TICK;

var NOW: integer;

queue : integer; freed1, freed2 : boolean;

guarded procedure SLUMBER2(AL: integer) when freed2; forward;

guarded procedure SLUMBER1(AL: integer) when freed1;

begin

if NOW < AL then requeue SLUMBER2(AL)

end; (* SLUMBER *)

guarded procedure SLUMBER2;

begin

if NOW < AL then

requeue SLUMBER1(AL)

end; (* SLUMBER *)

guarded procedure SLUMBER(ALARMACALL: integer) when true;

begin

if NOW < ALARMCALL then

if queue = 1 then requeue SLUMBER1(ALARMCALL)

else requeue SLUMBER2(ALARMCALL)

end; (* SLUMBER *)

procedure TICK;

begin

NOW := NOW + 1;

if queue = 1 then

begin

queue := 2; freed1 := true; freed2 := false

end else

begin

queue := 1; freed1 := false; freed2 := true

end

end; (* TICK *)

Page 27: Ejemplos Para Tener en Cuenta

Recursos (V)

1 Reloj-Alarma (II)begin (* body *)

NOW := 0;

queue := 1;

freed1 := false

end; (* ALARM *)

resource SCREEN;

export

PRINT;

procedure PRINT(N: integer);

begin

writeln('Process ',N:1,' awakes')

end; (* PRINT *)

end; (* SCREEN *)

process DRIVER;

begin

repeat

sleep(1);

ALARM.TICK

forever

end; (* DRIVER *)

process type SLEEPERTYPE(N: integer);

VAR llamar:INTEGER;

begin

repeat

alarma=ramdon(24);

ALARM.SLUMBER(alarma);

SCREEN.PRINT(N)

(* get up and go to work *)

forever

end; (* SLEEPERTYPE *)

varSLEEPERS: array[1..PMAX] of

SLEEPERTYPE;PLOOP: integer;

begincobeginDRIVER;for PLOOP := 1 to PMAX doSLEEPERS[PLOOP](PLOOP)

coendend.

Page 28: Ejemplos Para Tener en Cuenta

Recursos (VI)

Ø Filósofos (I)

program philres1;(* Dining Philosophers - resource version *)var j, num: integer;

resource forkcontrol;export getforks, putforks;var forks: array [0..4] of integer;i: integer; barrier1: boolean;

guarded procedure waiting1(i: integer) when not barrier1; forward;guarded procedure waiting2(i: integer) when barrier1; forward;

guarded procedure getforks(i: integer) when true;beginif forks[i] <> 2 then

if barrier1 then requeue waiting1(i)else requeue waiting2(i);

forks[(i+1) mod 5] := forks[(i+1) mod 5] - 1;forks[(i+4) mod 5] := forks[(i+4) mod 5] - 1;writeln('Philosopher ',i,' eats')end; (* getforks *)

procedure putforks(i: integer);beginwriteln('Philosopher ',i,' finishes');forks[(i+1) mod 5] := forks[(i+1) mod 5] + 1;forks[(i+4) mod 5] := forks[(i+4) mod 5] + 1;barrier1 := not barrier1end; (* putforks *)

Page 29: Ejemplos Para Tener en Cuenta

Recursos (VII)

Ø Filósofos (II)

(continuación)

guarded procedure waiting1;beginrequeue getforks(i)

end;

guarded procedure waiting2;beginrequeue getforks(i)

end;

begin (* resource body *)barrier1 := true;for i := 0 to 4 doforks[i] := 2

end; (* forkcontrol *)

process type philtype(n: integer);

beginrepeatsleep(random(5)); (* THINKING *)forkcontrol.getforks(n);sleep(random(5)); (* EATING *)forkcontrol.putforks(n)

foreverend; (* philosopher *)

varphilosopher: array[0..4] of philtype;

begin (* main *)cobeginfor num := 0 to 4 dophilosopher[num](num)

coendend.

Page 30: Ejemplos Para Tener en Cuenta

Recursos (VIII)

Ø Simulación de un Semáforo binario

resource BINSEM;

export

WAIT, SIGNAL;

var

VALUE: integer;

guarded procedure WAIT when VALUE > 0;

begin

VALUE := VALUE - 1

end; (* WAIT *)

procedure SIGNAL;

begin

VALUE := VALUE + 1

end; (* SIGNAL *)

begin (* body *)

VALUE := 1

end; (* BINSEM *)

Page 31: Ejemplos Para Tener en Cuenta

Recursos (IX)

Ø Uso del Semáforo binario anterior

program SEMRES;(* simulation of binary semaphore by resources *)

var COUNT: integer;

resource BINSEM;.... (* Recurso anterior *)end; (* BINSEM *)

process type INC;var I: integer;beginfor I := 1 to 20 dobeginBINSEM.WAIT;COUNT := COUNT + 1;BINSEM.SIGNALend

end; (* INC *)

var TURNSTILE1, TURNSTILE2: INC;

beginCOUNT := 0;cobeginTURNSTILE1;TURNSTILE2

coend;writeln('Final total; ',COUNT:1)

end.