Arquitectura y Tecnología de Computadores 14 de febrero de 2014
Objetivos Aprender a utilizar las variables condición y las barreras de la biblioteca Pthreads. Diseñar e implementar una barrera: Barrera que no funciona (sólo probar) Barrera que funciona sólo una vez (sólo probar). Barrera con espera ocupada (sólo probar). Barrera sin espera ocupada. Barrera con variables condición. Barrera de Pthread. Comprobar la funcionalidad y el rendimiento de las diferentes versiones ( make all ). La nota se calculará en función de... La corrección las soluciónes: 0-5. El rendimiento de las soluciones: 0-5 (variables condición).
Makefile http://pccito.ugr.es/~gustavo/aco/practicas/practica8/makefile Makefile SRC = $( wildcard.cc) EXE = $(basename $(SRC)) CXXFLAGS = D GLIBCXX USE NANOSLEEP O3 s t d=c++0x Wal LDFLAGS = lpthread lrt default : $(EXE) all : stat @for d in $(DIR); do $(MAKE) C $$d $@; done Mediante make all podrá comparar fácilmente las soluciones que vaya programando.
Semáforos (POSIX) #include <semaphore.h> Cabecera C/C++. sem t Tipo semáforo. sem init(sem, attr, valor) Inicializa el semáforo sem al calor valor con los atributos attr. sem destroy(sem) Destruye el semáforo sem. sem wait(sem) Si el valor del semáforo sem es positivo lo decrementa y retorna inmediatamente. En otro se bloquea hasta poder hacerlo. sem trywait(sem) Versión no bloqueante de sem wait(sem). En cualquier caso retorna inmediatamente. Es necesario comprobar la salida antes de continuar. sem post(sem) Incrementa el valor del semáforo sem. En caso de cambiar a un valor positivo desbloquea a alguno de los llamadores bloqueados en sem wait(sem).
Pthreads: API de variables condición pthread cond t Tipo variable condición. Inicializable a PTHREAD COND INITIALIZER. pthread cond init(cond,attr) Inicializa la variable condición cond con los atributos attr. pthread cond destroy(cond) Destruye la variable condición cond. pthread cond wait(cond, mutex) Bloque a la hebra llamadora hasta que se señale cond. Esta función debe llamarse mientras mutex está ocupado y ella se encargará de liberarlo automáticamente mientas espera. Despué de la señal la hebra es despertada y el cerrojo es ocupado de nuevo. El programador es responsable de desocupar mutex al finalizar la sección crítica para la que se emplea. pthread cond signal(cond) Función para despertar a otra hebra que espera que se señale sobre la variable condición cond. Debe llamarse después de que mutex esté ocupado y se encarga de liberarlo en pthread cond wait(cond, mutex). pthread cond broadcast(cond) Igual que la función anterior para el caso de que queramos desbloquear a varias hebras que esperan.
Pthreads: API de barreras pthread barrier t Tipo barrera. pthread barrier init(barrier, attr, n) Inicializa la barrera barrier con los atributos attr para que funcione con n hebras. pthread barrier destroy(barrier) Destruye la barrera barrier. pthread barrier wait(barrier) Bloque a la hebra llamadora hasta que se n hebras ejecuten pthread barrier wait(barrier).
Ejemplo: barrera.cc I http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera.cc Copie el programa barrera.cc y verifique que la secuencia de ejecución no es correcta. // barrera. cc #include <unistd. h> // alarm #include <pthread. h> #include <iostream> using namespace std ; const int HEBRAS = 10; pthread mutex t display = PTHREAD MUTEX INITIALIZER; // numero de hebras // exclusion mutua display class barrera t public : barrera t (): contador (0) void esperar ()
Ejemplo: barrera.cc II http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera.cc private : int contador ; barrera ; void hebra(void ) while ( true ) pthread mutex lock(&display ); cout << pthread self () << : antes << endl ; pthread mutex unlock(&display ); barrera. esperar (); pthread mutex lock(&display ); cout << pthread self () << : despues << endl ; pthread mutex unlock(&display ); return NULL; int main()
Ejemplo: barrera.cc III http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera.cc pthread t id [HEBRAS]; alarm (1); for ( int i = 0; i < HEBRAS; ++i ) pthread create(&id [ i ], NULL, hebra, NULL); for ( int i = 0; i < HEBRAS; ++i ) pthread join ( id [ i ], NULL);
Ejemplo: barrera-una.cc I http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-una.cc Copie el programa barrera-una.cc y verifique que la secuencia de ejecución sólo es correcta la primera vez. // barrera una. cc : barrera que funciona solo una vez #include <pthread. h> #include <unistd.h> // alarm #include <iostream> using namespace std ; const int HEBRAS = 10; pthread mutex t display = PTHREAD MUTEX INITIALIZER; // numero de hebras // exclusion mutua display class barrera t public : barrera t (): contador (0)
Ejemplo: barrera-una.cc II http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-una.cc pthread mutex init(&mutex, NULL); barrera t () pthread mutex destroy(&mutex ); void esperar () pthread mutex lock(&mutex ); ++contador ; pthread mutex unlock(&mutex ); while ( contador < HEBRAS); private : int contador ; pthread mutex t mutex; barrera ; void hebra(void ) while ( true ) pthread mutex lock(&display );
Ejemplo: barrera-una.cc III http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-una.cc cout << pthread self () << : antes << endl ; pthread mutex unlock(&display ); barrera. esperar (); pthread mutex lock(&display ); cout << pthread self () << : despues << endl ; pthread mutex unlock(&display ); return NULL; int main() pthread t id [HEBRAS]; alarm (1); for ( int i = 0; i < HEBRAS; ++i ) pthread create(&id [ i ], NULL, hebra, NULL); for ( int i = 0; i < HEBRAS; ++i ) pthread join ( id [ i ], NULL);
Ejemplo: barrera-una.cc IV http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-una.cc
Ejemplo: barrera-ceo.cc I http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-ceo.cc Copie el programa barrera-ceo.cc y verifique que la secuencia de ejecución es correcta. // barrera ceo. cc : barrera con espera ocupada #include <pthread. h> #include <unistd.h> // alarm #include <iostream> using namespace std ; const int HEBRAS = 10; pthread mutex t display = PTHREAD MUTEX INITIALIZER; // numero de hebras // exclusion mutua display class barrera t public : barrera t (): uso(0)
Ejemplo: barrera-ceo.cc II http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-ceo.cc pthread mutex init(&mutex, NULL); for ( int i = 0; i < 2; ++i ) en espera [ i ] = 0; barrera t () pthread mutex destroy(&mutex ); void esperar () int uso local = uso ; pthread mutex lock(&mutex ); ++en espera [ uso local ]; pthread mutex unlock(&mutex ); if ( en espera [ uso local ] == HEBRAS) en espera [ uso local ] = 0; uso = 1 uso ; else while ( en espera [ uso local ] > 0);
Ejemplo: barrera-ceo.cc III http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-ceo.cc private : pthread mutex t mutex; volatile int en espera [2], uso ; barrera ; void hebra(void ) while ( true ) pthread mutex lock(&display ); cout << pthread self () << : antes << endl ; pthread mutex unlock(&display ); barrera. esperar (); pthread mutex lock(&display ); cout << pthread self () << : despues << endl ; pthread mutex unlock(&display ); return NULL; int main()
Ejemplo: barrera-ceo.cc IV http://pccito.ugr.es/~gustavo/aco/practicas/practica8/barrera-ceo.cc pthread t id [HEBRAS]; alarm (1); for ( int i = 0; i < HEBRAS; ++i ) pthread create(&id [ i ], NULL, hebra, NULL); for ( int i = 0; i < HEBRAS; ++i ) pthread join ( id [ i ], NULL);
Implementación de barrera-seo.cc Copie barrera-ceo.cc en barrera-seo.cc. Elimine la espera ocupada de barrera-seo.cc modificando la clase barrera t. Compare barrera-seo.cc con las soluciones anteriores.
Implementación de barrera-vc.cc Copie barrera.cc en barrera-vc.cc. Modifique la clase barrera t de barrera-vc.cc para que funcione empleando variables condición. Compare barrera-vc.cc con las soluciones anteriores.
Implementación de barrier.cc Copie barrera.cc en barrier.cc. Modifique la función hebra() para que funcione empleando las barreras de la biblioteca pthread. Compare barrier.cc con las soluciones anteriores.