- Tomar una foto a los pasos 4 y 5 como se muestra en el ejemplo
- Ponerlas en formato pdf
- Enviarlas al correo electronico: sistemas.operativos.fime@gmail.com
- Asunto: HORA - Tarea 4 - Matricula - Nombre
- Entregarla antes del jueves 23 de mayo
1.- Implementar Locks en NachOS
Bueno lo primero que tenemos que hacer es abrir nuestra terminal y ir a nuestra carpeta de threads
cd nachos/nachos/code/threads
Bueno para la implementación de los Locks editaremos los archivos synch.cc y synch.h.
sudo gedit synch.h
Buscamos la linea 89 y depues de donde dice:
private:
const char* name; // para depuraci�n
Agregaremos Semaphore semaforo;
private:
const char* name; // para depuraci�n
Semaphore semaforo;
Ahora editaremos el synch.cc
sudo gedit synch.ccAl principio agregamos:
#include <iostream>
Buscamos donde viene Locks debe verse algo asi
// Dummy functions -- so we can compile our later assignments
// Note -- without a correct implementation of Condition::Wait(),
// the test case in the network assignment won't work!
Lock::Lock(const char* debugName) {}
Lock::~Lock() {}
void Lock::Acquire() {}
void Lock::Release() {}
Una vez que implementamos los Locks deberia verse asi:
Lock::Lock(const char* debugName)
:name(debugName), semaforo("semaforo_lock", 1) //constructor
{
printf("lock constructor\n");
}
Lock::~Lock()
{
printf("lock destructor \n");//destructor
}
void Lock::Acquire() {
semaforo.P();
printf("acquiring lock\n"); //debugging purposes
}
void Lock::Release() {
semaforo.V();
printf("releasing lock\n"); //debugging purposes
}

