Sunteți pe pagina 1din 45

Procesos

Es el concepto/abstraccin ms importante en los sist. op.


Proporcionan la capacidad de operar (pseudo)concurrentemente
Toda computadora moderna puede hacer varias cosas a la vez

2 - Procesos e hilos

Da al usuario la ilusin de paralelismo: muchos procesos


corriendo al mismo tiempo:
Pseudoparalelismo -> una CPU
Multiprocesadores -> varias CPUs

Un proceso es un programa secuencial corriendo en una unidad


de ejecucin (virtual o real) incluyendo los valores actuales del
PC, registros, variables,...

Procesos: El modelo de procesos


Ej: dos procesos corriendo en una mquina con una CPU

Lectura a disco

Cada proceso tiene su propia CPU virtual para ejecutar


En realidad la CPU conmuta de un proceso a otro
-> multiprogramacin

P0

=>Cuando el Sist. Op. realiza multiplexado temporal debe guardar


el estado del proceso:
registros
pila
espacio de direccion.

file descriptor
variables de entorno
seales

Cant. de instrucciones

Procesos: El modelo de procesos

P1
Peticin
a disco
[P0]

Lo que ocurre en la mquina

Tiempo

Procesos: El modelo de procesos

Procesos: El modelo de procesos

Excede quantum

P0

P1
Peticin
a disco
[P0]

Tiempo

Fin de
tiempo
[P1]

Envo de mensaje

Cant. de instrucciones

P0

Ej: dos procesos corriendo en una mquina con una CPU

Cant. de instrucciones

Ej: dos procesos corriendo en una mquina con una CPU

P1
Peticin
a disco
[P0]

Fin de
tiempo
[P1]

Uso
de red
[P0]

Lo que ocurre en la mquina

Lo que ocurre en la mquina

Procesos: El modelo de procesos

Procesos: El modelo de procesos

P0

Ej: dos procesos corriendo en una mquina con una CPU

Cant. de instrucciones

Ej: dos procesos corriendo en una mquina con una CPU

P0

P1
Peticin
a disco
[P0]

Fin de
tiempo
[P1]

Lo que ocurre en la mquina

Uso
de red
[P0]

P1

Tiempo

Lo que uno ve

Tiempo

Procesos: El modelo de procesos


Observar:

Procesos: El modelo de procesos


Observar:

La velocidad con que el proceso realiza su ejecucin no es


uniforme

La velocidad con que el proceso realiza su ejecucin no es


Comparar con un programa
uniforme

El orden en el que se intercalan las instrucciones de P0 y P1


no est definido

El orden en el que se intercalan las instrucciones de P0 y P1


no est definido

=>La forma en que se ejecutan ambos procesos no es fcilmente


reproducible

=>La forma en que se ejecutan ambos procesos no es fcilmente


reproducible

Por consiguiente:

secuencial/determinista

Por consiguiente:

Los procesos no deben programarse con presuposiciones


temporales

Procesos: El modelo de procesos

Los procesos no deben programarse con presuposiciones


temporales

Procesos: Creacin
Sistemas simples -> Todos los procesos se crean al principio

Observar:
La velocidad con que el proceso realiza su ejecucin no es
uniforme

Sistemas de propsitos generales

El orden en el que se intercalan las instrucciones de P0 y P1


no est definido

Cuatro eventos posibles determinan la creacin de un proceso:

=>La forma en que se ejecutan ambos


procesos
no(ej:
essist.
fcilmente
Si fuera
necesario
de tiempo
real)
se
requieren
medidas
especiales y
reproducible
sistemas operativos especiales

Por consiguiente:
Los procesos no deben programarse con presuposiciones
temporales

-> se necesita una forma de crear y terminar procesos


1. Inicializacin del sistema
2.Un proceso en ejecucin realiza una
llamada al sistema para crear un
nuevo proceso
3.El usuario pide crear un nuevo proceso
4.Se inicia un nuevo trabajo en batch

Al bootear, el SO crea muchos procesos

Procesos:Foreground
Creacin
-> procesos que interactan

Procesos: Creacin

directamente con el usuario

Crear nuevos procesos para que

Background:
Sistemas simples -> Todos los procesos
se crean al principio

Sistemas simples -> Todos los procesoscolaboren


se crean
al ellos.
principio
entre

ps -ax
Sistemas de propsitos
generales
-

Sistemas de propsitos generales

- no estn asociados a un usuario en particular

tienen funcionalidad especfica

-> se necesita una forma


de crear
y terminar
procesos
- daemons
(mal traducidos
como demonios)
Cuatro eventos posibles

- Ej:
determinan

1. Inicializacin del sistema

la creacin de un proceso:

- Proc. que acepta e-mail entrante


- o que acepta solicitudes de requerimientos

Particularmente til si los procesos


son bastante independientes entre s.

-> se necesita una forma de crear


y terminar procesos
Ej:
ls -R *de| un
sort
| uniq
Cuatro eventos posibles determinan la creacin
proceso:

1. Inicializacin del sistema

pginas web (ej: apache)


2.Un proceso en ejecucin realizadeuna
o que acepta conexiones entrantes de
llamada al sistema para crear un
internet (ej: inetd)
nuevo proceso

2.Un proceso en ejecucin realiza una


llamada al sistema para crear un
nuevo proceso

3.El usuario pide crear un nuevo proceso

3.El usuario pide crear un nuevo proceso

4.Se inicia un nuevo trabajo en batch

4.Se inicia un nuevo trabajo en batch

- o el spooler de la impresora (ej: cupsd)

Procesos: Creacin

Procesos: Creacin

Sistemas simples -> Todos los procesos se crean al principio

Sistemas simples -> Todos los procesos se crean al principio

Sistemas de propsitos generales

Sistemas de propsitos generales

Sistemas interactivos:
- doble click o

-> se necesita una forma de crear y terminar procesos


Cuatro eventos posibles determinan la
1. Inicializacin del sistema

- escribiendo un comando en una


creacin
terminal de un proceso:

En ambos casos se inicia un nuevo


proceso y se ejecuta el proceso
una seleccionado

-d

-> se necesita una forma de crear y terminar procesos


Cuatro eventos posibles determinan la creacin de un proceso:
1. Inicializacin del sistema

Solo en sistemas batch (por lotes)


Cuando el SO decide que tiene
recursos suficientes para iniciar
otro trabajo, crea un proceso y
ejecuta el siguiente trabajo en la
cola

2.Un proceso en ejecucin realiza


llamada al sistema para crear un
nuevo proceso

2.Un proceso en ejecucin realiza una


llamada al sistema para crear un
nuevo proceso

3.El usuario pide crear un nuevo proceso

3.El usuario pide crear un nuevo proceso

4.Se inicia un nuevo trabajo en batch

4.Se inicia un nuevo trabajo en batch

Esto se hace para compartir.


En particular permite compartir file descriptors y
redireccionarlos apropiadamente antes del execve.
Ej: ls -R * | sort | uniq -d

Procesos: Creacin

Procesos: Creacin

Tcnicamente, en todos los casos un proceso existente efecta


la llamada al sistema para crear un nuevo proceso

Tcnicamente, en todos los casos un proceso existente efecta


la llamada al sistema para crear un nuevo proceso

Esta llamada al sistema

Esta llamada al sistema

pide al SO crear un nuevo proceso e

pide al SO crear un nuevo proceso e

indica que programa correr sobre este

indica que programa correr sobre este

incluyendo
variables de entorno,
archivos abiertos, espacio de
direccionamiento, etc.

! fork -> crea una copia exacta del proceso que llama
UNIX " execve -> llamada por el proceso hijo para ejecutar un
nuevo programa
#

! fork -> crea una copia exacta del proceso que llama
UNIX " execve -> llamada por el proceso hijo para ejecutar un
nuevo programa
#

Windows -> Slo una llamada: CreatProcess + 10 parmetros

Windows -> Slo una llamada: CreatProcess + 10 parmetros

En ambos casos los espacios de direcciones de padre e hijo son


disjuntos

En ambos casos los espacios de direcciones de padre e hijo son


disjuntos

Procesos: Creacin

Procesos: Terminacin

Tcnicamente, en todos los casos un proceso existente efecta


la llamada al sistema para crear un nuevo proceso
Esta llamada al sistema

voluntaria

pide al SO crear un nuevo proceso e


indica que programa correr sobre este

!
"
#

fork

Terminacin

-> crea una copia exacta del proceso que llama

En Windows, los espacios de

En UNIX, el espacio de

UNIX direccionamiento
execve -> llamada
procesodireccionamiento
hijo para ejecutar
se copia.un
del padre por
y delel
hijo
son distintos.
nuevo programa (En algunos UNIX: copy on write)
Windows -> Slo una llamada: CreatProcess + 10 parmetros
En ambos casos los espacios de direcciones de padre e hijo son
disjuntos

involuntaria

Normal:
Ej: exit(0), Quit del men
Errnea:
Ej: gcc test.c, pero test.c
no existe -> exit(4)
Error causado por el proceso:
Ej: divisin por 0, referencia a
una dir. de mem. inexistente
Matado por otro proceso: kill
Ej: killall mozilla.bin.

