Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
29 de Enero de 2001
Pregunta 1 (1.5 p): Explicar, en un modelo de comunicacin por memoria compartida, cual es el
problema que puede suceder al acceder varias tareas ejecutndose concurrentemente a una variable
compartida y porque. Exponer que solucin nos proporciona Ada 95 y como funciona.
Solucin
Supongamos dos tareas que comparten la variable X, y que ambos quieren realizar una operacin sobre
Xx En muchos computadores esto no se realiza como una operacin atmica, sino que supone un
conjunto de operaciones a nivel de procesador, normalmente:
?? Cargar el valor de la variable X en un registro
?? Incrementar/decrementar el valor del registro
?? Almacenar el valor resultante en la variable X
Dado que estas operaciones no se puede garantizar que se ejecuten indivisiblemente el resultado puede ser
incorrecto. Veamos una posible secuencia donde dos tareas acceden a la variable X, P1 para incrementar
en 1 su valor y P2 para decrementarla tambin en 1. La lgica nos dice que fuera cual fuera el orden en
que se ejecutaran las instrucciones ( primero X:=X+1 y despues X:=X-1, o al contrario), el valor final de
X debera ser el mismo. Veamos una posible ejecucin.
Tiempo
Tarea
Operacin
Registro 1
Registro 2
Variable X
T1
5
T2
P1
Mov X,reg1
5
5
T3
P1
Inc reg1
6
5
T4
P2
Mov X,reg2
6
5
5
T5
P2
Dec reg2
6
4
5
T6
P1
Mov reg1,X
6
4
6
T7
P2
Mov reg2,X
6
4
4 ERROR!
Podemos ver que el resultado no es el esperado. Tal como nos dicta la lgica el resultado de la ejecucin
paralela (concurrente) de estas instrucciones debe ser el mismo en todos los casos.
La solucin aportada en Ada son los tipos protegidos
Un tipo protegido de Ada encapsula unos datos, proporcionando un acceso a los mismos mediante
subprogramas (function o procedure) y mediante entradas (entry) protegidos. El lenguaje garantiza que
dichos subprogramas y entradas se ejecutaran de forma que la informacin es actualizada en modo
excluyente. Condiciones de sincronizacin pueden obtenerse mediante el uso de guardas boolenas en las
entradas, las cuales debern ser verdaderas para poder ejecutar el cdigo asociado a la misma.
Un tipo protegido tiene una parte de especificacin y una implementacin
Pregunta 2 (1.0 p): Implementar una tarea peridica de periodo 500 milisegundos y con un plazo limite
del bucle de 250 de milisegundos. Incluir las llamadas necesarias a los paquetes que proporcionan el reloj
adecuado.
Solucin
with Ada.Real_Time;
use Ada.Real_Time;
task body Limitada is
Plazo : constant Time_Span := Milliseconds (250);
Periodo : constant Time_Span := Milliseconds (500);
Siguiente:Time;
Vez
:
Integer
:= 0;
Ok
:
Boolean;
begin
Main:
Siguiente:=clock;
loop
Vez:=Vez+1;
select
delay until (siguiente+plazo);
then
abort
Ok:=Cuenta(Vez);
end select;
siguiente:=siguiente+periodo;
delay until siguiente;
end loop Main;
end Limitada;
INTEGER; Tg:
INTEGER;pid:
INTEGER;pid:
INTEGER;pid:
begin
barniz(1).INICIALIZAR;
barniz(2).INICIALIZAR;
secad.INICIALIZAR;
cocid(1).INICIALIZAR;
cocid(2).INICIALIZAR;
pant.tomar;
entrada.abrir;
end trabajo;
Solucin 1.
task body GENERADOR is
i: INTEGER:=0;
P:PIEZA;
begin
entrada.entrar;
loop
i := i + 1;
delay duration(Tg);
P.numero:=i;
P.tipo:=gid;
P.tiempo_generacion:=clock;
P.Tiempo_salida:=clock;
barniz(gid).ANYADIR(P,Tp);
end loop
end generador;
task body BARN_SECA is
P:PIEZA;
begin
entrada.entrar;
loop
barniz(gid).NO_vacia;
delay until barniz(gid).VER_TIEMPO;
barniz(gid).SACAR(P);
secad.ANYADIR(P,tp);
secad.ESTADO_ALMACEN;
end loop;
end BARN_SECA;
task body SECA_COCI is
P:PIEZA;
begin
NATURAL;tp: NATURAL);
INTEGER;tp: NATURAL);
INTEGER;tp: NATURAL);
INTEGER);
entrada.entrar;
loop
secad.NO_vacia;
if secad.TIPO(gid) then
delay until secad.VER_TIEMPO;
secad.SACAR(P);
cocid(gid).ANYADIR(P,tp);
else
delay 1.0;
end if;
end loop;
end SECA_COCI;
task body CONSUMIDOR is
P:PIEZA;
Tiempo,T_max,T_min,T:duration;
Tm:float;
begin
entrada.entrar;
tiempo:=duration(0);
t_max:=duration(0);
t_min:=duration(100);
loop
cocid(gid).NO_VACIA;
delay until cocid(gid).VER_TIEMPO;
cocid(gid).sacar(P);
T:=clock-P.tiempo_generacion;
Tiempo:=Tiempo+T;
Tm:=float(Tiempo)/float(P.numero);
if T>t_max then t_max:=T;end if;
if T<t_min then t_min:=T;end if;
pant.tomar;
end loop;
end CONSUMIDOR;
Solucin 2.
task body GENERADOR is
i: INTEGER:=0;
P:PIEZA;
begin
entrada.entrar;
loop
i := i + 1;
delay duration(Tg);
P.numero:=i;
P.tipo:=gid;
P.tiempo_generacion:=clock;
P.Tiempo_salida:=clock;
barniz(gid).ANYADIR(P,Tp);
pant.tomar;
pos1.Row := 8*gid; pos1.column := 5;Goto_XY(pos1.column,pos1.row);
gnat.io.put("ANYADO: ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
barniz(gid).ESTADO_ALMACEN;
pant.dejar;
end loop;
end generador;
task body BARN_SECA is
P:PIEZA;
T:time;
begin
entrada.entrar;
loop
barniz(gid).NO_vacia;
delay until barniz(gid).VER_TIEMPO;
barniz(gid).SACAR(P);
T:=clock;
secad.ANYADIR(P,tp);
pant.tomar;
pos1.row:= 1;pos1.column:= 1;Goto_XY(pos1.column,pos1.row);
if T<barniz(gid).VER_TIEMPO+duration(1.0) then
gnat.io.put("Pieza ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
gnat.io.put(" Barnizado correcto. ");
else pos1.row:=2;Goto_XY(pos1.column,pos1.row);
gnat.io.put("Pieza ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
gnat.io.put(" Barnizado defectuoso.");
end if;
pos1.Row := 12; pos1.column := 35;Goto_XY(pos1.column,pos1.row);
gnat.io.put(P.tipo);gnat.io.put("-");gnat.io.put(P.numero);
secad.ESTADO_ALMACEN;
pant.dejar;
end loop;
end BARN_SECA;
task body SECA_COCI is
P:PIEZA;
T:time;
begin
entrada.entrar;
loop
secad.NO_vacia;
if secad.TIPO(gid) then
delay until secad.VER_TIEMPO;
secad.SACAR(P);
T:=clock;
cocid(gid).ANYADIR(P,tp);
pant.tomar;
pos1.row:= 3;pos1.column:= 30;Goto_XY(pos1.column,pos1.row);
if T<secad.VER_TIEMPO+duration(2.0) then
gnat.io.put("Pieza ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
gnat.io.put(" Secado correcto. ");
else pos1.row:=4;Goto_XY(pos1.column,pos1.row);
gnat.io.put("Pieza ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
gnat.io.put(" Secado defectuoso.");
end if;
pos1.Row := 8*gid; pos1.column :=
55;Goto_XY(pos1.column,pos1.row);
gnat.io.put(P.tipo);gnat.io.put("-");gnat.io.put(P.numero);
cocid(gid).ESTADO_ALMACEN;gnat.io.put(":CONSUMO");
pant.dejar;
else
delay 1.0;
end if;
end loop;
end SECA_COCI;
task body CONSUMIDOR is
P:PIEZA;
Tiempo,T_max,T_min,T:duration;
Tm:float;
TT:time;
begin
entrada.entrar;
tiempo:=duration(0);
t_max:=duration(0);
t_min:=duration(100);
loop
cocid(gid).NO_VACIA;
delay until cocid(gid).VER_TIEMPO;
cocid(gid).sacar(P);
TT:=clock;
T:=TT-P.tiempo_generacion;
Tiempo:=Tiempo+T;
Tm:=float(Tiempo)/float(P.numero);
if T>t_max then t_max:=T;end if;
if T<t_min then t_min:=T;end if;
pant.tomar;
pos1.row:=1;pos1.column:= 50;Goto_XY(pos1.column,pos1.row);
if TT<cocid(gid).VER_TIEMPO+duration(3.0) then
gnat.io.put("Pieza ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
gnat.io.put(" Cocido correcto. ");
else pos1.row:=2;Goto_XY(pos1.column,pos1.row);
gnat.io.put("Pieza ");gnat.io.put(P.tipo);gnat.io.put("");gnat.io.put(P.numero);
gnat.io.put(" Cocido defectuoso.");
end if;
pos1.row:=20;pos1.column:=5+38*(gid-1);Goto_XY(pos1.column,pos1.row);
gnat.io.put("Tiempo medio :");put(Tm,5,5,0);gnat.io.put(" segundos");
pos1.row:=21;pos1.column:=5+38*(gid-1);Goto_XY(pos1.column,pos1.row);
gnat.io.put("Tiempo maximo:");put(float(T_max),5,5,0);
gnat.io.put(" segundos");
pos1.row:=22;pos1.column:=5+38*(gid-1);Goto_XY(pos1.column,pos1.row);
gnat.io.put("Tiempo minimo:");put(float(T_min),5,5,0);
gnat.io.put(" segundos");
pant.dejar;
end loop;
end CONSUMIDOR;
Pregunta 5 (1.5 p): dado el siguiente conjunto de tareas definidas como T ? (C i , Pi , Di ) (cmputo,
periodo, deadline), determinar sin son planificables con el criterio de asignacin de prioridades Rate
Monotonic (Monotnico en frecuencia).
T1=(1,4,4); T2=(2,6,6); T3=(3,10,10);
?? Con el test de utilizacin de la CPU. Nota: U(3)=0.77
U=1/4+2/6+3/10=0.8>(3) . No planificable.
?? En caso de que el test anterior de un sistema no planificable, aplicar el test de tiempos de
finalizacin.
?? Supongamos que los datos varan en de la siguiente forma: T1=(1,4,2); T2=(2,6,3); T3=(3,10,4). Es
valido el anlisis anterior o se debera realizar ms clculos? No. Solo comparar el instante de
finalizacin con el plazo limite Por qu? Porque la ordenacin de prioridades se mantiene Cumplen
las tareas con sus restricciones temporales? No falla la tercera
Pregunta 6 (3.0 p): Sea un ro con un transbordador que lleva coches de la orilla norte a la sur y
viceversa. Puede llevar como mximo 10 coches en cada viaje. Se busca implementar una tarea en Ada
que mediante comunicacin por cita provea el servicio de transbordador comentado a las tareas coche que
realizan las siguientes llamadas sucesivas cada vez que desean pasar el ro:
iterar
Transbordador.Subir(orilla,aceptacion);--subir al transbordador
Sino se acepta esperar 4 segundos
Hasta aceptacin:
Transbordador.Bajar;--bajar cuando se llega a la orilla
Implementar el cdigo de la tarea transbordador y de las tareas coche que cumpla las siguientes
posibilidades:
?? El transbordador realiza un viaje cuando ha dejado subir a 10 coches en la orilla en la que se
encuentra
?? El transbordador realiza un viaje cuando ha recogido 10 coches o ha esperado ms de 10 segundos
en la orilla (pero no se permite hacer el viaje de vaco).
with Gnat.Io;
use Gnat.Io;
procedure Principal is
task Transbordador is
entry Pasar_Puente (
Direccion : in
Integer;
Arriba
:
out Boolean );
entry Bajar;
end Transbordador;
task body Transbordador is
Direc_Trans : Integer := 0;
Coches
: Integer := 0;
salir:boolean;
begin
loop
loop
salir:=false;
select
when (Coches<11)=>
accept Pasar_Puente (
Direccion :
Integer;
Arriba
:
out Boolean ) do
Arriba:=True;
if (Direccion=Direc_Trans) and Arriba then
Coches:=Coches+1;
end if;
Arriba:=False;
end Pasar_Puente;
or delay 10.0;
salir:=true;
end select;
exit when (Coches=10) or (salir and coches>0);
end loop;
loop
accept Bajar do
Coches:=Coches-1;
end Bajar;
exit when Coches=0;
end loop;
if Direc_Trans=1 then
Direc_Trans:=0;
else
Direc_Trans:=1;
end if;
end loop;
end Transbordador;
task type Coche (Dir_Coche:Integer);
task body Coche is
Aceptado : Boolean := False;
direccion:integer;
begin
direccion:=dir_coche;
loop
loop
Transbordador.Pasar_Puente(Direccion,Aceptado);