You are on page 1of 108

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Exclusi on mutua
Gustavo Romero
Arquitectura y Tecnolog a de Computadores

4 de febrero de 2013

c Gustavo Romero

Exclusi on mutua (1/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Indice

1 2 3

Introducci on Usuario Hardware Cerrojos Gesti on de interrupciones Instrucciones especiales

5 6

N ucleo Sem aforos Monitores Variables condici on Problemas Pthreads

c Gustavo Romero

Exclusi on mutua (2/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Lecturas recomendadas

J.Bacon A. Silberschatz W. Stallings A. Tanuenbaum

Operating Systems (9, 10, 11) Fundamentos de Sistemas Operativos (4, 6, 7) Sistemas Operativos (5, 6) Sistemas Operativos Modernos (2)

c Gustavo Romero

Exclusi on mutua (3/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Introducci on

c Gustavo Romero

Exclusi on mutua (4/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Secci on cr tica (1)


Cuando una hebra/proceso accede a un recurso compartido diremos que est a ejecutando una secci on cr tica. Una hebra puede tener m as de una secci on cr tica. Las secciones cr ticas puede anidarse. La ejecuci on de una secci on cr tica debe ser mutuamente excluyente:
En cualquier instante de tiempo s olo a una hebra se le permite ejecutar su secci on cr tica. Toda hebra debe pedir permiso para entrar en una secci on cr tica. Al abandonar la secci on cr tica la hebra debe asegurarse de que otra hebra que lo necesite pueda entrar avisar de que ha salido. Es necesario que toda hebra cumpla con este protocolo.

c Gustavo Romero

Exclusi on mutua (5/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Secci on cr tica (2)

Suponga que todas estas son hebras de un mismo proceso y que la hebra 1 ha conseguido entrar en la secci on cr tica roja. Qu e otros IP son v alidos al mismo tiempo?
c Gustavo Romero Exclusi on mutua (6/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Uso de secciones cr ticas (1)


C omo resolver el problema de las secciones cr ticas? Establecer un protocolo de serializaci on o exclusi on mutua. El resultado de las hebras involucradas no depender an del entrelazado no determinista de sus instrucciones. Protocolo: El c odigo que desee entrar en una secci on cr tica debe on cr tica . solicitarlo mediante entrar secci Una vez ejecutada la secci on cr tica esta debe nalizarse con salir secci on cr tica . Al resto del c odigo fuera de la secci on cr tica lo denominaremos secci on no cr tica .

c Gustavo Romero

Exclusi on mutua (7/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Uso de secciones cr ticas (2)

// patr on de comportamiento // habitual de una hebra que // ejecuta una secci on cr tica while(true) { entrar secci on_cr tica secci on_cr tica salir secci on_cr tica secci on_no_cr tica }

Cada hebra se ejecuta a una velocidad no cero pero no podemos hacer ninguna suposici on acerca de su velocidad relativa de ejecuci on. Aunque dispongamos de m as de un procesador la gesti on de memoria previene el acceso simult aneo a la misma localizaci on.

c Gustavo Romero

Exclusi on mutua (8/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Protocolo de exclusi on mutua

Ejecuci on de secciones cr ticas mediante exclusi on mutua.


c Gustavo Romero Exclusi on mutua (9/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de la exclusi on mutua 1965


Dijkstra dene el problema. Primera soluci on por Dekker. Soluci on general por Dijkstra.

196x 1974 1981 2008

Soluciones por Fischer, Knuth, Lynch, Rabin, Rivest...

Algoritmo de la panader a de Lamport.

Algoritmo de Peterson.

Cientos de soluciones publicadas. Muchos problemas relacionados.


c Gustavo Romero Exclusi on mutua (10/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Soluciones para lograr exclusi on mutua


Soluciones a nivel de usuario: Algoritmos no basados en el uso de instrucciones especiales del procesador ni de caracter sticas del n ucleo espera ocupada. Soluciones hardware: Instrucciones especiales del procesador. Soluciones a nivel del n ucleo: Bajo nivel: cerrojos y sem aforos binarios. Alto nivel: sem aforos y monitores. La soluci on adecuada depender a del modelo de procesamiento.

c Gustavo Romero

Exclusi on mutua (11/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Requisitos necesarios de una secci on cr tica (1)


1

Exclusividad:
Como m aximo una hebra puede entrar en su secci on cr tica.

Progreso:
Ninguna hebra fuera de su secci on cr tica puede impedir que otra entre en la suya.

Espera acotada (no inanici on):


El tiempo de espera ante una secci on cr tica debe ser limitado.

Portabilidad:
El funcionamiento correcto no puede basarse en...
la velocidad de ejecuci on. el n umero o tipo de los procesadores. la pol tica de planicaci on del SO.

No todos los autores dan importancia a este requisito.

c Gustavo Romero

Exclusi on mutua (12/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Requisitos necesarios de una secci on cr tica (2)

Exclusividad:
Si no se cumple la soluci on es incorrecta.

Progreso:
Los protocolos m as sencillos a veces violan este requisito.

Espera acotada (no inanici on):


La espera ocupada y las pol ticas de prioridad est aticas son t picos candidatos para violar este requisito.

Portabilidad:
Algunas soluciones dependen de...
el n umero o tipo de los procesadores. la pol tica de planicaci on del SO.

c Gustavo Romero

Exclusi on mutua (13/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Propiedades deseables de las secciones cr ticas Eciencia:


La sobrecarga de entrar y salir de la secci on cr tica deber a ser peque na en comparaci on con el trabajo u til realizado en su interior. En general suele ser buena idea evitar la espera ocupada.

Justicia:
Si varias hebras esperan para entrar en su secci on cr tica deber amos permitir que todas entrasen con parecida frecuencia.

Escalabilidad:
Debe funcionar igual de bien para cualquier n umero de hebras.

Simplicidad:
Deben ser f aciles de usar el esfuerzo de programaci on debe ser lo m as peque no posible.

c Gustavo Romero

Exclusi on mutua (14/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Usuario

c Gustavo Romero

Exclusi on mutua (15/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Soluciones a nivel usuario


La sincronizaci on se consigue a trav es de variables globales. Estas soluciones funcionan mediante espera ocupada: while(condici on != cierto); // s olo salta Simplicaci on:
Empezaremos resolviendo el problema para 2 procesos o2 hebras: H0 y H1 . Cuando hablemos de m as de dos hebras Hi y Hj denotar an a dos hebras diferentes (i = j ).

Exclusi on mutua para 2 hebras:


Algoritmos de Dekker. Algoritmo de Petterson.

Exclusi on mutua para m as de 2 hebras:


Algoritmo de la panader a (Lamport).
c Gustavo Romero Exclusi on mutua (16/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 1: exclusi on mutua mediante espera ocupada


variables compartidas int turno = 0; Hebra 0 while(true) { while (turno != 0); secci on cr tica(); turno = 1; secci on no cr tica(); } } Primera soluci on propuesta para el problema de la exclusi on mutua en secciones cr ticas. Versi on 1 del algoritmo de Dekker... hay 5!.
c Gustavo Romero Exclusi on mutua (17/108)

Hebra 1 while(true) { while (turno != 1); secci on cr tica(); turno = 0; secci on no cr tica();

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo 1: funciona? (1)


variables compartidas turno = 0; // compartida Hebra i while (true) { while (turno != i); secci on cr tica(); turno = j; secci on no cr tica(); }

Debemos inicializar la variable turno. La hebra Hi ejecuta su secci on cr tica si y s olo si turno == i. Hi se mantiene en espera ocupada mientras Hj est a en su secci on cr tica exclusividad satisfecha. El requisito de progreso no es satisfecho porque estamos suponiendo la alternancia estricta de las 2 hebras.

progreso no satisfecho soluci on no v alida


c Gustavo Romero Exclusi on mutua (18/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo 1: es correcto? (2) Supongamos SNC0 larga y SNC1 corta. Si turno == 0, H0 entrar a en su SC0 , la abandonar a haciendo turno = 1 y comenzar aa ejecutar su larga SNC0 . Ahora H1 entrar a en su SC1 , la abandona haciendo turno = 0 y ejecuta su corta SNC1 . Si de nuevo H1 intenta entrar en su SC1 , debe esperar hasta que H0 nalice su larga SNC0 y pase de nuevo por SC0 .
c Gustavo Romero Exclusi on mutua (19/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo 1


requisito exclusividad progreso espera acotada portabilidad eciencia escalabilidad cumple si no si no no no motivo debido a turno s olo una hebra entra en su secci on cr tica alternancia estricta, adem as el tama no de la secci on no cr tica afecta a la otra hebra espera igual al tiempo de ejecuci on de la otra secci on cr tica 1 procesador + prioridad est atica = circulo vicioso espera ocupada el problema se acent ua al aumentar el n umero de hebras

Analice cuidadosamente y compare su an alisis con la bibliograf a.


c Gustavo Romero Exclusi on mutua (20/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 2

Cu al es el principal problema del primer algoritmo? Almacenamos el identicador de hebra en la variable compartida usada para sincronizar y el identicador de cada hebra ha de establecerlo la otra.

Podemos hacerlo mejor? Hagamos que cada hebra sea responsable de modicar la variable compartida para permitirse el uso de la secci on cr tica. Ahora las hebras competir an por el uso de la secci on cr tica en lugar de cooperar.

c Gustavo Romero

Exclusi on mutua (21/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 2
variables compartidas bool bandera[2] = {false, false}; hebrai while (true) { while (bandera[j]); bandera[i] = true; secci on cr tica(); bandera[i] = false; secci on no cr tica(); }

Necesitamos una variable l ogica por cada hebra. Hi muestra su deseo de entrar en su secci on cr tica haciendo bandera[i] = true No satisface el requisito de exclusividad. Satisface el requisito de progreso.

c Gustavo Romero

Exclusi on mutua (22/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo 2


requisito exclusividad progreso espera acotada portabilidad eciencia escalabilidad cumple no si si no no no usa espera ocupada m as hebras requiere recodicaci on motivo condici on de carrera en el protocolo de acceso a la secci on cr tica

Analice cuidadosamente y compare su an alisis con la bibliograf a.


c Gustavo Romero Exclusi on mutua (23/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 3
variables compartidas bool bandera[2] = {false, false}; hebrai while (true) { bandera[i] = true; while (bandera[j]); secci on cr tica(); bandera[i] = false; secci on no cr tica(); }

Necesitamos una variable l ogica por cada hebra. Hi muestra su deseo de entrar en su secci on cr tica haciendo bandera[i] = true Satisface el requisito de exclusividad. Satisface el requisito de progreso.

c Gustavo Romero

Exclusi on mutua (24/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 3: es correcto? Imaginemos la siguiente secuencia de ejecuci on: H0 : bandera[0] = true; H1 : bandera[1] = true; Qu e pasar a? Ambas hebras esperar an para siempre y ninguna podr a entrar en su secci on cr tica = interbloqueo.
c Gustavo Romero Exclusi on mutua (25/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo 3


requisito exclusividad progreso espera acotada portabilidad eciencia escalabilidad cumple si si no no no no utiliza espera ocupada m as hebras requiere recodicaci on interbloqueo en el protocolo de entrada motivo

Analice cuidadosamente y compare su an alisis con la bibliograf a.


c Gustavo Romero Exclusi on mutua (26/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 4

Cu al es el principal problema del algoritmo 3? Cada hebra establece su estado sin preocuparse del estado de la otra hebra. Si las dos hebras insisten en entrar simult aneamente se produce un interbloqueo.

Podemos hacerlo mejor? Cada hebra activa su bandera indicando que desea entrar pero la desactiva si ve que la otra tambi en quiere entrar.

c Gustavo Romero

Exclusi on mutua (27/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo 4
variables compartidas bool bandera[2] = {false, false}; hebrai while (true) { bandera[i] = true; while (bandera[j]) { bandera[i] = false; // retardo bandera[i] = true; }; secci on cr tica(); bandera[i] = false; secci on no cr tica(); }
c Gustavo Romero

bandera expresa el deseo de entrar en la secci on cr tica. Hi hace bandera[i] = true pero est a dispuesta a dar marcha atr as. Satisface el requisito de exclusividad. Satisface el requisito de progreso. No satisface el requisito de espera acotada.
Exclusi on mutua (28/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo 4


requisito exclusividad progreso espera acotada portabilidad eciencia escalabilidad cumple si si no no no no utiliza espera ocupada empeora con el n umero de hebras y requiere recodicaci on motivo

Analice cuidadosamente y compare su an alisis con la bibliograf a.


c Gustavo Romero Exclusi on mutua (29/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo de Dekker
variables compartidas bool bandera[2] = {false, false}; int turno = 0; // desempate hebrai while (true) { bandera[i] = true; while (bandera[j]) { if (turno == j) { bandera[i] = false; while (turno == j); bandera[i] = true; } } secci on cr tica(); turno = j; bandera[i] = false; secci on no cr tica(); }
Exclusi on mutua (30/108)

bandera expresa la intenci on de entrar en la secci on cr tica. turno indica cu al es la hebra preferida en caso de empate. Hi hace bandera[i] = true pero est a dispuesta a dar marcha atr as con la ayuda de turno.
c Gustavo Romero

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo de Dekker (5)


requisito exclusividad progreso espera acotada portabilidad eciencia escalabilidad cumple si si si no no no utiliza espera ocupada empeora con el n umero de hebras y requiere recodicaci on motivo

Analice cuidadosamente y compare su an alisis con la bibliograf a.


c Gustavo Romero Exclusi on mutua (31/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo de Peterson
variables compartidas bool bandera[2] = {false, false}; int turno = 0; // desempate hebrai while (true) { bandera[i] = true; turno = j; while (bandera[j] && turno == j); secci on cr tica(); bandera[i] = false; secci on no cr tica(); }
c Gustavo Romero

La hebra i muestra su deseo de entrar en su secci on cr tica haciendo bandera[i] = true. Si ambas hebras intentan entrar a la vez en su secci on cr tica la variable turno decide quien va a pasar. En comparaci on con el algoritmo de Dekker es m as eciente, m as simple y extensible a m as de 2 hebras.
Exclusi on mutua (32/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Algoritmo de Peterson: es correcto?


exclusividad: H0 y H1 s olo pueden alcanzar su secci on cr tica si bandera[0] == bandera[1] == true y s olo si turno == i para cada hebra Hi , lo que es imposible. Progreso y espera acotada: Hi podr a evitar que Hj entre en su secci on cr tica s olo si est a atrapado en while (bandera[j] && turno == j);. Si Hj no est a intentando entrar en su secci on cr tica bandera[j] == false y Hi puede entrar en su secci on cr tica. Si Hj ha hecho bandera[j] == true y est a atrapado en el bucle while entonces turno == i o turno = j.

Si turno == i Hi podr a entrar en su secci on cr tica. Si turno == j Hj entrar a en su secci on cr tica y har a bandera[j] = false a la salida y permitir a a Hi entrar.
Si a Hj le da tiempo a hacer bandera[j] = true, har a turno = i. Como Hi no cambia el valor de turno mientras est a esperando en el while, Hi podr a entrar en su secci on cr tica tras como mucho una ejecuci on de la secci on cr tica de Hj .
c Gustavo Romero Exclusi on mutua (33/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

An alisis del algoritmo de Peterson


requisito exclusividad progreso espera acotada portabilidad eciencia escalabilidad cumple si si si no no si espera ocupada pero requiere recodicaci on motivo

Analice cuidadosamente y compare su an alisis con la bibliograf a.


c Gustavo Romero Exclusi on mutua (34/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de las hebras defectuosas


Si una hebra falla fuera de su secci on cr tica no afectar aa otra:
Si una soluci on cumple los 3 requisitos (exclusividad, progreso y espera acotada) entonces proporcionar a robustez frente a fallos en el exterior de la secci on cr tica.

Sin embargo, ninguna soluci on proporcionar a robustez frente a una hebra que falle en su secci on cr tica... Por qu e?
Una hebra que falle en su secci on cr tica no podr a ejecutar on cr tica() con lo que impedir aa salir de secci cualquier otra hebra entrar en su secci on cr tica porque no on cr tica(). podr an nalizar entrar en secci

Qu e puede hacerse en este caso? Deber amos hacer algo?


c Gustavo Romero Exclusi on mutua (35/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El algoritmo de la panader a de Lamport (1)


Antes de entrar en su secci on cr tica cada hebra recibe un n umero. El propietario del menor n umero entra en su secci on cr tica. En caso de que dos hebras Hi y Hj reciban el mismo n umero si i < j entonces Hi puede entrar primero. Hi pone su n umero a 0 al abandonar la secci on cr tica. Notaci on: (a, b ) < (c , d ) si (a < c ) o ((a = c ) y (b < d )). La correcci on se basa en que si Hi est a en su secci on cr tica y Hk ha escogido su n umero (= 0), entonces (numero [i ], i ) < (numero [k ], k ). variables compartidas
const int N; // n umero de hebras bool escoger[N] = {false, false,... false}; int n umero[N] = {0, 0,... 0};
c Gustavo Romero Exclusi on mutua (36/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El algoritmo de la panader a de Lamport (2)


hebrai
while (true) { escoger[i] = true; n umero[i] = max(n umero[0],...n umero[N - 1]) + 1; escoger[i] = false; for (int j = 0; j < N; ++j) { while (escoger[j]); while (n umero[j] != 0 && (n umero[j],j) < (n umero[i], i)); } secci on cr tica(); n umero[i] = 0; secci on no cr tica(); }

c Gustavo Romero

Exclusi on mutua (37/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Inconvenientes de las soluciones a nivel de usuario Las hebras intentando entrar en una secci on cr tica bloqueada se mantienen en espera ocupada = se desperdicia tiempo del procesador. Si la secci on cr tica tarda mucho tiempo en ejecutarse puede ser m as eciente bloquear a la hebra. Con un u nico procesador y una pol tica de prioridad est atica, la espera ocupada puede llevar a la inanici on.
c Gustavo Romero Exclusi on mutua (38/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Hardware

c Gustavo Romero

Exclusi on mutua (39/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Primera soluci on: un simple cerrojo (1)


Un cerrojo es un objeto en memoria principal sobre el que podemos realizar dos operaciones:
adquirir(): antes de entrar en la secci on cr tica.
Puede requerir alg un tiempo de espera a la entrada de la secci on cr tica.

liberar(): tras abandonar la secci on cr tica.


Permite a otra hebra acceder a la secci on cr tica.

Tras cada adquirir() debe haber un liberar():


Entre adquirir() y liberar() la hebra posee el cerrojo. adquirir() s olo retorna cuando el llamador se ha convertido en el due no del cerrojo... Por qu e?

Qu e podr a suceder si existieran llamadas a adquirir() sin su correspondiente liberar() emparejado? Qu e pasa si el propietario de un cerrojo trata de adquirirlo por segunda vez?
c Gustavo Romero Exclusi on mutua (40/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Usando un cerrojo (1)

retirar fondos de una cuenta bancaria while (true) { cerrojo.adquirir(); saldo = conseguir saldo(cuenta); saldo = saldo - cantidad; almacenar saldo(cuenta, saldo); cerrojo.liberar(); return saldo; }

c Gustavo Romero

Exclusi on mutua (41/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Usando un cerrojo (2)


Hebra 1 cerrojo.adquirir(); saldo = conseguir saldo(cuenta); saldo = saldo - cantidad; cerrojo.adquirir(); almacenar saldo(cuenta, saldo); cerrojo.liberar(); return saldo; saldo = conseguir saldo(cuenta); saldo = saldo - cantidad; almacenar saldo(cuenta, saldo); cerrojo.liberar(); return saldo; Hebra 2

c Gustavo Romero

Exclusi on mutua (42/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Implementaci on de un cerrojo giratorio (spinlock) (1)


class cerrojo { public: cerrojo(): cerrado(false) {} // inicialmente abierto void adquirir() { while (cerrado); // espera ocupada cerrado = true; // cerrar } void liberar() { cerrado = false; // abrir } private: volatile bool cerrado; };
1

condici on de carrera
c Gustavo Romero Exclusi on mutua (43/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Implementaci on de un cerrojo giratorio (spinlock) (2)


Problema: Las operaciones adquirir() y liberar() tienen en su interior secciones cr ticas. Estas operaciones deben ser at omicas. Aparece un dilema de dif cil soluci on: Hemos creado los cerrojos para implementar un protocolo de exclusi on mutua que resolviese el problemas de las secciones cr ticas pero la soluci on contiene otro problema de secci on cr tica. Qu e podemos hacer?
Utilizar alg un algoritmo que solucione el problema (panader a). Utilizar la arquitectura del procesador para poner n a este problema recursivo.
c Gustavo Romero Exclusi on mutua (44/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Implementaci on de operaciones at omicas El soporte hardware puede facilitar la tarea: Deshabilitar las interrupciones: cli/sti
Por qu e funciona? Por qu e puede esta acci on evitar el cambio de hebra? Funcionar a en cualquier tipo de sistema? no, v alido s olo en sistemas con un u nico procesador.

Instrucciones at omicas:
Existen instrucciones para las que el procesador y el bus garantizan su ejecuci on at omica.
TAS FAA CAS LL/SC Test And Set: lock xchg %al,( %edx) Fetch And Add: lock xadd %eax,( %edx) Compare And Swap: lock cmpxchg %ecx,( %edx) Load Linked/Store Conditional: ldrex/strex

c Gustavo Romero

Exclusi on mutua (45/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Bloqueo mediante interrupciones


Mecanismo primitivo y s olo v alido en sistemas monoprocesador. No cumple con el requisito de la portabilidad. Deshabilitar las interrupciones en un procesador no evita que en otro se ejecute la secci on cr tica. S olo en el caso de secciones cr ticas extremadamente cortas dentro del n ucleo y en sistemas monoprocesador ser a una soluci on v alida. Si no podemos atender la interrupci on del reloj no podremos cambiar de hebra tal y como hacen la mayor a de los sistemas de tiempo compartido. Protocolo: Antes de que una hebra entre en su secci on cr tica deshabilita las interrupciones (cli). Al salir de la secci on cr tica se han de volver a habilitar las interrupciones (sti).
c Gustavo Romero Exclusi on mutua (46/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Deshabilitar las interrupciones a nivel de usuario (1)


monoprocesador

hebrai
while(true) { deshabilitar interrupciones(); secci on cr tica(); habilitar interrupciones(); secci on no cr tica(); }

Se preserva la exclusi on mutua pero se degrada la eciencia del sistema: mientras est a en la secci on cr tica no se atender an interrupciones. No habr a tiempo compartido. El retraso en la atenci on de las interrupciones podr a afectar al sistema completo. Por qu e? Las aplicaciones podr an abusar o contener fallos = cuelgue del sistema.

c Gustavo Romero

Exclusi on mutua (47/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Deshabilitar las interrupciones a nivel de usuario (2)


multiprocesador

Multiprocesador: No es efectivo en absoluto porque...


Aunque las deshabilit asemos en todos los procesadores no arregla nada porque... Varios procesadores podr a acceder a la vez a un mismo recurso no garantiza la exclusi on mutua.

En resumen: Los efectos laterales son inaceptables en general. La buena noticia es que esta operaci on es privilegiada :)

c Gustavo Romero

Exclusi on mutua (48/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Deshabilitar las interrupciones a nivel del n ucleo (1)


Vamos a crear un objeto cerrojo que permita implementar el protocolo de exclusi on mutua necesario para las secciones cr ticas. Protocolo:
adquirir(): la primera hebra que ejecuta este m etodo puede continuar ejecutando su secci on cr tica. Las siguientes deben esperar a que la primera la abandone. liberar(): la hebra que abandona la secci on cr tica lo ejecuta para comunicar que queda libre y dejar pasar a otra hebra.
Exclusi on mutua (49/108)

variable compartida cerrojo_t cerrojo; hebrai while(true) { cerrojo.adquirir(); secci on cr tica(); cerrojo.liberar(); secci on no cr tica(); }

c Gustavo Romero

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Deshabilitar las interrupciones a nivel del n ucleo (2)


class cerrojo { public: cerrojo(): cerrado(false) {} void adquirir() { deshabilitar interrupciones(); * while (cerrado); cerrado = true; habilitar interrupciones(); } void liberar() { deshabilitar interrupciones(); cerrado = false; habilitar interrupciones(); } private: volatile bool cerrado; };

Permite implementar cerrojos (spin lock) de forma at omica: Existe alguna condici on de carrera? no. Utilizar as esta soluci on para resolver un problema de secci on cr tica? no. Cu al es su principal desventaja? espera ocupada con efectos laterales sobre el sistema. Es capaz de detectar un grave error? *
Exclusi on mutua (50/108)

c Gustavo Romero

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Deshabilitar las interrupciones a nivel del n ucleo (3)


class cerrojo { private: volatile bool cerrado; public: cerrojo(): cerrado(false) {} void adquirir() { deshabilitar interrupciones(); while (cerrado) { habilitar interrupciones(); deshabilitar interrupciones(); } cerrado = true; habilitar interrupciones(); }
c Gustavo Romero

void liberar() { deshabilitar interrupciones(); cerrado = false; habilitar interrupciones(); } };

Con esta soluci on es posible el cambio de hebra. Todav a no es una soluci on v alida porque no es portable y depende del n umero de procesadores.
Exclusi on mutua (51/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Instrucciones at omicas
Lectura/modicaci on/escritura sobre una posici on de memoria:
lock2 xchg %eax,( %edx): intercambia de forma at omica el valor del registro con la direcci on de memoria. lock xadd %eax,( %edx): intercambia y suma, %eax = ( %edx), ( %edx) = %eax + ( %edx). lock cmpxchg %ecx, ( %edx): compara el acumulador con ( %edx). Si son iguales activa ZF = 1 y hace ( %edx) = %ecx. En otro caso limpia ZF = 0 y lleva ( %edx) al acumulador.

Carga enlazada y almacenamiento condicional:


ldrex r1, [r0]: carga el contenido de la direcci on de memoria r0 y el procesador se vuelve sensible a dicha direcci on de memoria. strex r2, r1, [r0]: almacena r1 en [r0] si ning un otro procesador ha modicado el contenido de [r0] y coloca en r2 si la operaci on ha tenido exito.
2

prejo de bloqueo del bus, necesario con m as de 1 procesador.


c Gustavo Romero Exclusi on mutua (52/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

La instrucci on Test And Set


La instrucci on TAS se ejecuta siempre de forma at omica independientemente del n umero de cach es que se tengan.
Test And Set (v2) Test And Set (v1) bool test_and_set(bool *cerrojo) { bool viejo = *cerrojo; *cerrojo = true; return viejo; } bool test_and_set(int *c) { if (*c == 0) { *c = 1; return false; } return true; }

cerrojo es un par ametro tanto de entrada como de salida.


c Gustavo Romero Exclusi on mutua (53/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

La instrucci on Compare And Swap


Compare And Swap (v1) bool compare_and_swap(long *p, long viejo, long nuevo) { if (*p == viejo) { *p = nuevo; return true; } return false; } Compare And Swap (v2) long compare_and_swap(long *p, long viejo, long nuevo) { long valor = *p; if (*p == viejo) { *p = nuevo; } return valor; }
c Gustavo Romero Exclusi on mutua (54/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Ejemplo de implementaci on: i386/{futex,cmpxchg}.h


long int testandset (int *spinlock) { long int ret; __asm__ __volatile__("xchgl %0, %1" : "=r"(ret), "=m"(*spinlock) : "0"(1), "m"(*spinlock) : "memory"); return ret; } int compare_and_swap (long int *p, long int oldval, long int newval) { char ret; long int readval; __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" : "=q" (ret), "=m" (*p), "=a" (readval) : "r" (newval), "m" (*p), "a" (oldval) : "memory"); return ret; }
c Gustavo Romero Exclusi on mutua (55/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Implementaci on de un cerrojo mediante TAS


class cerrojo { public: cerrojo(): ocupado(false) adquirir() { while (test and set(&ocupado)); } liberar() { ocupado = false; } private: volatile bool ocupado; };
c Gustavo Romero

Existe todav a alguna condici on de carrera? no. Es portable? no. Es eciente? no. Qu e sucede cuando muchas hebras intentan adquirir el cerrojo? baja la tasa de aprovechamiento del procesador debido a la espera ocupada. Puede llamarse a adquirir() recursivamente?
Exclusi on mutua (56/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

An alisis del cerrojo (1)


La exclusi on mutua se preserva. Si Hi entra en su secci on cr tica las dem as hebras Hj realizan espera ocupada = problema de eciencia. Cuando Hi sale de su secci on cr tica, la elecci on de la siguiente hebra Hj es arbitraria lo que viola el requisito de espera acotada = posible inanici on. Algunos procesadores (como el Pentium) proporcionan instrucciones at omicas como xchg o cmpxchg que sufren los mismo inconvenientes que TAS. Sin embargo, Cu al es el mayor problema con este tipo de cerrojos?

c Gustavo Romero

Exclusi on mutua (57/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

An alisis del cerrojo (2)


Repetidas llamadas a test and set() pueden monopolizar el bus del sistema afectando a otras tareas independientemente de si est an relacionadas con la secci on cr tica o no. Qu e pasar a con la coherencia de cach e? garantizada.
write-through: Intel 486. write-back: MESI(pentium), MOESI(k8), MESIF(nehalem). Modied/Owned/Exclusive/Shared/Invalid/Forwarding.

Adem as hay un grave peligro de otra clase de inanici on en sistemas con un s olo procesador. Recordar lo que pasaba al utilizar espera ocupada a nivel de usuario y exist an diferentes tama nos de secci on no cr tica.

c Gustavo Romero

Exclusi on mutua (58/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Protocolos de coherencia de cach e MOESI

c Gustavo Romero

Exclusi on mutua (59/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Efecto ping-pong

El efecto ping-pong entre la cach e 1 y la cach e 2 monopoliza, y desperdicia, el uso del bus del sistema. Es necesario implementar cerrojos m as ecientes.
c Gustavo Romero Exclusi on mutua (60/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

Conclusiones sobre TAS


Ventajas: El n umero de hebras involucradas en la secci on cr tica puede ser ilimitado. Puede utilizarse para controlar varias secciones cr ticas sin m as que utilizar un cerrojo diferente para cada una ellas. Soluci on v alida en sistemas mono y multiprocesador. Soluci on simple y f acil de comprender. Inconvenientes: Las espera ocupada es ineciente. Una proceso o hebra tipo n ucleo puede padecer inanici on si tiene baja prioridad (planicador basado en prioridades). Susceptible a interbloqueo e inversi on de prioridad en secciones cr ticas anidadas.
c Gustavo Romero Exclusi on mutua (61/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Cerrojos Gesti on de interrupciones Instrucciones especiales

La instrucci on de intercambio
Disponible en la pr actica totalidad de los procesadores. Permite crear un protocolo de secci on cr tica? si. Soluciona el problema de la portabilidad? si. instrucci on de intercambio void intercambiar(bool *a, bool *b) { bool t = *a; *a = *b; *b = *t; }

c Gustavo Romero

Exclusi on mutua (62/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

N ucleo

c Gustavo Romero

Exclusi on mutua (63/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforos con contador


Valor de un sem aforo con contador: positivo: m aximo n umero de hebras que pueden entrar en una secci on cr tica. Si la exclusi on mutua es necesaria 1. negativo: n umero de hebras que han intentado entrar en su secci on cr tica y han sido bloqueadas en una cola de espera. cero: ninguna hebra est a esperando para entrar y dentro de la secci on cr tica hay tantas hebras como el valor al que se inicializ o el sem aforo. C omo conseguir que las operaciones sobre sem aforos sean at omicas?
c Gustavo Romero Exclusi on mutua (64/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforos con contador: implementaci on


class sem aforo { public: // 0? sem aforo(int _valor = 1): valor(_valor), bloq(vac a) void esperar() // p() { valor = valor - 1; if (valor < 0) { bloq.meter(esta); bloquear(esta); } }

void se~ nalar() // v() { valor = valor + 1; if (valor <= 0) { desbloquear(bloq.sacar()); } } private: int valor; lista<hebra> bloq; };

c Gustavo Romero

Exclusi on mutua (65/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Operaciones at omicas sobre sem aforos (1)


Problema: esperar() y se~ nalar() constan de m ultiples instrucciones m aquina que deben ejecutarse de forma at omica. Soluci on: Utilizar otro tipo de secciones cr ticas con la esperanza de que tenga tiempos de ejecuci on m as cortos y que permitan la atomicidad y exclusividad de las operaciones sobre el sem aforo.

c Gustavo Romero

Exclusi on mutua (66/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Operaciones at omicas sobre sem aforos (2)


Son deseables secciones cr ticas cortas al implementar esperar() y se~ nalar() at omicos. Posibles soluciones (ya vistas pero con renovada validez en este nuevo contexto): Monoprocesador:
Deshabilitar las interrupciones mientras se ejecutan las operaciones sobre sem aforos. Contradice la recomendaci on general de no manipular las interrupciones desde el nivel de usuario. Soluci on v alida porque sabemos que se van a deshabilitar durante muy poco tiempo conocemos el tama no de la secci on cr tica.

Multiprocesador:
Emplear instrucciones at omicas: TAS, CAS, LL/SC,...
c Gustavo Romero Exclusi on mutua (67/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforos con contador: implementaci on monoprocesador


class sem aforo { public: sem aforo(int _valor = 0): valor(_valor), bloq(vac a) {} void esperar() // p() { deshabilitar_interrupciones(); valor = valor - 1; if (valor < 0) { bloq.meter(esta); bloquear(esta); 3 } habilitar_interrupciones(); } void se~ nalar() // v() { deshabilitar_interrupciones(); valor = valor + 1; if (valor <= 0) { desbloquear(bloq.sacar()); } habilitar_interrupciones(); } private: volatile int valor; volatile lista<hebra> bloq; };

Qu e sucede al cambiar a otra hebra? Siguen las interrupciones deshabilitadas? 3 bloquear() = bloquear() + sti 4 desbloquear() = cli + desbloquear()
c Gustavo Romero Exclusi on mutua (68/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforos con contador: implementaci on multiprocesador


class sem aforo { public: sem aforo(int _valor = 0): ocupado(false), valor(_valor), bloq(vac a) {} void esperar() // p() { while(TAS(ocupado) == true); valor = valor - 1; if (valor < 0) { bloq.meter(esta); bloquear(esta); } ocupado = false; } } private: volatile bool ocupado; volatile int valor; volatile lista<hebra> bloq; };

void se~ nalar() // v() { while(TAS(ocupado) == true); valor = valor + 1; if (valor <= 0) { desbloquear(bloq.sacar()); } ocupado = false;

c Gustavo Romero

Exclusi on mutua (69/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforo d ebil


class sem aforo_d ebil { public: sem aforo_d ebil(int _valor = 0): valor(_valor), bloq(vac a) void esperar() // p() { valor = valor - 1; if (valor < 0) { bloq.meter(esta); bloquear(esta); } } void se~ nalar() // v() { valor = valor + 1; if (valor <= 0) { desbloquear(bloq.sacar()); } } private: int valor; lista<hebra> bloq; };

No se respeta el orden de llegada!

c Gustavo Romero

Exclusi on mutua (70/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforo fuerte (estricto)


} class sem aforo_fuerte { void se~ nalar() // v() public: sem aforo_fuerte(int _valor = 0): { valor = valor + 1; valor(_valor), if (valor <= 0) bloq(vac a) { void esperar() // p() desbloquear(bloq.primero()); { } valor = valor - 1; } if (valor < 0) { private: bloq.a~ nadir(esta); int valor; bloquear(esta); cola<hebra> bloq; } }; Respeta el orden primero en llegar, primero en ser servido = espera acotada.
c Gustavo Romero Exclusi on mutua (71/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Aplicaciones de los sem aforo con contador


Supongamos n hebras concurrentes: Si inicializamos s .valor = 1 s olo una hebra podr a entrar en su secci on cr tica = exclusi on mutua. Si inicializamos s .valor = k con k > 1 entonces k hebras podr an acceder a su secci on cr tica Cu ando utilizar as un sem aforo? = sincronizaci on, ejemplo: gesti on de recursos divisibles.
c Gustavo Romero

variable global sem aforo s = 1; hebrai while(true) { s.esperar(); secci on cr tica(); s.se~ nalar(); secci on no cr tica(); }

Exclusi on mutua (72/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Productor/Consumidor (b ufer ilimitado) (1)


Necesitamos un sem aforo, s, para conseguir la exclusi on mutua en el acceso al b ufer. Necesitamos otro sem aforo, n, para sincronizar el n umero de elementos del b ufer por parte del productor y el consumidor: s olo podemos consumir despu es de haber producido. El productor es libre para a nadir nuevos elementos al b ufer en cualquier instante, pero antes debe hacer s.esperar(). Tras a nadir un elemento debe hacer s.se~ nalar() para garantizar la exclusi on mutua. El productor debe hacer n.se~ nalar() despu es de cada ejecuci on de su secci on cr tica para avisar al consumidor que hay elementos para consumir. El consumidor debe hacer n.esperar() antes de ejecutar su secci on cr tica para asegurarse de que el b ufer contiene elementos.
c Gustavo Romero Exclusi on mutua (73/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Productor/Consumidor (b ufer ilimitado) (2)


sem aforo sem aforo volatile volatile s = 1; n = 0; elemento b ufer[]; int entra = 0, sale = 0; // // // // exclusi on mutua b ufer n umero de elementos b ufer ilimitado posiciones del b ufer

void* productor(void*) { while(true) { elemento e = producir(); s.esperar(); b ufer[entra++] = e; s.se~ nalar(); n.se~ nalar(); } }
5 c Gustavo Romero

void* consumidor(void*) { while(true) { n.esperar(); // el orden s.esperar(); // importa elemento e = b ufer[sale++]; s.se~ nalar(); consumir(e); } }

Por qu e es importante el orden de las 2 llamadas a esperar()?


Exclusi on mutua (74/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Productor/Consumidor (b ufer ilimitado) (3)


Necesitamos exclusi on mutua para el b ufer? si. Por qu e hace n.se~ nalar() el productor? permite al consumidor acceder a su secci on cr tica. Por qu e es importante el orden de las llamadas a esperar() en el consumidor? evita interbloqueo. Es el orden de las llamadas a se~ nalar() en el productor importante? si, por eciencia, acorta la secci on cr tica. Es esta soluci on extensible a m as de dos productores y/o consumidores? si. C omo modicar a esta implementaci on para el caso del b ufer limitado? a nadir un nuevo sem aforo para evitar producir sobre un b ufer lleno.
c Gustavo Romero Exclusi on mutua (75/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Productores/Consumidores (b ufer limitado)


const unsigned N = 100; // tama~ no del b ufer volatile elemento b ufer[]; // b ufer ilimitado volatile int entra = 0, sale = 0; // posiciones del b ufer sem aforo exclusi on = 1; // exclusi on mutua b ufer sem aforo elementos = 0; // n umero de elementos introducidos sem aforo huecos = N; // n umero de huecos libres void* productor(void*) { while(true) { elemento e = producir(); huecos.esperar(); exclusi on.esperar(); b ufer[entra] = e; entra = (entra + 1) % N; exclusi on.se~ nalar(); elementos.se~ nalar(); } }
c Gustavo Romero

void* consumidor(void*) { while(true) { elementos.esperar(); exclusi on.esperar(); elemento e = b ufer[sale]; sale = (sale + 1) % N; exclusi on.se~ nalar(); huecos.se~ nalar() consumir(e); } }
Exclusi on mutua (76/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforos binarios, cerrojos o mutex


En lugar de implementar adquirir() mediante espera ocupada podr amos utilizar el API del n ucleo: bloquear() y desbloquear(). Cuando el cerrojo ya est a en posesi on de una hebra, cualquier otra que llame a adquirir() ser a bloqueada. La hebra deber a permanecer bloqueada hasta que pueda adquirir el cerrojo. El procesador queda libre para ejecutar otras tareas. Tambi en es necesario modicar liberar() para tener en cuenta las hebras bloqueadas. Cada sem aforo binario tiene asociada una cola de hebras bloqueadas.
c Gustavo Romero Exclusi on mutua (77/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforo binario


class sem aforo_binario { public: sem aforo_binario(): ocupado(false), bloq(vac a) void esperar() { if (!ocupado) ocupado = true; else { cola.a~ nadir(esta); bloquear(esta); } } void se~ nalar() { if (cola.vac a()) ocupado = false; else desbloquear(cola.primero()); } private: volatile bool ocupado; volatile cola<hebra> bloq; };

Esta soluci on tiene efectos adversos muy serios sobre la arquitectura del sistema.

c Gustavo Romero

Exclusi on mutua (78/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforo binario: conicto de depuraci on


void esperar() { if (!ocupado) ocupado = true; else { cola.a~ nadir(esta); bloquear(esta); } } void se~ nalar() { if (cola.vac a()) ocupado = false; else desbloquear(cola.primero()); }
c Gustavo Romero

void depurador(hebra h) { bloquear(h); operaciones de depuraci on sobre h; desbloquear(h); } Conicto entre depurador y depurado: Doble bloquear() = uno es olvidado. desbloquear() en el depurador() viola la exclusi on mutua al permitir el acceso a su secci on cr tica a la hebra que ejecut o esperar(). desbloquear() en se~ nalar() viola el funcionamiento del depurador.
Exclusi on mutua (79/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Independencia conceptual (1)


bloquear() y desbloquear() son operaciones de planicaci on pura...
sin embargo las estamos utilizando para transferir informaci on entre hebras. el simple hecho de que alguien desbloquee una hebra le indica que posee acceso a la secci on cr tica.

Consecuencias:
la planicaci on y los sem aforos son operaciones fuertemente acopladas. Cualquier m etodo de sincronizaci on que utilice bloquear() y desbloquear() deber a tener en cuenta sus consecuencias sobre los sem aforos.

Todo m etodo de sincronizaci on, aunque l ogicamente independiente de la planicaci on, debe ser implementado en un u nico m odulo.
c Gustavo Romero Exclusi on mutua (80/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Independencia conceptual (2)


C omo arreglarlo? Intento 1: Contar las llamadas a bloquear() y desbloquear():
n bloquear() n desbloquear().

esperar(), se~ nalar(), depuraci on y planicaci on deben coexistir. Sin embargo el sistema podr a dejar de funcionar si no emparejamos de forma correcta las llamadas a bloquear() y desbloquear() soluci on no v alida. Intento 2: No transferir informaci on a trav es de desbloquear(). Transferir la informaci on acerca de quien posee el sem aforo de forma expl cita. Utilizar bloquear() y desbloquear() tan s olo como optimizaci on.
c Gustavo Romero Exclusi on mutua (81/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Sem aforo binario


class sem aforo_binario { public: sem aforo_binario(): propietario(nadie), bloq(vac a) } void se~ nalar() { if (cola.vac a()) propietario = nadie; else { propietario = cola.primero(); desbloquear(propietario); } }

void esperar() { if (propietario == nadie) propietario = esta; else { cola.a~ nadir(esta); do private: bloquear(esta); volatile hebra propietario; while (propietario != esta); volatile cola<hebra> bloq; } };
c Gustavo Romero Exclusi on mutua (82/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Independencia conceptual: conclusiones

Como reglas de dise no... Mantener independientes las cosas independientes. Evitar cualquier t ecnica que induzca efectos laterales.

Consecuencias: El dise no y la implementaci on de sem aforos requiere habilidad y visi on de futuro. Modicar las operaciones del n ucleo es justo lo contrario.

c Gustavo Romero

Exclusi on mutua (83/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

En resumen...
Los sem aforos son una herramienta de coordinaci on primitiva:
para garantizar la exclusi on mutua. para sincronizar hebras.

Las llamadas a esperar() y se~ nalar() suelen estar dispersas por varias hebras con lo que es dif cil comprender todos sus efectos. El uso debe ser correcto en todas estas las hebras. Una hebra defectuosa o maliciosa puede estropear el funcionamiento del resto. Algunos autores recomiendan evitar su uso = Qu e utilizar en su lugar? Existen mejores m etodos de sincronizaci on?
c Gustavo Romero Exclusi on mutua (84/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Monitores

Construcciones de alto nivel de algunos lenguajes de programaci on.


Funcionamiento parecido al de los sem aforos binarios. Gesti on autom atica por parte del lenguaje.

Ofrecido en lenguajes de programaci on concurrente como Java, Modula-3, Pascal concurrente,... Internamente puede ser implementado mediante sem aforos u otros mecanismos de sincronizaci on.

c Gustavo Romero

Exclusi on mutua (85/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Denici on de monitor Un m odulo software (clase) que contiene:


Una interfaz con uno o m as procedimientos. Una secuencia de inicializaci on. Variables de datos locales.

Caracter sticas:
Las variables locales s olo son accesibles mediante los procedimientos del monitor. Una hebra entra en el monitor mediante la invocaci on de uno de sus procedimientos. S olo una hebra puede estar ejecutando alg un procedimiento del monitor los monitores proporcionan exclusi on mutua de forma autom atica.

c Gustavo Romero

Exclusi on mutua (86/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Caracter sticas de los monitores


Los monitores aseguran la exclusi on mutua = no es necesario programar esta restricci on expl citamente. Los datos compartidos son protegidos autom aticamente si los colocamos dentro de un monitor. Los monitores bloquean sus datos cuando una hebra entra. Sincronizaci on adicional puede conseguirse dentro de un monitor mediante el uso de variables condici on. Una variable de condici on representa una condici on (evento) que tiene que cumplirse antes de que una hebra pueda continuar la ejecuci on de alguno de los procedimientos del monitor.
c Gustavo Romero Exclusi on mutua (87/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Ejemplo: B ufer circular (1)


Ejemplo de monitor sin variables condici on

Utilizaci on de un vector contiguo de N posiciones como b ufer circular. Interfaz con operaciones: recuperar() y depositar()

c Gustavo Romero

Exclusi on mutua (88/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Ejemplo: b ufer circular (2)


monitor b ufer_circular { public: b ufer_circular(): b ufer(vacio), cabeza(0), cola(0), contador(0) {} void depositar(elemento e) { b ufer[cola] = e; cola = (cola + 1) % N; contador = contador + 1; } void recuperar(elemento e) { e = b ufer[cabeza]; cabeza = (cabeza + 1) % N; contador = contador - 1; } private: elemento b ufer[N]; int cabeza, cola, contador; };

Exclusi on mutua autom atica entre hebras. Operaciones serializadas pero aun podemos depositar() sobre un b ufer lleno o recuperar() desde un b ufer vacio 2 restricciones m as.
c Gustavo Romero Exclusi on mutua (89/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Ejemplo: b ufer circular (3)


monitor b ufer_circular { public: b ufer_circular(): b ufer(vacio), cabeza(0), cola(0), contador(0), dep(vac a), rec(vac a) {} void depositar(elemento e) { while (contador == N) * bloquear(dep.meter(esta)); b ufer[cola] = e; cola = (cola + 1) % N; contador = contador + 1; if (!rec.vac a()) desbloquear(rec.sacar()); } } private: elemento b ufer[N]; int cabeza, cola, contador; cola<hebra> dep, rec; }; void recuperar(elemento e) { while (contador == 0) * bloquear(rec.meter(esta)); e = b ufer[cabeza]; cabeza = (cabeza + 1) % N; contador = contador - 1; if (!dep.vac a()) desbloquear(dep.sacar());

Ya no podemos depositar sobre un b ufer lleno o recuperar desde un b ufer vacio pero... bloqueamos el monitor (*).
c Gustavo Romero Exclusi on mutua (90/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Variables condici on

Variables locales al monitor y s olo accesibles desde su interior mediante las operaciones: esperar(): Bloquea la ejecuci on de la hebra llamadora sobre la variable condici on. La hebra bloqueada s olo puede continuar su ejecuci on si otra ejecuta se~ nalar(). Antes de bloquearse libera el monitor. se~ nalar(): Reactiva la ejecuci on de alguna hebra bloqueada en la variable condici on. Si hay varias podemos escoger una cualquiera. Si no hay ninguna no hace nada.

c Gustavo Romero

Exclusi on mutua (91/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Monitores y variables condici on

Las hebras pueden estar esperando en la cola de entrada o en la de alguna variable de condici on. Una hebra se pone en la cola de espera al invocar esperar() sobre una variable de condici on. se~ nalar() permite a una hebra que estuviese bloqueada en la cola de una condici on continuar. se~ nalar() bloquea a la hebra llamadora y la pone en la cola urgente a menos que sea la u ltima operaci on del procedimiento (?).
c Gustavo Romero Exclusi on mutua (92/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Ejemplo: b ufer circular (v2)


Ejemplo de monitor con variables condici on
monitor b ufer_circular { public: b ufer_circular(): b ufer(no vacio), cabeza(0), cola(0), contador(0) {} void depositar(elemento e) { while (contador == N) no lleno.esperar(); b ufer[cola] = e; cola = (cola + 1) % N; contador = contador + 1; no vacio.se~ nalar(); }

void recuperar(elemento e) { while (contador == 0) no vacio.esperar(); e = b ufer[cabeza]; cabeza = (cabeza + 1) % N; contador = contador - 1; no lleno.se~ nalar(); } private: elemento b ufer[N]; int cabeza, cola, contador; variable_condici on no lleno, no vacio; };

No bloquea el monitor, s olo hebras.


c Gustavo Romero Exclusi on mutua (93/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Productor/consumidor con monitores


Dos tipos de hebras:
1 2

productori while (true) { producir(e); depositar(e); } consumidori while (true) { recuperar(e); consumir(e); }
Exclusi on mutua (94/108)

productor consumidor

La sincronizaci on queda connada en el interior del monitor. depositar() y recuperar() son m etodos del monitor. Si estos m etodos se implementan correctamente cualquier hebra podr a utilizarlos para sincronizarse de forma correcta.
c Gustavo Romero

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos Monitores Variables condici on

Comentarios y problemas sin resolver

Si una hebra Hi ejecuta se~ nalar() mientras que otra, Hj , estaba bloqueada debido a una ejecuci on previa de esperar(), Cu al de las dos deber a continuar ejecut andose? estilos Hoare/Mesa. Un monitor deber a permanecer cerrado si alg un evento iniciado externamente ocurriese, por ejemplo el n del quantum asignado. De otra forma no podr amos garantizar la exclusi on mutua otra hebra podr a ejecutar el monitor. Qu e hacer si un m etodo de un monitor Mi invoca un m etodo de otro monitor Mj ?

c Gustavo Romero

Exclusi on mutua (95/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Problemas

c Gustavo Romero

Exclusi on mutua (96/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de la cena de los l osofos (1)

vida de un l osofo repetir { pensar estar hambriento coger tenedores comer soltar tenedores }

c Gustavo Romero

Exclusi on mutua (97/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de la cena de los l osofos (2)


Posibles soluciones:
Turno c clico Se empieza por un l osofo, si quiere comer lo hace y, en cualquier caso, pasa el turno al siguiente. Colas de tenedores Cada tenedor tiene asociada una cola de peticiones. Si el l osofo no puede coger los dos tenedores devuelve el que tiene y espera una cantidad de tiempo aleatorio antes de volver a intentarlo. Camarero Deja que como m aximo se sienten a comer n 1 l osofos con lo que se garantiza que al menos uno de ellos pueda comer. Jerarqu a de recursos Numerar los tenedores y coger siempre el de menor valor antes de coger el de mayor. Devolverlos en orden contrario.
c Gustavo Romero Exclusi on mutua (98/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de la cena de los l osofos (3)


Soluci on de Chandy/Misra (1984) Algoritmo:
1

Para cada par de l osofos que compiten por un tenedor d arselo al de menor identicador. Cuando un l osofo quiere comer debe obtener los dos tenedores de sus vecinos. Por cada tenedor que no tenga debe enviar un mensaje para solicitarlo. Cuando un l osofo posee un tenedor y recibe una petici on pueden pasar dos cosas:

Si est a limpio lo conserva. Si est a sucio lo limpia y lo pasa.


4

Despu es de comer los dos tenedores de un l osofo est an sucios. Si otro l osofo solicita alguno de ellos lo limpia y lo pasa. Cada tenedor puede estar limpio o sucio. Inicialmente todos los tenedores est an sucios. El sistema debe inicializarse de forma no perfectamente sim etrica, ej: todos los l osofos poseen el tenedor izquierdo.
c Gustavo Romero Exclusi on mutua (99/108)

Notas:

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de la cena de los l osofos (4)


Libre de interbloqueos? Supongamos un interbloqueo: todos los l osofos tienen el tenedor izquierdo limpio. El F1 obtuvo su tenedor de F2 porque...
el tenedor estaba sucio despu es de que F2 comiera. los tenedores s olo se limpian al pasarse. los tenedores limpios nunca se pasan.

F2 comi o despu es de F1 , F3 comi o despu es de F2 , F4 comi o despu es de F3 y F1 comi o despu es de F4 = F1 comi o despu es de F1 = contradicci on. El interbloqueo es imposible

c Gustavo Romero

Exclusi on mutua (100/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de la cena de los l osofos (5)


Libre de inanici on? Un l osofo pasa hambre si...
tiene un tenedor limpio. no tiene ning un tenedor.

Imaginemos que el F1 acaba sin ning un tenedor, entonces...


el F2 pasa hambre con el tenedor derecho limpio. el F4 pasa hambre con el tenedor izquierdo limpio. el F3 tambi en pasar a hambre porque no puede estar comiendo eternamente = contradicci on con interbloqueo.

Supongamos entonces que el F1 tiene el tenedor izquierdo limpio, entonces...


el F2 pasa hambre con el tenedor izquierdo limpio. los F3 y F4 tambi en pasar an hambre por la misma causa = contradicci on con interbloqueo.

La inanici on es imposible.
c Gustavo Romero Exclusi on mutua (101/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de los lectores/escritores


Los lectores tienen prioridad (W. Stallings)
unsigned numero lectores = 0; // numero de lectores semaforo no lectores = 1; // exclusion mutua para numero lectores semaforo no escritor = 1; // exclusion mutua datos compartidos ----------------------------------------------------------------------void* lector(void*) { while(true) { no lectores.esperar(); ++numero lectores; if (numero lectores == 1) no escritor.esperar(); nalar(); no lectores.se~ leer(); no lectores.esperar(); --numero lectores; if (numero lectores == 0) nalar(); no escritor.se~ no lectores.se~ nalar(); } }
c Gustavo Romero

void* escritor(void*) { while(true) { no escritor.esperar(); escribir(); no escritor.se~ nalar(); } }

Exclusi on mutua (102/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de los lectores/escritores (2)


Los lectores tienen prioridad (W. Stallings) void* lector(void*) { while(true) { no lectores.esperar(); ++numero lectores; if (numero lectores == 1) no escritor.esperar(); no lectores.se~ nalar(); leer(); no lectores.esperar(); --numero lectores; if (numero lectores == 0) no escritor.se~ nalar(); no lectores.se~ nalar(); } }
c Gustavo Romero Exclusi on mutua (103/108)

void* escritor(void*) { while(true) { no escritor.esperar(); escribir(); no escritor.se~ nalar(); } }

Introducci on Usuario Hardware N ucleo Problemas Pthreads

El problema de los lectores/escritores (3)


Los escritores tienen prioridad (J. Bacon)
class RWProtocol void adquirir_lector() { { private: sem_wait(CGUARD); sem aforo ar = ar + 1; R, // lecturas pendientes if (aw == 0) W, // escrituras pendientes { WGUARD, // escritura exclusiva rr = rr + 1; CGUARD; // exclusi on contadores sem_post(R); int } ar, // lectores activos sem_post(CGUARD); rr, // lectores leyendo sem_wait(R); aw, // escritores activos } ww; // escritores escribiendo void liberar_lector() public: { RWProtocol() sem_wait(CGUARD); : ar(0), rr(0), aw(0), ww(0) rr = rr - 1; { ar = ar - 1; sem_init(R , 0, 0); if (rr == 0) sem_init(W , 0, 0); while (ww < aw) sem_init(WGUARD, 0, 1); { sem_init(CGUARD, 0, 1); ww = ww + 1; } sem_post(W); } sem_post(CGUARD); } void adquirir_escritor() { sem_wait(CGUARD); aw = aw + 1; if (rr == 0) { ww = ww + 1; sem_post(W); } sem_post(CGUARD); sem_wait(W); sem_wait(WGUARD); } void liberar_escritor() { sem_post(WGUARD); sem_wait(CGUARD); ww = ww - 1; aw = aw - 1; if (aw == 0) while (rr < ar) { rr = rr + 1; sem_post(R); } sem_post(CGUARD); } };

c Gustavo Romero

Exclusi on mutua (104/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Pthreads

c Gustavo Romero

Exclusi on mutua (105/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos binarios: mutex en Pthreads


#include <pthreads.h> Cabecera C/C++. pthread mutex t Tipo mutex, inicializable a PTHREAD MUTEX INITIALIZER. pthread mutex init(mutex, attr) Crea e inicializa mutex con los atributos attr. pthread mutex destroy(mutex) Destruye mutex. pthread mutex lock(mutex) Adquiere mutex en caso de estar libre. En otro caso bloquea la hebra. pthread mutex unlock(mutex) Desbloquea mutex. pthread mutex trylock(mutex) Intenta bloquear mutex y en caso de no poder continua sin bloquear la hebra.

c Gustavo Romero

Exclusi on mutua (106/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Sem aforos: sem aforos POSIX


#include <semaphore.h> Cabecera C/C++. sem t Tipo sem aforo. sem init(sem, attr, valor) Inicializa el sem aforo sem al valor valor con los atributos attr. sem destroy(sem) Destruye el sem aforo sem. sem wait(sem) Si el valor del sem aforo sem es positivo lo decrementa y retorna inmediatamente. En otro caso se bloquea hasta poder hacerlo. sem trywait(sem) Versi on 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 aforo sem. En caso de cambiar a un valor positivo desbloquea a alguno de los llamadores bloqueados en sem wait(sem).
c Gustavo Romero Exclusi on mutua (107/108)

Introducci on Usuario Hardware N ucleo Problemas Pthreads

Variables condici on: Pthreads


pthread cond t Tipo variable de condici on. Inicializable a PTHREAD COND INITIALIZER. pthread cond init(cond,attr) Inicializa la variable de condici on cond con los atributos attr. pthread cond destroy(cond) Destruye la variable de condici on cond. pthread cond wait(cond, mutex) Bloque a la hebra llamadora hasta que se se nale cond. Esta funci on debe llamarse mientras mutex est a ocupado y ella se encargar a de liberarlo autom aticamente mientas espera. Despu es de la se nal la hebra es despertada y el cerrojo es ocupado de nuevo. El programador es responsable de desocupar mutex al nalizar la secci on cr tica para la que se emplea. pthread cond signal(cond) Funci on para despertar a otra hebra que espera que se se nale sobre la variable de condici on cond. Debe llamarse despu es de que mutex est e ocupado y se encarga de liberarlo en pthread cond wait(cond, mutex). pthread cond broadcast(cond) Igual que la funci on anterior para el caso de que queramos desbloquear a varias hebras que esperan.
c Gustavo Romero Exclusi on mutua (108/108)

You might also like