Procesos: Jerarqua
UNIX:
Jerrquico: se mantiene la estructura padre-hijo segn
creacin
Ver con pstree
Tiene cierta utilidad para manejar grupo de procesos
Windows:
No hay jerarqua
Slo existe un token especial (handle) que se retorna al padre
en la creacin, pero este puede cederlo a otro proceso

Procesos: Estado de los procesos


Supongamos dos procesos que estn interactuando entre s
Ej:

cat cap1.txt cap2.txt cap2.txt | grep abracadabra

Si cat produce ms lento de lo que grep consume,


grep debe esperar aunque la CPU est a su disposicin
En este caso grep queda bloqueado.

dargenio@russell:~$ pstree
init!"!acpid
#!apache2!!!10*[apache2]
#!3*[automount]
#!cron
#!dnsmasq
#!fail2ban-server!!!8*[{fail2ban-serve}]
UNIX:
#!6*[getty]
#!klogd
Jerrquico: se mantiene la estructura
padre-hijo segn
#!mailmanctl!!!8*[python]
#!master!"!pickup
creacin
$
#!qmgr
$
%!tlsmgr
Ver con pstree
#!mysqld_safe!"!logger
$
%!mysqld!!!17*[{mysqld}]
Tiene cierta utilidad para manejar
grupo de procesos
#!portmap
#!rpc.idmapd
#!rpc.mountd
#!rpc.statd
#!rpc.yppasswdd
Windows:
#!rpc.ypxfrd
#!sensord
No hay jerarqua
#!sshd!"!sshd!!!sshd!!!bash!!!ssh
$
%!sshd!!!sshd!!!bash!!!pstree
Slo existe un token especial#!syslogd
(handle) que se retorna al padre
#!udevd!!!2*[udevd]
en la creacin, pero este puede
cederlo a otro proceso
#!ypbind!!!2*[{ypbind}]
%!ypserv

Procesos: Jerarqua

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:
Ejecutando: usando la CPU en este instante
Listo: puede ejecutarse pero no hay CPU disponible
Bloqueado: imposibilitado de ejecutar hasta la ocurrencia de
algn evento particular

Un proceso que est listo para ejecutar puede que no lo haga


porque hay otro proceso haciendo uso de la CPU.
Notar:

Ejecutando

bloqueado ! listo

Suspensin inherente
al problema

Tecnicalidad del sistema


(#CPU < #proc. listos p/ejecutar)

Bloqueado

Listo

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:

Ejecutando: usando la CPU en este instante

Ejecutando: usando la CPU en este instante

Listo: puede ejecutarse pero no hay CPU disponible

Listo: puede ejecutarse pero no hay CPU disponible

Bloqueado: imposibilitado de ejecutar hasta la ocurrencia de

Bloqueado: imposibilitado de ejecutar hasta El


la scheduler
ocurrencia de
determina que el proceso
algn evento particular

El proceso en ejecucin
algn
evento
requiere
algn
eventoparticular
para
continuar (ej: el arribo de un
dato de entrada)

en ejecucin debe dejar la CPU


(ej: se acab el quantum)

Ejecutando

Bloqueado

Ejecutando

Listo

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:

Bloqueado

Listo

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:

Ejecutando: usando la CPU en este instante

Ejecutando: usando la CPU en este instante

Listo: puede ejecutarse pero no hay CPU disponible

Listo: puede ejecutarse pero no hay CPU disponible

se libera yde
un
Bloqueado: imposibilitado de ejecutar hastaLalaCPU
ocurrencia
proceso en la cola de listos
algn evento particular

Bloqueado: imposibilitado de ejecutar hasta la ocurrencia de


Se produjo
algn
evento elparticular

Ejecutando

Bloqueado

retoma la ejecucin. El criterio


para elegir el proceso en la cola
de listos depende de la poltica
de scheduling.

Listo

evento esperado. El
proceso est ahora listo para
ejecutar (ej: ya se
produjo la entrada)

Bloqueado

Ejecutando

Listo

Lgicamente,
los estados ejecutando y listo
son similares: en ambos casos el
proceso est dispuesto a
ejecutar

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:

Procesos: Estado de los procesos


Un proceso puede estar en 3 estados:

Ejecutando: usando la CPU en este instante

Ejecutando: usando la CPU en este instante

Listo: puede ejecutarse pero no hay CPU disponible

Listo: puede ejecutarse pero no hay CPU disponible

Bloqueado: imposibilitado de ejecutar hasta la ocurrencia de


algn evento particular

La forma en de
la
Bloqueado: imposibilitado de ejecutar hasta la ocurrencia
que se administran estas
algn evento particular
dos transiciones es tarea del

Ejecutando

Bloqueado

En cambio, si el
proceso est bloqueado,
ste no puede ejecutar an
si la CPU est ociosa.

Listo

Procesos: ejecutan
Procesos: Estado deprogramas
los procesos
de usuarios, o son parte

Modelo en capas

del sistema y se encargan de brindar


servicios a los programas usuarios o
de administrar recursos

planificador de procesos o
scheduler

Ejecutando

Bloqueado

Listo

Procesos: Implementacin
Se implementa a travs de tablas de procesos
Tabla de procesos -> arreglos o listas:
una entrada por proceso

Procesos

cada entrada es un bloque de control de proceso (PCB:


process control block)
el PCB contiene la info del estado del proceso
->Todo lo que necesita guardarse cuando el proceso cambia de
ejecutando a listo o bloqueado para luego poder recomenzar
a ejecutar como si nunca hubiera sido detenido

Scheduler
Scheduler (o Planificador):
da la ilusin de mltiples CPU

Procesos: Implementacin
Depende
del procesador y del sistema
operativo

Contenido tpico del PCB

Hilos (Threads)
Sistemas operativos tradicionales
->cada proceso tiene un espacio de dir. y un slo hilo de control
Hay situaciones en las que es conveniente tener varios hilos de
ejecucin en el mismo espacio de direccionamiento.
Como si fueran procesos (casi) separados excepto que
comparten el espacio de direccionamiento.

Por qu queremos esto?


Ejemplos?

Hilos: Uso
Por qu queremos hilos?

Hilos: Uso
Por qu queremos hilos?

Para manejar muchas actividades al mismo tiempo

Para manejar muchas actividades al mismo tiempo


Adems:

Y no tenemos a los
procesos para esto?

Permite computar concurrentemente compartiendo datos


Como comparten (casi) todo:
es mucho ms simple crear y destruir hilos

hasta 100 veces ms


rpido que en procesos

el context switch es mucho ms rpido que en los procesos


Ejecutan con mejor desempeo si hay mucha actividad I/O
bound (permite solapar actividades)
Si hay mltiples CPUs => verdadero paralelismo

Ej: Servidor web de algn sitio.

Hilos: UsoEj: Word podra manipular 5 hilos

Hilos: Uso

idea simple: tener una cach en memoria con las pginas


Ej: Word podra manipular 5 hilos
solicitadas ms frecuentemente
simultneamente:

simultneamente:

Por qu queremos hilos?

Por qu queremos hilos?

1. prepaginado
2. impresin

Para manejar muchas actividades al mismo tiempo


3. spell checking

Adems:

4. backup automtico

1. prepaginado

2. impresin
Para manejar muchas actividades al mismo
tiempo
3. spell checking

Adems:

4. backup automtico

Permite computar concurrentemente 5.


compartiendo
datos
hilo principal

Permite computar concurrentemente 5.


compartiendo
datos
hilo principal

Como comparten (casi) todo:

Como comparten (casi) todo:

es mucho ms simple crear y destruir hilos

hasta 100 veces ms


rpido que en procesos

el context switch es mucho ms rpido que en los procesos

es mucho ms simple crear y destruir hilos

hasta 100 veces ms


rpido que en procesos

el context switch es mucho ms rpido que en los procesos

Ejecutan con mejor desempeo si hay mucha actividad I/O


bound (permite solapar actividades)

Ejecutan con mejor desempeo si hay mucha actividad I/O


bound (permite solapar actividades)

Si hay mltiples CPUs => verdadero paralelismo

Si hay mltiples CPUs => verdadero paralelismo

Ej: Servidor web de algn sitio.

Hilos: Uso

Hilos: El modelo de hilos

idea simple: tener una cach en memoria con las pginas


Ej: Word podra manipular 5 hilos
solicitadas ms frecuentemente
simultneamente:

Por qu queremos hilos?

El modelo de procesos se basa en dos conceptos independientes:

1. prepaginado

2. impresin
Para manejar muchas actividades al mismo
tiempo

Adems:

3. spell checking

4. backup automtico

agrupacin de recursos
ejecucin

Permite computar concurrentemente 5.


compartiendo
datos
hilo principal

Podramos enfocarnos slo en el hilo de ejecucin del proceso

Como comparten (casi) todo:

Para el hilo de ejecucin slo es relevante:

es mucho ms simple crear y destruir hilos

hasta 100 veces ms


rpido que en procesos

el context switch es mucho ms rpido que en los procesos


Ejecutan con mejor desempeo si hay mucha actividad I/O
bound (permite solapar actividades)
Si hay mltiples CPUs => verdadero paralelismo

el contador del programa,


los registros de la CPU, y
la pila de ejecucin

los recursos que

los recursos que

Hilos: El modelo de hilos


el proceso necesita para

Hilos: El modelo de hilos


el proceso necesita para

funcionar

El modelo de procesos se basa en dos conceptos independientes:

funcionar

El modelo de procesos se basa en dos conceptos independientes:

agrupacin de recursos

agrupacin de recursos

ejecucin

ejecucin

Podramos enfocarnos slo en el hilo de ejecucin del proceso

Podramos enfocarnos slo en el hilo de ejecucin del proceso

Para el hilo de ejecucin slo es relevante:

Para el hilo de ejecucin slo es relevante:

el contador del programa,


los registros de la CPU, y
la pila de ejecucin

registra cual es la
instruccin que se ejecutar a
continuacin
contiene las variables
de trabajo actuales
contiene el historial de
llamadas a procedimientos pendientes a
lo largo de la ejecucin

el contador del programa,


los registros de la CPU, y
la pila de ejecucin

El hilo y su proceso son conceptos


distintos y pueden tratarse por separado

Hilos: El modelo de hilos

Hilos: El modelo de hilos

El hilo y su proceso son conceptos


distintos y pueden tratarse por separado

El hilo y su proceso son conceptos


distintos y pueden tratarse por separado

Los procesos se usan para para agrupar recursos

Los procesos se usan para para agrupar recursos

Los hilos son las entidades planificadas para ejecutar en la CPU

Los hilos son las entidades planificadas para ejecutar en la CPU

=>Los hilos permiten mltiples ejecuciones en un nico proceso


dentro del mismo entorno del proceso.
n hilos en 1 proceso

los hilos comparten


espacio de direcciones,
archivos, etc.

es comparable a

n procesos en 1 CPU

=>Los hilos permiten mltiples ejecuciones en un nico proceso


dentro del mismo entorno del proceso.
n hilos en 1 proceso
es comparable a

los procesos
comparten mem. fsica, disco,
y otros recursos.

n procesos en 1 CPU

Hilos: El modelo de hilos

Hilos: El modelo de hilos

Los hilos alternan su ejecucin de la misma manera que los


procesos
Ejecutando
=> mismo diagrama de estados

Los hilos alternan su ejecucin de la misma manera que los


procesos
Ejecutando
=> mismo diagrama de estados

Bloqueado

Listo

Cul es entonces la diferencia?

Bloqueado

Listo

Cul es entonces la diferencia?

Los hilos comparten

Exclusivo de cada hilo

Los hilos comparten

Exclusivo de cada hilo

Espacio de direccionamiento

Contador de programa

Espacio de direccionamiento

Contador de programa

Variables globales

Registros

Variables globales

Registros

Archivos abiertos

Pila

Archivos abiertos

Pila

Procesos hijos

Estado

Procesos hijos

Estado

Alarmas pendientes

Alarmas pendientes

Seales y manejadores de seales

Seales y manejadores de seales

Informacin administrativa

Informacin administrativa

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = ? }

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = ? }

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 2 }

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

