Elaboró: Dr. Luis Gerardo de la Fraga Sistemas Operativos Mayo-Agosto 2015 9/06/2015 down() -> sleep() up() -> wakeup() typedef int semaforo down( semaforo s ) { if ( s > 0 ) s--; else lista_procesos[s] = sleep( ); } up( semaforo s ) { if( s > 0 ) s++; else { if( hay_procesos_dormidos( s ) ) { * se selecciona un proceso, tal vez al azar, FIFO, o por prioridad de lista_procesos[s] * se despierta el proceso dormido y se completa su down() } } } -------------------------------------------------------------- semaforo s0=1; proceso1( s0 ) proceso2( s0 ) { { down( s0 ); down( s0 ); region_critica(); region_critica(); up( s0 ); up( s0 ); } } Uso de un semáforo binario para garantizar la exclusión mutua. -------------------------------------------------------------- Otro uso de los semáforos es para sincronizar #define N 10 int buffer[N]; int cuenta_cosas; semaforo vacio=0; productor( ) { if ( cuenta_cosas == 1 ) { up( vacio ); } } consumidor( ) { // Tenemos que proteger que el consumidor // use una cosa si no la hay if( cuenta_cosas == 0 ) { down( vacio ); } } Aquí garantizamos que con el semáforo se haga o no se haga algo (eso es sincronizar). --------------------------------------------------------------- 10/06/2015 El problema de productores y consumidores con mutexes #define N 20 int buffer[N]; int celdas=20; // El número inicial de cedas vacias mutex vacio; mutex lleno; mutex s; // Hay que inicializarlos productor( ) { if ( celdas == N-1 ) unlock( vacio ); lock( s ); // Región crítica celda--; buffer[N-celda] = N-celda; unlock( s ); // hay que hacer algo con la cosa que se obtuvo if( celdas == 0 ) lock( lleno ); } consumidor( ) { // Checamos si las celdas están llenas. Si lo está bloqueamos al consumidor if( celdas == 1 ) unlock( lleno ); lock( s ); // Región crítica celda++; // Incrementa una celda vacía buffer[N-celda] = 0; unlock( s ); // Tenemos que proteger que el consumidor // use una cosa si no la hay if( celdas == N ) lock( vacio ); }