Examen final de Ampliación de sistemas operativos, Fila A

Anuncio
Examen final de Ampliación de sistemas operativos, Fila A.
Febrero de 2009
Tercer curso de Ingeniería técnica de informática de sistemas
Tiempo total: 2 horas.
Problema: Cuarto de baño unisex
En una conocida discoteca de Móstoles hay un cuarto de baño unisex, es decir al que pueden acceder hombres y mujeres, aunque en este caso no simultáneamente. Se nos pide diseñar el programa que controlará el
acceso a este cuarto de baño. Este programa ejecutará en un dispositivo con dos botones. Un botón será utilizado por las mujeres para pedir la entrada al baño. El otro por los hombres. Al apretar el botón se
imprimirá un papel con el número de turno. Cuando su número aparezca en la puerta general del baño, los
hombres y mujeres, que a partir de ahora denominaremos usuarios podrán entrar.
Simule los usuarios como procesos concurrentes que compartan memoria y que pueden estar fuera del
baño, esperando, haciendo uso de él o fuera satisfechos.
Debe controlar que solo accedan al baño usuarios de un solo género y que como mucho entren 5
simultáneamente que es la capacidad del baño. Dicho de otra forma, sólo pueden entrar al baño hombres o
mujeres pero no hombres y mujeres simultáneamente y como mucho puede haber 5 usarios a la vez en el
baño.
El programa debe ser justo, es decir, no puede existir hambruna.
Utilice para crear los procesos la librería de thread(2) y semáforos nativos del sistema Plan 9.
NOTA: Tanto este problema como el problema de la cafetera/tetera son en realidad el mismo problema. Por tanto, estas soluciones (se incluyen dos) también son soluciones para el problema de la
cafetera/tetera.
-2-
Solución
Esta solución es más compacta, pero puede ser más difícil de entender:
__________
toiletsem.c 

#include <u.h>
#include <libc.h>
#include <thread.h>
// 8c -FVw toiletsem.c && 8l -o toiletsem toiletsem.8
// kill toiletsem|rc
enum{
Stacksize = 8*1024,
NSEATS = 5,
Masc= 0,
Fem,
Maxgen,
Nogender,
};
long turn = 1;
long serial[Maxgen] = {
1,
1,
};
long seat = NSEATS;
long door = 1;
int npeople;
long nticmutex = 1;
int nticket;
void
user(void *g)
{
int nt, gender;
gender = (int)g;
semacquire(&turn, 1);
semrelease(&turn, 1);
semacquire(&nticmutex, 1);
nt = nticket++;
semrelease(&nticmutex, 1);
//I could use turn, but this is cleaner
print("your ticket number is %d\n", nt);
-3-
semacquire(&serial[gender], 1);
if(npeople++ == 0){
semacquire(&turn, 1);
semacquire(&door, 1);
semrelease(&turn, 1);
}
semrelease(&serial[gender], 1);
semacquire(&seat, 1);
print(" %d of gender %d has entered and is doing things\n", nt, gender);
sleep(100);
semrelease(&seat, 1);
semacquire(&serial[gender], 1);
if(--npeople == 0)
semrelease(&door, 1);
print(" %d of gender %d left\n", nt, gender);
semrelease(&serial[gender], 1);
}
void
threadmain(int, char *[])
{
int g, i;
srand(2); //no realmente aleatorio, repetible
for(i = 0; i < 100; i++){
g = nrand(Maxgen);
print("A user of gender %d pressed a button\n", g);
proccreate(user, (void *)g, Stacksize);
}
threadexits(nil);
}
Esta otra solución es más clásica.
___________
toiletsem2.c 

#include <u.h>
#include <libc.h>
#include <thread.h>
// 8c -FVw toiletsem2.c && 8l -o toiletsem toiletsem2.8
enum{
Stacksize = 8*1024,
NSEATS = 5,
Masc= 0,
Fem,
Maxgen,
Nogender,
};
-4-
long mutex = 1;
long seats[Maxgen];
int npeople[Maxgen];
int npeoplein;
int toiletgen = Nogender;
int nticket;
char *gennames[Maxgen] = { //para depurar
[Masc]
"Masc",
[Fem]
"Fem",
};
int
total(void)
{
int t, i;
t = 0;
for(i = 0; i<Maxgen; i++)
t += npeople[i];
return t;
}
int
other(int gen)
{
return (gen+1)%Maxgen;
}
int
max(int a, int b)
{
if( a > b)
return a;
else
return b;
}
void
user(void *g)
{
int gender, genother, mytick;
gender = (int)g;
genother = other(gender);
-5-
semacquire(&mutex, 1);
mytick = nticket++;
print("your ticket number is %d\n", mytick);
if(toiletgen == Nogender){
toiletgen = gender;
npeoplein = max(NSEATS, npeople[gender]);
semrelease(&seats[gender], npeoplein);
print("gender of the toilet is %s \n", gennames[gender]);
}
else if(toiletgen == gender && npeoplein < NSEATS){
npeoplein++;
semrelease(&seats[gender], npeoplein);
}
npeople[gender]++;
semrelease(&mutex, 1);
semacquire(&seats[gender], 1);
print("Doing my things, I am a %s, with ticket %d \n", gennames[gender], mytick);
sleep(100);
semacquire(&mutex, 1);
npeoplein--;
npeople[gender]--;
if(!npeople[genother]){
semrelease(&seats[gender], 1);
}
else if(!npeoplein && npeople[genother]){
toiletgen = genother;
npeoplein = max(NSEATS, npeople[genother]);
semrelease(&seats[genother], npeoplein);
}
else if(!npeoplein && total() == 0){
toiletgen = Nogender;
}
semrelease(&mutex, 1);
}
void
threadmain(int, char *[])
{
int g, i;
srand(2); //no realmente aleatorio, repetible
for(i = 0; i < 30; i++){
g = nrand(Maxgen);
print("A user of gender %s pressed a button\n", gennames[g]);
proccreate(user, (void *)g, Stacksize);
}
threadexits(nil);
}
Descargar