{ x = 2 }

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 2 }

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 }

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

{ x = 1 x = 2}

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 0 }
P 0:
x := x+1;

P 1:
x := x+1;

{ x = ? }

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = ? }

{ x = 0 }
P 0:
x := 1;

{ x = 1 x = 2}

{ x = 0 }

Hilos: El modelo de hilos


Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 1 x = 2}
Estas instrucciones
pueden no realizarse de
manera atmica (indivisible)

{ x = 0 }
MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = ? }

AX = ?
x = 0

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 1 x = 2}

{ x = 0 }

{ x = 0 }

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 0
x = 0

{ x = ? }

MOV AX, x
ADD AX, 1
MOV x, AX

P 0:
x := 1;

MOV AX, x
ADD AX, 1
MOV x, AX

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 0 }
P 0:
x := 1;

{ x = 0 }

{ x = 0 }

{ x = ? }

AX = 1
x = 1

MOV AX, x
ADD AX, 1
MOV x, AX

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 1 x = 2}

MOV AX, x
ADD AX, 1
MOV x, AX

x = 0

Hilos: El modelo de hilos

{ x = 1 x = 2}

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 1

{ x = ? }

Hilos: El modelo de hilos


{ x = 0 }

Esto se denomina
condicin de carrera

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = ? }

El scheduler
cambia de proceso

AX = ?
x = 1

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 1 x = 2}

{ x = 0 }

{ x = 0 }

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 1
x = 1

{ x = ? }

MOV AX, x
ADD AX, 1
MOV x, AX

P 0:
x := 1;

MOV AX, x
ADD AX, 1
MOV x, AX

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 0 }

{ x = 0 }

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = ? }

x = 1

Hilos: El modelo de hilos

{ x = 1 x = 2}

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 2

{ x = ? }

Hilos: El modelo de hilos


{ x = 0 }

Esto se denomina
condicin de carrera

AX = 2
x = 2

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = 2 }

Esto se denomina
condicin de carrera

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 1 x = 2}

{ x = 0 }

{ x = 0 }

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

AX = ?
x = 0

{ x = 2 }

MOV AX, x
ADD AX, 1
MOV x, AX

P 0:
x := 1;

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 0
x = 0

{ x = 2 }

Hilos: El modelo de hilos


{ x = 0 }

Esto se denomina
condicin de carrera

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

{ x = 1 x = 2}

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 1 x = 2}
EL SCHEDULER DECIDE
CAMBIAR DE PROCESO

{ x = 0 }
MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = 2 }

{ x = 0 }
AX = 1
x = 0

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = 2 }

AX = ?
x = 0

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 1 x = 2}

{ x = 0 }

{ x = 0 }

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 0
x = 0

{ x = 2 }

MOV AX, x
ADD AX, 1
MOV x, AX

P 0:
x := 1;

MOV AX, x
ADD AX, 1
MOV x, AX

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 0 }
P 0:
x := 1;

{ x = 0 }

{ x = 0 }

{ x = 2 }

AX = 1
x = 1

MOV AX, x
ADD AX, 1
MOV x, AX

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 1 x = 2}

MOV AX, x
ADD AX, 1
MOV x, AX

x = 0

Hilos: El modelo de hilos

{ x = 1 x = 2}

MOV AX, x
ADD AX, 1
MOV x, AX

AX = 1

{ x = 2 }

Hilos: El modelo de hilos


{ x = 0 }

Esto se denomina
condicin de carrera

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = 2 }

AX = 1
x = 1

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 1;

P 1:
x := 2;

{ x = 1 x = 2}

{ x = 1 x = 2}

{ x = 0 }

{ x = 0 }

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

MOV AX, x
ADD AX, 1
MOV x, AX

Hilos: El modelo de hilos

P 0:
x := 1;

Esto se denomina
condicin de carrera

P 1:
x := 2;

{ x = 1 x = 2}

Conclusin:
el
scheduler es MANDINGA
{ x = 0 }
en persona!!
AX, x
MOV AX, x

MOV
ADD AX, 1
MOV x, AX

ADD AX, 1
MOV x, AX

{ x = 1 x = 2}

MOV AX, x
ADD AX, 1
MOV x, AX

{ x = 1 x = 2}

{ x = 1 }

{ x = 0 }

Esto se denomina
condicin de carrera

Hilos: El modelo de hilos


{ x = 0 }
P 0:
x := 2;
x := x+2;

P 1:
x := 1;
x := x+1;

{ x = ? }

Cul es la postcondicin si
las instrucciones son atmicas?

Y si no lo son?

Queda como
ejercicio

Hilos: El modelo de hilos

Hilos: El modelo de hilos

Por lo tanto: No hay proteccin entre hilos

Es importante tener en cuenta que cada hilo tiene su propia pila

Porque:

Si esto no fuera as entonces estamos en problemas:

1. es imposible, y
2. no debera ser necesario!
Mientras que los procesos son hostiles entre ellos, compitiendo
por recursos,

P 0:
call Foo(x);

P 1:
call Faa(y);

los hilos cooperan entre s para llevar a cabo una tarea comn.
Para lograr una cooperacin adecuada los hilos necesitan
sincronizarse apropiadamente

Pila

Lo posponemos para la
prxima clase

Hilos: El modelo de hilos

Hilos: El modelo de hilos

Es importante tener en cuenta que cada hilo tiene su propia pila

Es importante tener en cuenta que cada hilo tiene su propia pila

Si esto no fuera as entonces estamos en problemas:

Si esto no fuera as entonces estamos en problemas:

P 0:
call Foo(x);

P 0:
call Foo(x);

P 1:
call Faa(y);

1. P0 llama al procedimiento Foo(x)


2. CS durante la ejecucin de Foo

x
dir ret Foo

Pila

* CS = Context Switch

1. P0 llama al
2. CS durante
3. P1 llama al
4. CS durante

P 1:
call Faa(y);

procedimiento Foo(x)
la ejecucin de Foo
procedimiento Faa(y)
la ejecucin de Faa

* CS = Context Switch

y
dir ret Faa
x
dir ret Foo

Pila

Hilos: El modelo de hilos

Hilos: El modelo de hilos

Es importante tener en cuenta que cada hilo tiene su propia pila

Es importante tener en cuenta que cada hilo tiene su propia pila

Si esto no fuera as entonces estamos en problemas:

Si esto no fuera as entonces estamos en problemas:

P 0:
call Foo(x);