2.- Crear un programa que corra Locks
Bueno para esto abriremos el archivo threadtest.cc.
sudo gedit threadtest.ccLo primero que tenemos que agregar son las librerias nuevas
#include "synch.h" //agregado para ejecutar los locks #include <iostream> using namespace std; #include <ctime> #include <cstdlib>
Ahora antes de:
void
SimpleThread(void* name)
{
// Reinterpret arg "name" as a string
char* threadName = (char*)name;
// If the lines dealing with interrupts are commented,
// the code will behave incorrectly, because
// printf execution may cause race conditions.
for (int num = 0; num < 10; num++) {
//IntStatus oldLevel = interrupt->SetLevel(IntOff);
printf("*** thread %s looped %d times\n", threadName, num);
//interrupt->SetLevel(oldLevel);
//currentThread->Yield();
}
//IntStatus oldLevel = interrupt->SetLevel(IntOff);
printf(">>> Thread %s has finished\n", threadName);
//interrupt->SetLevel(oldLevel);
}
Agregaremos los Siguientes codigos:
Codigo del Productor Consumidor
//apuntador a un lock compartido en todo el codigo
Lock *l;
Lock *l2; //lock usado para crear un deadlock
Lock *l3; //lock usado para crear un deadlock
Lock *consumidor; //usado para bloquear a los consumidores
Lock *productor; //usado para bloquear a los productores
Lock *modificarComestibles; //exclusion mutua entre productores y consumidores
int comestibles;
int maxComestibles;
//se ejecuta la rutina para los consumidores
void
Consumidor(void *name){
char* threadName = (char*)name;
bool tieneLock = false;
while(1){
if(!tieneLock){
consumidor->Acquire();
tieneLock = true;
}
cout <<"comestibles: "<<comestibles << "\n";
if(comestibles > 0){ //podemos consumir productos
//parte critica del codigo que se comparte entre todos los threads
//sean productores o consumidores
modificarComestibles->Acquire();
comestibles --;
modificarComestibles->Release();
cout<<threadName<<" consumio\n";
consumidor->Release();
tieneLock = false;
}else{
cout <<threadName <<" no puede consumir \n";
}
currentThread->Yield();
}
}
//se ejecuta la rutina para los productores
void
Productor(void* name){
char* threadName = (char*)name;
//cout <<"\nrutina del productor\n";
bool tieneLock = false;
while(1){
if(!tieneLock){
productor->Acquire();
tieneLock = true;
}
cout <<"comestibles: "<<comestibles << "\n";
if(comestibles < maxComestibles){ //podemos producir
//parte critica del codigo que se comparte entre todos los threads
//sean productores o consumidores
modificarComestibles -> Acquire();
comestibles ++;
modificarComestibles -> Release();
cout<<threadName<<" produjo\n";
productor->Release();
tieneLock = false;
}else{
cout <<threadName <<" no puede producir \n";
}
currentThread->Yield();
}
}
Prueba Fairness.
void
PruebaFairness(void* name){
//parseando de tipo void a tipo char
char* threadName = (char*)name;
cout << "ejecutando Fairness para thread "<< threadName << "\n";
int repeticiones = 3;
while(repeticiones >= 0 ){
cout << threadName <<" quiere el lock\n";
l->Acquire();
cout << threadName <<" tiene el lock\n";
l->Release();
repeticiones--;
currentThread->Yield(); //despierta el primer thread en la cola
// currentThread->Sleep();//manda el thread al final de la cola
}
}
Prueba Liveness.void
PruebaLiveness(void* name){
char* threadName = (char*)name;
srand(time(0));
float probabilidad;
float pasa = 0.5;
int a;
int repeticiones = 0;
while(repeticiones < 3){
probabilidad = (float)rand()/RAND_MAX ;
if (probabilidad > pasa){
cout << threadName << " pide el lock\n";
l->Acquire();
cout << threadName << " tiene el lock\n";
for (int i = 0; i< 10000; i++){
a++;
}
for (int i = 0; i< 10000; i++){
a--;
}
l->Release();
cout << threadName << " libera el lock\n";
//cout << probabilidad<<endl;
}
currentThread->Yield();
repeticiones++;
}
}
Prueba Safety (con esta aremos un deadlock).
void
DeadLock1(void* name){
char* threadName = (char*)name;
cout <<"\n"<<threadName <<" funciona de la siguiente manera\n";
cout <<"l2 Acquire()\n";
cout <<"l3 Acquire()\n";
cout <<"realiza operaciones criticas \n";
cout <<"l3 release()\n";
cout <<"l2 release()\n";
currentThread->Yield();
l2->Acquire();
cout <<"\n"<<threadName<<" Adquiere l2\n";
cout <<threadName<<" es interrumpido\n";
currentThread->Yield();
l3->Acquire();
cout<<"esta parte nunca va a pasar\n";
l3->Release();
l2->Release();
}
void
DeadLock2(void* name){
char* threadName = (char*)name;
cout <<"\n"<<threadName <<" funciona de la siguiente manera\n";
cout <<"l3 Acquire()\n";
cout <<"l2 Acquire()\n";
cout <<"realiza operaciones criticas \n";
cout <<"l2 release()\n";
cout <<"l3 release()\n";
currentThread->Yield();
l3->Acquire();
cout <<"\n"<<threadName<<" Adquiere l3\n";
cout <<threadName<<" es interrumpido\n";
currentThread->Yield();
l2->Acquire();
cout<<"esta parte nunca va a pasar\n";
l2->Release();
l3->Release();
}
Despues de Agregarlos buscamos el que dice ThreadTest() y en este agregaremos /* y */ para que no ejecute el SimpleTest(), debe quedar como en la siguiente imagen.
Despues del */ y antes de } agregamos el siguiente codigo:
int n = 10;
int p = 3; //cuantos productores
int c = 2;// cuantos consumidores
l = new Lock("lock1");
l2 = new Lock("lock2");
l3 = new Lock("lock3");
modificarComestibles = new Lock("comestibles");//bloquea productores y consumidores
consumidor = new Lock("consumidor");//bloquea consumidores
productor = new Lock("productor");//bloquea productores
comestibles = 0; //cero comestibles
maxComestibles = 10; //maximo de productos que podemos tener en cola
cout << "*------------->Ejecutando prueba para Fairness<-------------*\n";
for ( int k=1; k<=n; k++) {
char* threadname = new char[100];
sprintf(threadname, "Hilo %d", k);
Thread* newThread = new Thread (threadname);
newThread->Fork (PruebaFairness, (void*)threadname);
}
PruebaFairness( (void*)"Hilo 0");
//se realiza la prueba de livenes "si varios threads piden un lock
//al mismo tiempo al menos uno lo debe de obtener"
cout << "\n*------------->Ejecutando prueba para Liveness<-------------*\n";
for ( int k=1; k<=n; k++) {
char* threadname = new char[100];
sprintf(threadname, "Hilo %d", k);
Thread* newThread = new Thread (threadname);
newThread->Fork (PruebaLiveness, (void*)threadname);
}
PruebaLiveness((void*)"Hilo 0");
// Productor((void*)"Productor0");
/*
cout << "\n*------------->Ejecutando prueba para Safety<-------------*\n";
for ( int k=1; k<=1; k++) {
char* threadname = new char[100];
sprintf(threadname, "Hilo %d", k);
Thread* newThread = new Thread (threadname);
newThread->Fork (DeadLock2, (void*)threadname);
}
DeadLock1((void*)"Hilo 0");
*/
cout <<"\n*------------->Ejecutando el programa del productor consumidor<-------------*\n";
cout << "\ncreando productores\n";
for ( int k=1; k<=p; k++) {
char* threadname = new char[100];
sprintf(threadname, "Productor %d", k);
Thread* newThread = new Thread (threadname);
newThread->Fork (Productor, (void*)threadname);
}
cout << "\ncreando consumidores\n";
for ( int k=2; k<=c; k++) {
char* threadname = new char[100];
sprintf(threadname, "Consumidor %d", k);
Thread* newThread = new Thread (threadname);
newThread->Fork (Consumidor, (void*)threadname);
}
Consumidor((void*)"Consumidor 1");
3.- Compilar
Bueno aqui tecleamos en la terminal lo siguiente:
cd ..
Y ahora si le damos make.
make4.- Primera prueba correr nachOS.
Suponiedo que no marco algun error volvemos a la carpeta de threads y para correrlo le tecleamos:
cd threads
y lo corremos
./nachos
Esta prueba deberia correr PruebaFairness, PruebaLiveness y el Consumidor - Productor. La ejecución deberia verse de la siguiente manera:
5.- Causar un DeadLock.
Para matar el proceseso presionamos Ctrl C, y despues abrimos el archivo threadtest.cc y borraremos el /* y */ del DeadLock como en la siguiente imagen:
Ahora lo siguiente es volver a compilar nachOS, tecleamos en la terminal lo siguiente:
Y ahora si le damos make.
Suponiedo que no marco algun error volvemos a la carpeta de threads y para correrlo le tecleamos:
Informacion y codigos de: http://sistemassoperativos.blogspot.mx/2011/09/first-practical-presentation.html
![]() |
| Imagen para la tarea. |
5.- Causar un DeadLock.
Para matar el proceseso presionamos Ctrl C, y despues abrimos el archivo threadtest.cc y borraremos el /* y */ del DeadLock como en la siguiente imagen:
Ahora lo siguiente es volver a compilar nachOS, tecleamos en la terminal lo siguiente:
cd ..
Y ahora si le damos make.
make
Suponiedo que no marco algun error volvemos a la carpeta de threads y para correrlo le tecleamos:
cd threadsy lo corremos
./nachosUna vez que corremos nachOS deberia verse algo asi:
![]() | |
|
Informacion y codigos de: http://sistemassoperativos.blogspot.mx/2011/09/first-practical-presentation.html





No comments:
Post a Comment