P 0:
call Foo(x);

P 1:
call Faa(y);

1. P0 llama al procedimiento Foo(x)


2. CS durante la ejecucin de Foo
3. P1 llama al procedimiento Faa(y)
4. CS durante la ejecucin de Faa
5. El proc. Foo finaliza y retorna

y
dir ret Faa

P 1:
call Faa(y);

La historia de la ejecucin
es local a cada hilo

dir ret Foo

Pila

dir ret Foo

dir ret Faa

Pila P0

Pila P1

Cmo queda la pila ahora?

* CS = Context Switch

Hilos: El modelo de hilos


Operaciones:
thread_create
thread_exit
thread_join
thread_yield

Crea un
nuevo hilo (usualmente con un parmetro)
Habitualmente no hay relacin padre-hijo
Retorna un identificador del nuevo hilo.

Hilos: El modelo de hilos


Problemas:
si un hilo de un proceso con mltiples hilos hace un fork, el
proceso hijo deber tambin tener los mismos mltiples hilos?
si no => no funcionar como el padre

Termina el hilo llamante

Espera hasta que un hilo especfico


(dado como parmetro) termine

Se entrega
voluntariamente al scheduler dando la
posibilidad a otros hilos de ejecutar

si s => qu pasara con los hilos bloqueados a la espera de


una entrada (ej: de teclado o de red)?
Estructuras de datos compartidas. Ej: Qu pasara si un hilo
cierra un archivo mientras otro hilo an lo est leyendo?
Funciones de biblioteca no reentrantes

Hilos: Implementacin en espacio de usuario

Hilos: Implementacin en espacio de usuario

El scheduler no sabe de la existencia de mltiples hilos y maneja


al proceso de la misma manera que si tuviera un slo hilo

Ventajas:

Una biblioteca se encarga de


manipular los hilos:
Tabla de hilos (PC, SP, registros,
estado, etc.)
Sistema en tiempo de ejecucin
(Run-time system)
Si un hilo se bloquea => llama al
run-time syst.
El run-time syst. planifica
entonces un nuevo hilo y se
encarga del cambio de contexto

Hilos: Implementacin en espacio de kernel


Una nica tabla de hilos (en lugar de una por proceso)
Misma informacin que antes pero en espacio de kernel

Se puede implementar en cualquier SO (no necesita soportar hilos)


No necesita de trap al kernel para cambiar de hilo
Context switch de hilos es muy rpido
Problema
Schedulers customizados
Desventajas:

semejante si ocurre un
fallo de pgina

Llamadas bloqueantes: si es una syst. call directa


=> trap al kernel y cambio de proceso: Inaceptable
Usar jackets/wrappers sobre la syst. call:
- hacen uso de la syst. call select
- requiere de reimplementacin de partes de las bibliotecas
Como no hay interrupciones de reloj es imprescindible la entrega
voluntaria del control (thread_yield)

Hilos: Implementacin en espacio de kernel


Una nica tabla de hilos (en lugar de una por proceso)
Misma informacin que antes pero en espacio
de kernel
Implementacin

en espacio de usuario: el runtime system continuar ejecutando hilos


del mismo proceso hasta que se acaben
los hilos disponibles o el kernel
Toda llamada potencialmente
le quite la CPU
bloqueante debe implementarse por

Creacin/terminacin de hilos a
travs de syst. calls al kernel

Creacin/terminacin de hilos a
travs de syst. calls al kernel

Toda llamada potencialmente


bloqueante debe implementarse por
medio de syst. calls al kernel

medio de syst. calls al kernel

Cuando un hilo se bloquea, el kernel


puede elegir si continuar con un hilo
del mismo proceso o de otro

Cuando un hilo se bloquea, el kernel


puede elegir si continuar con un hilo
del mismo proceso o de otro

Las desventajas de antes desaparecen

Las desventajas de antes desaparecen

Pero los costos de los syst. calls son


sustancialmente mayores

Pero los costos de los syst. calls son


sustancialmente mayores

Comunicacin entre procesos

Comunicacin entre procesos

Para qu?

Para qu?

compartir y

compartir y

sincronizar

sincronizar

Tres cosas involucradas:

Ej: Un proc. produce info.


que otro debe imprimir.

Ej: dos puntos de


ventas vendiendo el ltimo
pasaje de avin

Menos obvio

Tres cosas involucradas:

Fcil

Como hacer transferencia de info. entre procesos (o hilos)

Como hacer transferencia de info. entre procesos (o hilos)

Asegurar que los procesos no se molesten cuando realizan


ciertas actividades crticas

Asegurar que los procesos no se molesten cuando realizan


ciertas actividades crticas

Asegurar la secuencialidad apropiada cuando haya


dependencias

Asegurar la secuencialidad apropiada cuando haya


dependencias

Lo que veremos a continuacin asume memoria compartida pero


se aplica tambin a procesos (los procesos tambin pueden
compartir recursos!)

Lo que veremos a continuacin asume memoria compartida pero


se aplica tambin a procesos (los procesos tambin pueden
compartir recursos!)

Comunicacin e/proc.: Condiciones de carrera

Comunicacin e/proc.: Condiciones de carrera

Ej: Spooler de la impresora

Buffer
circular

Ej: Spooler de la impresora

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

8
9

Buffer
circular

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

out = 4

Qu hace esto?
Anda bien?

in = 7

8
9
out = 4

Consideremos la secuencia de planificacin:


A1

B1

B2

A2
Cmo termina
la ejecucin?

in = 7

Comunicacin e/proc.: Condiciones de carrera


Ej: Spooler de la impresora

Buffer
circular

Ej: Spooler de la impresora

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

J4

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

Comunicacin e/proc.: Condiciones de carrera

8
9

Buffer
circular

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

J5

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

8
9

out = 4

Consideremos la secuencia de planificacin:


A1

B1

B2

in = 7

A2

out = 4

Consideremos la secuencia de planificacin:


A1

B1

B2

Cmo termina
la ejecucin?

Cmo termina
la ejecucin?

Comunicacin e/proc.: Condiciones de carrera


Ej: Spooler de la impresora

Buffer
circular

Comunicacin e/proc.: Condiciones de carrera


Ej: Spooler de la impresora

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

J5

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

8
9

Buffer
circular

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

J5

Basura

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

out = 4

Consideremos la secuencia de planificacin:


A1

B1

B2

A2

in = 8

9
out = 4

Consideremos la secuencia de planificacin:


A1

Cmo termina
la ejecucin?

in = 7

A2

B1

B2

A2
Cmo termina
la ejecucin?

in = 9

Comunicacin e/proc.: Condiciones de carrera


Ej: Spooler de la impresora

Buffer
circular

Ej: Spooler de la impresora

struct spl { buf : *job[MAX];


out : int;
in: int;
}

J1

J2

J3

Proc_A:
...
A1: spl->buf[in] = J4;
A2: spl->in ++;
...

J5

Basura

Proc_B:
...
B1: spl->buf[in] = J5;
B2: spl->in ++;
...

Consideremos la secuencia de planificacin:


A1

B1

B2

A2

Comunicacin e/proc.: Condiciones de carrera

Hola.
out = 4
Soy yo, MANDINGA.
Otra in
vez= 9

Comunicacin e/proc.: Regiones crticas

Buffer
circular

struct spl { buf : *job[MAX];


out : int;
in: int;
Una condicin
}

J1

J2

de carrera es una
6
situacin donde dos o ms proceso (o hilos)
Proc_A:
Proc_B:
7
en un rea compartida y el
... deben leer o escribir
...
8
A1: spl->buf[in]
= J4; final
B1: spl->buf[in]
= J5;
resultado
depende de qu
proceso
9
A2: spl->in ++;
B2: spl->in ++;
ejecuta ...
y cundo lo hace
...
Hola.

Consideremos la secuencia de planificacin:Les dije que soy


Debuggear
A1 programas
B1 B2con condiciones
A2
MANDINGA?

J3
J5
Basura

out = 4
in = 9

de carrera es extremadamente frustrante.


Debido al no-determinismo, los test corren bien la
mayora de las veces y los errores son muy
difciles de reproducir.

Ej: la variable compartida,


Comunicacin e/proc.: Regiones
crticas
el spooler de la impresora.

Cmo evitar las condiciones de carrera?

Cmo evitar las condiciones de carrera?

=> Prohibir que ms de un proceso acceda al recurso compartido al


mismo tiempo

=> Prohibir que ms de un proceso acceda al recurso compartido al


mismo tiempo

Es decir: Se necesita exclusin mutua:

Es decir: Se necesita exclusin mutua:

Si un proc. accede al recurso compartido los otros quedan excluidos.

Si un proc. accede al recurso compartido los otros quedan excluidos.

La parte del programa que accede al recurso compartido se denomina


regin crtica.

La parte del programa que accede al recurso compartido se denomina


regin crtica.
Tpicamente analizaremos
programas con esta pinta.
La idea es tratar de
construir el cdigo que
implemente Inicio RC y
Fin RC para asegurar
exclusin mutua de las RCi

P 0:
do true ->
RNC0
Inicio RC0
RC0
Fin RC0
od

P 1:
do true ->
RNC1
Inicio RC1
RC1
Fin RC1
od

Ej: la variable compartida,


Comunicacin e/proc.: Regiones
crticas
el spooler de la impresora.

Cmo evitar las condiciones de carrera?

=> Prohibir !!!???


que ms de un proceso acceda al recurso compartido al
mismo tiempo

1. A lo sumo un proceso est dentro


de la RC

tenga derecho a hacerlo.

2.No hace suposiciones respecto de la


velocidad de la CPU

La parte del programa que accede al recurso compartido se denomina


regin crtica.

La idea es tratar de
construir el cdigo que
implemente Inicio RC y
Fin RC para asegurar
exclusin mutua de las RCi

Para obtener una buena solucin se necesitan las siguientes


cuatro condiciones:

Una solucin obvia es no

Es decir: Se necesita exclusin


mutua:
permitir
a ningn proceso entrar a
la
regin
crtica, olos
queotros
slo quedan
uno
Si un proc. accede al recurso compartido
excluidos.

Tpicamente analizaremos
programas con esta pinta.

Comunicacin e/proc.: Regiones crticas

P 0:
do true ->
RNC0
Inicio RC0
RC0
Fin RC0
od

P 1:
do true ->
RNC1
Inicio RC1
RC1
Fin RC1
od

Comunicacin e/proc.: Regiones crticas

3.Ningn proceso fuera de su RC


puede bloquear el acceso de otro
proceso a su RC
4.Un proceso que desee entrar a su
RC deber hacerlo en algn
momento.

Comunicacin e/proc.: Regiones crticas

Para obtener una buena solucin se necesitan las siguientes


Requerimiento de seguridad
cuatro condiciones:
(safety - nada malo va a pasar)

Para obtener una buena solucin se necesitan las siguientes


Requerimiento de seguridad
cuatro condiciones:
(safety - nada malo va a pasar)

1. A lo sumo un proceso est dentro


de la RC

1. A lo sumo un proceso est dentro


de la RC

2.No hace suposiciones respecto de la


velocidad de la CPU
3.Ningn proceso fuera de su RC
puede bloquear el acceso de otro
proceso a su RC
4.Un proceso que desee entrar a su
RC deber hacerlo en algn
momento.

Ya lo vimos

Requerimiento de progreso
Requerimiento de equidad
(fairness)

Ya lo vimos

2.No hace suposiciones respecto de la


velocidad de la CPU
3.Ningn proceso fuera de su RC
puede bloquear el acceso de otro
proceso a su RC
4.Un proceso que desee entrar a su
RC deber hacerlo en algn
momento.

Requerimiento de progreso
Requerimiento de equidad
(fairness)

Requerimientos de vitalidad
(liveness - algo bueno va a pasar)

Comunicacin e/proc.: Regiones crticas


Para obtener una buena solucin se necesitan las siguientes
Requerimiento de seguridad
cuatro condiciones:
(safety - nada malo va a pasar)
1. A lo sumo un proceso est dentro
de la RC

esto?

Requerimiento de progreso
Requerimiento de equidad
(fairness)

cola de listos del scheduler

Exclusin mutua con espera ocupada (busy waiting)

= STI (set interrupt)

No funciona

= STI (set interrupt)

Funciona?

P 1:
do true ->
RNC1
CLI
RC1
STI
od

Sin interrupciones nadie puede detener al proceso. En particular


no hay interrupciones de reloj (no hay quantum que valga!)
no hay interrupciones de solicitud a disco
Problemas:
Si hay ms de una CPU el mtodo no anda

Requerimientos de vitalidad
(liveness - algo bueno va a pasar)

Esto slo es conveniente para el

Fin RC

Inicio RC = CLI (clear interrupt)

P 0:
do true ->
RNC0
CLI
RC0
STI
od

Qu pasa si un proc. no hace Fin RC? y si quiere hacer E/S?

kernel, Regiones
por ej: durante lacrticas
actualizacin de la
Comunicacin e/proc.:

Inicio RC = CLI (clear interrupt)

Deshabilitar interrupciones:

Ya lo vimos

3.Ningn proceso fuera de su RC


puede bloquear el acceso de otro
proceso a su RC

Deshabilitar interrupciones:

Exclusin mutua con espera ocupada (busy waiting)

Fin RC

2.No hace suposiciones


respecto
de la
Cmo
logramos
velocidad de la CPU

4.Un proceso que desee entrar a su


RC deber hacerlo en algn
momento.

Comunicacin e/proc.: Regiones crticas

P 0:
do true ->
RNC0
CLI
RC0
STI
od

P 1:
do true ->
RNC1
CLI
RC1
STI
od

Sin interrupciones nadie puede detener al proceso. En particular


no hay interrupciones de reloj (no hay quantum que valga!)
Viola equidad,
seguridad (si CPU>1),
no hay interrupciones de solicitud a disco
Problemas:

y tantas otras cosas

Qu pasa si un proc. no hace Fin RC? y si quiere hacer E/S?


Si hay ms de una CPU el mtodo no anda
No permite la ejecucin de las RNC de los otros procesos

No permite la ejecucin de las RNC de los otros procesos

Comunicacin e/proc.: Regiones crticas


Exclusin mutua con espera ocupada (Intento
(busyde)waiting)
solucin
por software

Variable candado:
Init:

lock = 0

Inicio RC:

do (lock == 1) -> skip od


lock = 1

Fin RC:

lock = 0
{ lock == 0 }

P0: do true ->


A1
RNC0
A2
do (lock==1) -> skip od
A3
lock = 1
A4
RC0
A5
lock = 0
od

P1: do true ->


B1
RNC1
B2
do (lock==1) -> skip od
B3
lock = 1
B4
RC1
B5
lock = 0
od

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Exclusin mutua con espera ocupada (busy waiting)

Exclusin mutua con espera ocupada (busy waiting)

Variable candado:

Variable candado:

Init:

lock = 0

Inicio RC:

do (lock == 1) -> skip od


lock = 1

Fin RC:

lock = 0

Funciona?

Init:

lock = 0

Inicio RC:

do (lock == 1) -> skip od


lock = 1

Fin RC:

lock = 0

{ lock == 0 }
P0: do true ->
A1
RNC0
A2
do (lock==1) -> skip od
A3
lock = 1
A4
RC0
A5
lock = 0
od

No funciona
Viola seguridad
(condicin 1)

{ lock == 0 }

P1: do true ->


B1
RNC1
B2
do (lock==1) -> skip od
B3
lock = 1
B4
RC1
B5
lock = 0
od

P0: do true ->


A1
RNC0
A2
do (lock==1) -> skip od
A3
lock = 1
A4
RC0
A5
lock = 0
od

P1: do true ->


B1
RNC1
B2
do (lock==1) -> skip od
B3
lock = 1
B4
RC1
B5
lock = 0
od

Contraejemplo: A1 B1 A2 B2 A3 B3 A4 B4

Usa una variable turn


Comunicacin e/proc.: Regiones
crticas
para alternar los
turnos en que los

procesos
acceden
a la RC
Exclusin mutua con espera ocupada
(busy
waiting)

Alternancia estricta:

procesos
acceden
a la RC
Exclusin mutua con espera ocupada
(busy
waiting)

Alternancia estricta:
Funciona?

Init:

turn = 0

Inicio RC:

do (turn != ID) -> skip od

Fin RC:

Usa una variable turn


Comunicacin e/proc.: Regiones
crticas
para alternar los
turnos en que los

turn = (turn+1)%CANT_PROC
{ turn == 0 }

P0: do true ->


A1
RNC0
A2
do (turn!=0) -> skip od
A3
RC0
A4
turn = (turn + 1) % 2
od

Se puede ver que


garantiza la exclusin
mutua (cond. 1)

P1: do true ->


B1
RNC1
B2
do (turn!=1) -> skip od
B3
RC1
B4
turn = (turn + 1) % 2
od

Funciona?

Init:

turn = 0

Inicio RC:

do (turn != ID) -> skip od

Fin RC:

turn = (turn+1)%CANT_PROC
{ turn == 0 }

P0: do true ->


A1
RNC0
A2
do (turn!=0) -> skip od
A3
RC0
A4
turn = (turn + 1) % 2
od

Consideremos la secuencia:

Se puede ver que


garantiza la exclusin
mutua (cond. 1)

P1: do true ->


B1
RNC1
B2
do (turn!=1) -> skip od
B3
RC1
B4
turn = (turn + 1) % 2
od
Viola progreso
(cond. 3)

A1 A2 A3 A4 A1 A2 A2 A2 B1 (tarda y se acaba el quantum) A2 A2 A2 ...

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Exclusin mutua con espera ocupada (busy waiting)

Exclusin mutua con espera ocupada (busy waiting)

Locks que usan


busy waiting se llaman
spin locks

Alternancia estricta:
Init:

turn = 0

Inicio RC:

do (turn != ID) -> skip od

Fin RC:

turn = (turn+1)%CANT_PROC
{ turn == 0 }

P0: do true ->


Debera evitarse:
A1
RNC0
desperdicia
CPU od
A2
do (turn!=0)
-> skip
A3
RC0
A4
turn = (turn + 1) % 2
od

P1: do true ->


B1
RNC1
B2
do (turn!=1) -> skip od
B3
RC1
B4
turn = (turn + 1) % 2
od

Busy waiting

Algoritmo de Peterson:
En 1959, Edsger W. Dijkstra plante el problema de exclusin mutua en
el Departamento de Computacin del Matematisch Centrum (Amsterdam).
Bsicamente solicitaba las mismas condiciones que planteamos antes.

Los colegas proponan soluciones que Dijkstra demostraba incorrectas


Cada nueva solucin era ms compleja y a Dijkstra le costaba ms
encontrar los contraejemplos
Hasta que Dijkstra se pudri y cambi las reglas: quien trajera una
solucin deba tambin traer la demostracin de su correccin
Theodorus J. Dekker propuso entonces una solucin para 2 procesos
con demostracin y todo
Mezclaba la idea de locks y turno de los algoritmos anteriores

Consideremos la secuencia:

En 1965, Dijkstra la pudo generalizar a N procesos

A1 A2 A3 A4 A1 A2 A2 A2 B1 (tarda y se acaba el quantum) A2 A2 A2 ...

En 1981, G.L. Peterson simplific este algoritmo

Comunicacin e/proc.: Regiones crticas


Exclusin
mutua
con espera
ocupada (busy waiting)
An no existan
las tcnicas
de

clculo de programa o de verificacin!


(R.W.
Floyd introduce
el primer clculo para
Algoritmo
de Peterson:
programas secuenciales en 1967)

En 1959, Edsger W. Dijkstra plante el problema de exclusin mutua en


And then something
profound
el Departamento de Computacin del Matematisch
Centrum
(Amsterdam).

and lovely happened. By analyzing by what


Bsicamente solicitaba las mismas condiciones que planteamos antes.
structure of argument the proof obligations
Los colegas proponan soluciones could
que Dijkstra
demostraba
incorrectas
be met, Dekker
designed
within a few
hours
the
solution
together
Cada nueva solucin era ms compleja y a Dijkstra le costaba with
ms its
correctness argument

encontrar los contraejemplos

Hasta que Dijkstra se pudri y cambi las reglas: quien trajera una
solucin deba tambin traer la demostracin de su correccin
Theodorus J. Dekker propuso entonces una solucin para 2 procesos
con demostracin y todo
Mezclaba la idea de locks y turno de los algoritmos anteriores

En 1965, Dijkstra la pudo generalizar a N procesos


En 1981, G.L. Peterson simplific este algoritmo

turn contiene el nro de proceso

Comunicacin e/proc.: Regiones


crticas
que tiene
prioridad

want[i] indica si el proceso i


Exclusin mutua con espera ocupada
(busy waiting)
quiere ingresar a la RC

Algoritmo de Peterson (para 2 procesos):


Init:

turn = 0; want = [false, false]

Inicio RC:

want[i] = true
turn = 1-i
do (want[1-i] && turn==1-i) -> skip od

Fin RC:

want[i] = false
{ turn == 0

&&

Funciona

want == [false, false] }

P0:
do true ->
RNC0
want[0] = true
turn = 1
do (want[1] && turn==1) -> skip od
RC0
want[0] = false
od

P1:
do true ->
RNC1
want[1] = true
turn = 0
do (want[0] && turn==0) -> skip od
RC1
want[1] = false
od

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Exclusin mutua con espera ocupada (busy waiting)

Exclusin mutua con espera ocupada (busy waiting)

Algoritmo de Peterson (para 2 procesos):

Lgica de Owicki-Gries: provee una


Programas de estado finito
turn = 0; want = [false, false]
Init:
forma de razonar semejante a la lgica de
como este pueden verificarse
want[i] =concurrentes)
true
Inicio
RC: programas
Hoare
(pero para
automticamente (ej: model checking)
turn = 1-i

[OPT: Programacin Concurrente,


do (want[1-i] && turn==1-i) ->[Ingeniera
skip oddel software II]
Blanco&Wolovick]

Fin RC:

want[i] = false
{ turn == 0

&&

want == [false, false] }

P0:
do true ->
RNC0
want[0] = true
turn = 1
do (want[1] && turn==1) -> skip od
RC0
want[0] = false
od

P1:
do true ->
RNC1
want[1] = true
turn = 0
do (want[0] && turn==0) -> skip od
RC1
want[1] = false
od

Comunicacin e/proc.: Regiones crticas


Exclusin mutua con espera ocupada (busy waiting)
Instruccin Test & Set Lock (TSL):

Algoritmo de Peterson:

Ejercicios:
Observar que no sufre de retraso innecesario como el de
alternancia estricta. Mostrar que P0 puede entrar varias veces
aunque P1 no progrese.
El algoritmo es muy delicado: intercambiar las asignaciones en
Inicio RCarruina el algoritmo => dar una ejecucion que lo
muestre
Dar una demostracin de que este algoritmo funciona [Difcil!!]
Generalizar a N procesos

En C sera algo como:


Comunicacin e/proc.: Regiones
crticas
int test_set(int *lock) {

rx;
Exclusin mutua con espera ocupadaregister
(busy int
waiting)

asm(TSL rx, lock);


return( rx );

Instruccin Test & Set Lock (TSL):

La solucin de la variable candado no funciona porque el scheduler


puede interrumpir entre inspeccin y cerrado del candado.

Init:

Si las dos operaciones se realizaran de manera atmica (indivisible)

Fin RC:

lock = 0

Inicio RC: do test_set(&lock) -> skip od


lock = 0

=> S funcionara
Esto requiere de una ayuda del hardware (y van...):
TSL RX, lock
registro

RX ! lock
lock ! 1

memoria
La CPU garantiza que el
scheduler no interrumpe entre medio
de la ejecucin de ambas
instrucciones

Con N procesos
se resuelve de la misma
manera

{ lock == 0 }
P 0:
do true ->
RNC0
do test_set(&lock) -> skip od
RC0
lock = 0
od

P 1:
do true ->
RNC1
do test_set(&lock) -> skip od
RC1
lock = 0
od

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Exclusin mutua con espera ocupada (busy waiting)

Exclusin mutua con espera ocupada (busy waiting)

Instruccin Test & Set Lock (TSL):

Instruccin Test & Set Lock (TSL):

Supongamos que hay dos regiones crticas donde en una se modifica


la tabla de procesos y en la otra los files descriptors:

Supongamos que hay dos regiones crticas donde en una se modifica


la tabla de procesos y en la otra los files descriptors:

{ lock == 0 }

{ lock == 0 }

Qu observan?

P 0:
do true ->
...
do test_set(&lock) -> skip od
p.id = tb_alloc(proc_tb,pcb)
lock = 0
...
do test_set(&lock) -> skip od
fd = tb_get(fd_tb,fid)
lock = 0
...
od

P 1:
do true ->
...
do test_set(&lock) -> skip od
p.id = tb_alloc(proc_tb,pcb)
lock = 0
...
do test_set(&lock) -> skip od
fd = tb_get(fd_tb,fid)
lock = 0
...
od

Bloqueo al cuete!

P 0:
do true ->
...
do test_set(&lock) -> skip od
p.id = tb_alloc(proc_tb,pcb)
lock = 0
...
do test_set(&lock) -> skip od
fd = tb_get(fd_tb,fid)
lock = 0
...
od

P 1:
do true ->
...
do test_set(&lock) -> skip od
p.id = tb_alloc(proc_tb,pcb)
lock = 0
...
do test_set(&lock) -> skip od
fd = tb_get(fd_tb,fid)
lock = 0
...
od

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Exclusin mutua con espera ocupada (busy waiting)

Sincronizacin bloqueante
Tanto Peterson como TSL funcionan correctamente

P 0:
do true ->
...
do test_set(&lock1) -> skip od
p.id = tb_alloc(proc_tb,pcb)
lock1 = 0
...
do test_set(&lock2) -> skip od
fd = tb_get(fd_tb,fid)
lock2 = 0
...
od

P 1:
do true ->
...
do test_set(&lock1) -> skip od
p.id = tb_alloc(proc_tb,pcb)
lock1 = 0
...
do test_set(&lock2) -> skip od
fd = tb_get(fd_tb,fid)
lock2 = 0
...
od

{ lock == 0 }
P 0:
do true ->
A1 RNC0
A2 do test_set(&lock) -> skip od
A3 RC0
A4 lock = 0
od

P 1:
do true ->
B1 RNC1
B2 do test_set(&lock) -> skip od
B3 RC1
B4 lock = 0
od

Consideremos la siguiente secuencia de ejecucin:


A1 A2 A3 B1 B2 B2 B2 B2 A4 A1 A2 A3 B2 B2 B2 B2 B2 A4 A1 A2 A3 B2 B2 B2 B2

Desperdicio de tiempo de CPU

!
"
#

{ lock1 == 0 && lock2 == 0 }

Pero -> busy waiting

!
"
#

Supongamos que hay dos regiones crticas donde en una se modifica


la tabla de procesos y en la otra los files descriptors:

!
"
#

Instruccin Test & Set Lock (TSL):

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Sincronizacin bloqueante

Sincronizacin bloqueante

Tanto Peterson como TSL funcionan correctamente


Pero -> busy waiting

Lo mejor es bloquear el proceso en lugar de desperdiciar CPU:

Ocurre lo mismo en
schedulers no apropiativos y
{ lock == 0 }
suponiendo que P0 realiza E/S en
la ejecucin de la RC
P 1:

P 0:
do true ->
A1 RNC0
A2 do test_set(&lock) -> skip od
A3 RC0
A4 lock = 0
od

do true ->
B1 RNC1
B2 do test_set(&lock) -> skip od
Problema
B3 RC1
de inversin de
B4 lock = 0
prioridades
od

Supongamos que el scheduler considera prioridades: Que pasa?


Supongamos que P1 tiene ms prioridad que P0:

!!!!!

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

sleep(queue)

-> duerme al proceso encolndolo en queue

wakeup(queue) -> despierta un proceso en la cola queue


(lo pasa de bloqueado a listo)
Recodemos el ejemplo del spooler de la impresora:
Que pasa cuando el buffer se llena? y cuando se vaca?

Problema abstracto: Productores y Consumidores


Hay productores y consumidores de datos transferidos a travs de
un buffer de tamao N

Peor => inanicin y deadlock:

A1 A2 A3 B1 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 B2 .....

Se proponen dos tipos de primitivas nuevas:

Si el buffer se llena, los productores deben esperar para producir


Si el buffer se vaca, los consumidores deben esperar para consumir

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }

Funciona?

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Comienza ejecutando el consumidor

Funciona?

count = 0
qp = []
qc = []

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = 0
qp = []
qc = []

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = 0
qp = []
qc = []

El consumidor excede su tiempo


Contina ejecutando el productor

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El consumidor excede su tiempo


Contina ejecutando el productor

insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

{ count == 0 && empty(qp) && empty(qc) }

El consumidor excede su tiempo


Contina ejecutando el productor

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }

Funciona?

count = 0
qp = []
qc = []

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El consumidor excede su tiempo


Contina ejecutando el productor

Funciona?

count = 0
qp = []
qc = []

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = 1
qp = []
qc = []

count: cant. datos en el buffer

insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Contina ejecutando el productor

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = 1
qp = []
qc = []

El consumidor excede su tiempo


Contina ejecutando el productor

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para

El consumidor an
El consumidor excede su tiempo
no est encolado!

insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

{ count == 0 && empty(qp) && empty(qc) }

El consumidor excede su tiempo


Contina ejecutando el productor

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }

Funciona?

count = 1
qp = []
qc = []

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El productor excede su tiempo


Contina ejecutando el consumidor

Funciona?

count = 1
qp = []
qc = []

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = 1
qp = []
qc = [Cons]

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = 2
qp = []
qc = [Cons]

El consumidor se bloquea
Contina ejecutando el productor

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El consumidor se bloquea
Contina ejecutando el productor

insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

{ count == 0 && empty(qp) && empty(qc) }

El consumidor se bloquea
Contina ejecutando el productor

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }

Funciona?

count = ...
qp = []
qc = [Cons]

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El consumidor se bloquea
Contina ejecutando el productor

Funciona?

count = N
qp = []
qc = [Cons]

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = N
qp = []
qc = [Cons]

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

Funciona?

count = N
qp = []
qc = [Cons]

El consumidor se bloquea
Contina ejecutando el productor

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El consumidor se bloquea
Contina ejecutando el productor

insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

{ count == 0 && empty(qp) && empty(qc) }

El consumidor se bloquea
Contina ejecutando el productor

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }

Funciona?

count = N
qp = []
qc = [Cons]

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

El productor se bloquea
=> Deadlock!

No funciona

count = N
qp = [Prod]
qc = [Cons]

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

count: cant. datos en el buffer

Comunicacin e/proc.: Regiones


b: buffercrticas
con instrucciones para
insertar (buf_insert) y quitar

Sincronizacin bloqueante
(buf_remove) datos

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
consumidores, respect.

{ count == 0 && empty(qp) && empty(qc) }


Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

No funciona

count = N
qp = [Prod]
qc = [Cons]

Comunicacin e/proc.: Regiones crticas

Operaciones (sem es la variable):

V(sem) :

Productor:
do true ->
d = produce_item()
if (count == N)
-> sleep(qp) fi
buf_insert(b,d)
count = count + 1
if (count == 1)
-> wakeup(qc) fi
od

Tratemos de enternder
por qu surge el problema

si sem ! 1 => decrementa sem


si sem = 0 => se bloquea

Consumidor:
do true ->
if (count == 0)
-> sleep(qc) fi
d = buf_remove(b)
if (count = N-1)
-> wakeup(qp) fi
count = count - 1
consume_item(d)
od

No funciona

count = N
qp = [Prod]
qc = [Cons]

Este modelo de sleep/wakeup no se


acord que ya haba hecho un wakeup.
En general, no cuenta la cantidad de wakeup hechos

Comunicacin e/proc.: Regiones crticas


Semforos

La variable cuenta cuantos wakeups se efectuaron

{
{

consumidores, respect.

[Dijkstra 1965]

Es un tipo abstracto de datos que consta de una variable entera y


dos operaciones.

P(sem) :

qp, qc: colas donde se

Implementacin para un productor y un consumidor


duermen los productores y
{ count == 0 && empty(qp) && empty(qc) }

Se podra arreglar pero:


esa solucin valdra para mltiples productores y consumidores?
An as existen posibles condiciones de carreras en el uso del
buffer sin solucionar.

Semforos

Sincronizacin bloqueante
(buf_remove) datos

Solucin de Productores/Consumidores con 3 semforos:


full

-> cuenta la cantidad de lugares ocupados en el buffer

empty -> cuenta la cantidad de lugares vacos del buffer


A veces se
bloquea

si hay procesos bloqueados => desbloquea uno


si no => incrementa sem

Nunca se
bloquea
P es por probeer te verlagen (intentar decrementar)
y V es por verhogen (incrementar)

mutex -> asegura la exclusin mutua del buffer


{ full == 0 && empty == N && mutex == 1 }
Productor:
do true ->
d = produce_item()
P(empty)
P(mutex)
buf_insert(b,d)
V(mutex)
V(full)
od

Consumidor:
do true ->
P(full)
P(mutex)
d = buf_remove(b)
V(mutex)
V(empty)
consume_item(d)
od

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Semforos

Semforos

En particular, mutex es
un semforo que slo manipula dos
estados:
o desbloqueado. Este
Solucin de Productores/Consumidores
conbloqueado
3 semforos:
tipo de semforos se denomina
full -> cuenta la cantidad de lugares
ocupados en el buffer
semforo binario o mutex.

empty -> cuenta la cantidad de lugares vacos del buffer


mutex -> asegura la exclusin mutua del buffer
{ full == 0 && empty == N && mutex == 1 }
Productor:
do true ->
d = produce_item()
P(empty)
P(mutex)
buf_insert(b,d)
V(mutex)
V(full)
od

Consumidor:
do true ->
P(full)
P(mutex)
d = buf_remove(b)
V(mutex)
V(empty)
consume_item(d)
od

Comunicacin e/proc.:ParaRegiones
crticas
mltiples core usar TSL o XCHG.

Solo funciona
en mquinas de una
sola CPU

Implementacin de semforos en kernel


Consideramos dadas las dos llamadas al sistema sleep y wakeup
typedef struct {
int count;
queue q;
// cola de hilos del semforo
} Semaphore;
void P(Semaphore s) {
Deshab. interrup.
if (s->count > 0) {
s->count --;
Hab. interrup.
} else {
Add(s->q, current_thread);
Hab. interrup.
sleep();
}
}

Comunicacin e/proc.: Regiones crticas

Semforos
No queda otra que busy waiting, pero notar
que es muy localizado.

Implementacin de semforos en kernel


Consideramos dadas las dos llamadas al sistema sleep y wakeup
typedef struct {
int count;
queue q;
// cola de hilos del semforo
} Semaphore;
void P(Semaphore s) {
Deshab. interrup.
if (s->count > 0) {
s->count --;
Hab. interrup.
} else {
Add(s->q, current_thread);
Hab. interrup.
sleep();
}
}

Opiniones?

void V(Semaphore s) {
Deshab. interrup.
if (isEmpty(s->q)) {
s->count ++;
} else {
thread = RemoveFirst(s->q);
wakeup(thread);
}
Hab. interrup.
}

void V(Semaphore s) {
Deshab. interrup.
if (isEmpty(s->q)) {
s->count ++;
} else {
thread = RemoveFirst(s->q);
wakeup(thread);
}
Hab. interrup.
}

Semforos
Implementacin de mutexes en espacio de usuario.
Mucho ms eficiente
mutex_lock:
TSL RX, mutex
CMP RX, #0
JZE ok
CALL thread_yield
JMP mutex_lock
ok: RET

|
|
|
|
|
|

mutex_unlock:
MOVE mutex, #0
RET

| guardar 0 en mutex
| retornar

copiar mutex a registro y setear mutex en 1


mutex era 0?
si era 0, mutex estaba libre => return
si no, mutex est ocupada => ceder la CPU
intentar otra vez
retornar; ingreso a la regin crtica

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Monitores

Monitores

{ full == 0 && empty == N && mutex == 1 }


Productor:
do true ->
d = produce_item()
P(empty)
P(mutex)
buf_insert(b,d)
V(mutex)
V(full)
od

Consumidor:
do true ->
P(mutex)
P(full)
d = buf_remove(b)
V(mutex)
V(empty)
consume_item(d)
od

{ full == 0 && empty == N && mutex == 1 }

Funciona?

Productor:
do true ->
d = produce_item()
P(empty)
P(mutex)
buf_insert(b,d)
V(mutex)
V(full)
od

Consumidor:
do true ->
P(mutex)
P(full)
d = buf_remove(b)
V(mutex)
V(empty)
consume_item(d)
od

No funciona

Deadlock!

Los semforos son (an) primitivas de bajo nivel


Errores sutiles pueden producir deadlocks o condiciones de carrera
Ej: Olvidarse un V, disponer las primitivas en orden incorrecto,...

Comunicacin e/proc.: Regiones crticas

Comunicacin e/proc.: Regiones crticas

Monitores

Monitores

Se necesitan construcciones de alto nivel que brinden una buena


abstraccin a estos mtodos de sincronizacin:
Monitores

[Hoare 74, Brinch Hansen 75]

Coleccin de procedimientos (y funciones), variables y estructura de


datos agrupados en un mdulo con una forma especial de
sincronizacin
=> TAD sincronizado
Los procesos pueden llamar a los procedimientos del monitor cuando
lo deseen
Pero no pueden acceder directamente a las estructura de datos y
variables internas del monitor

Muy importante

Slo un proceso puede estar activo en el monitor a cada instante

Productores/Consumidores:
monitor syncBuff
int count = 0
buffer b = []
condvar full, empty
procedure insert(d:Data){
if count == N -> wait(full) fi
buf_insert(b,d)
count = count + 1
if count == 1 -> signal(empty) fi
}
function remove() data {
if count == 0 -> wait(empty) fi
result = buf_remove(b)
count = count - 1
if count == N-1 -> signal(full) fi
return(result)
}
end monitor

Productor:
do true ->
d = produce_item()
syncBuff.insert(d)
od
Consumidor:
do true ->
d = syncBuff.remove(b)
consume_item(d)
od

Comunicacin e/proc.: Regiones crticas


Monitores

Variables
Productores/Consumidores: de condicin:
definen una cola de
monitor syncBuff
procesos
int count = 0
buffer b = []
condvar full, empty

procedure insert(d:Data){
if count == N -> wait(full) fi
buf_insert(b,d)
count = count + 1
if count == 1 -> signal(empty) fi
}
function remove() data {
if count == 0 -> wait(empty) fi
result = buf_remove(b)
count = count - 1
if count == N-1 -> signal(full) fi
return(result)
}
end monitor

Todos los
procedimientos y funciones se
ejecutan en exclusin mutua
Levanta la exclusin
mutua y duetme al proceso
encolndolo en full

Despierta a un
proceso encolado en full
(si es que hay)

Varias polticas para signal:


despierta y continua ejecutando
despierta y espera [Hoare]
despierta y termina [Brinch Hansen]

Otros modos de sincronizacin


Sin memoria compartida
No existen condiciones de carrera

Sincroniza mltiples procesos

int count = 0
buffer b = []
condvar full, empty

procedure insert(d:Data){
if count == N -> wait(full) fi
buf_insert(b,d)
count = count + 1
Las implementaciones
if count == 1 -> signal(empty) fi
existentes (como en Java), no
}
function remove() data {
aqu explicadas
if count == 0 -> wait(empty) fi
result = buf_remove(b)
count = count - 1
if count == N-1 -> signal(full) fi
return(result)
}
end monitor

Lo van a ver en Redes y


Sistemas Distribuidos y en
Ingeniera del Software II

Todos los
procedimientos y funciones se
ejecutan en exclusin mutua
Levanta la exclusin
mutua y duetme al proceso
encolndolo en full

Despierta a un
proceso encolado en full
(si es que hay)
Atencin!
La correccin depende
de esta poltica
Varias polticas para signal:
despierta y continua ejecutando
despierta y espera [Hoare]
despierta y termina [Brinch Hansen]

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Usualmente para comunicar distintas mquinas

Barreras

Monitores

Variables
Productores/Consumidores: de condicin:
definen una cola de
monitor syncBuff
procesos

responden exactamente a las

Comunicacin e/proc.: Regiones crticas


Pasaje de mensajes

Comunicacin e/proc.: Regiones crticas

La actividad de un filsofo es:


Fili:
do true ->
pensar
comer
od

Para comer debe


tener los dos tenedores
que estn a su lado

Los tenedores son


recursos compartidos. Hay que
administrarlos apropiadamente

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Fili:
do true ->
pensar
tomar_tenedor(i)
tomar_tenedor((i+1)%5)
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Fili:
do true ->
pensar
tomar_tenedor(i)
tomar_tenedor((i+1)%5)
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Funciona?

No funciona

Deadlock!

Comunicacin e/proc.: Problemas clsicos

Comunicacin e/proc.: Problemas clsicos

Los filsofos comensales [Dijkstra 1965]

Los filsofos comensales [Dijkstra 1965]

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Comunicacin e/proc.: Problemas clsicos

Comunicacin e/proc.: Problemas clsicos

Los filsofos comensales [Dijkstra 1965]

Los filsofos comensales [Dijkstra 1965]

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Comunicacin e/proc.: Problemas clsicos

Comunicacin e/proc.: Problemas clsicos

Los filsofos comensales [Dijkstra 1965]

Los filsofos comensales [Dijkstra 1965]

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Comunicacin e/proc.: Problemas clsicos

Comunicacin e/proc.: Problemas clsicos

Los filsofos comensales [Dijkstra 1965]

Los filsofos comensales [Dijkstra 1965]

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
Funciona?
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Fili:
do true ->
pensar
done = false
do !done ->
tomar_tenedor(i)
if tenedor_disponible (i)
then
tomar_tenedor((i+1)%5)
done = true
else
dejar_tenedor(i)
fi
od
No funciona
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
od

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

etc.

Inanicin!

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Para sentarse a comer, el


filsofo debe primero agarrar
una de las sillas disponibles

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Funciona

Cmo se implementa?

Cuando termina de
comer, libera la silla y
vuelve a pensar

Comunicacin e/proc.: Problemas clsicos


Los filsofos comensales [Dijkstra 1965]

Comunicacin e/proc.: Problemas clsicos


Lectores y escritores
Modela el acceso a un recurso de lectura escritura como por
ejemplo una base de datos.

{ sillas == 4 }
Fili:
do true ->
pensar
P(sillas)
tomar_tenedor(i)
tomar_tenedor((i+1)%5)
comer
dejar_tenedor(i)
dejar_tenedor((i+1)%5)
V(sillas)
od

Existen otras soluciones:


Investiguen

Ej: Sistema de reservas de una lnea aerea o de mnibus, una red


bancaria, ...
Hay varias terminales consultando/modificando/agregando
Esto puede traer problemas
Solucin? => lock en la Base de Datos
Parece exagerado:
La lectura puede hacerse simultaneamente por mltiples entidades
El problema real como consecuencia de la condicin de carrera se
da durante la escritura
Por qu?

Comunicacin e/proc.: Problemas clsicos


Lectores y escritores

Es decir, a la RC

Supongamos que
r cuenta la cant. de lectores accediendo a la BD a la vez, y
w cuenta la cant. de escritores accediendo a la BD a la vez
Qu es lo que necesitamos que funcione?
(w " 1) ((w = 1)
Nunca puede
acceder ms de un escritor
a la vez

Invariante de
seguridad

(r = 0))

Si un escritor est
accediendo, ningn lector puede estar
leyendo

Otras formas del invariante:

Comunicacin e/proc.: Problemas clsicos


Lectores y escritores
Implementacin:

!
"
#

{ sem_w == 1 && cant_r == 0 && mutex == 1 }


Escritor:
do true ->
P(sem_w)
// Escribir
V(sem_w)
od

Problema de equidad
(fairness) si hay un flujo
continuo de lectores

((w = 1) (r = 0)) (w = 0)
(w " 1) ((w = 0) (r = 0))

Comunicacin e/proc.: Problemas clsicos


El peluquero dormiln

sem_w: semforo de escritura


cant_r: contador de lectores accediendo a la BD
mutex: mutex para modificar cant_r

Lector:
do true ->
P(mutex)
cant_r ++
if (cant_r == 1) -> P(sem_w)
V(mutex)
// Leer
P(mutex)
cant_r -if (cant_r == 0) -> V(sem_w)
V(mutex)
od

Comunicacin e/proc.: Problemas clsicos


El bao unisex

Hay una peluquera con una cantidad acotada de sillas

(O su versin aburrida: puente de una sola va)

Si no hay clientes, el peluquero duerme

Existen dos tipos de procesos: hombres y mujeres

Los clientes llegan a la peluquera:

El bao puede ser utilizado por cualquiera si est vaco

Si el peluquero est durmiendo lo despiertan


Si est atendiendo esperan sentados en una silla
Pero si no hay silla libre, se van
Se debe modelar al peluquero y a los clientes.
Tipico problema de colas en redes de computadoras

Investiguen

El bao no puede ser utilizado por hombres si hay mujeres


dentro
Viceversa: el bao no puede ser utilizado por mujeres si hay
hombres dentro
Problema de fairness si hay flujo constante de mujeres (u
hombres)

Investiguen

S-ar putea să vă placă și