Taller de Programación Paralela - Universidad de Santiago de Chile

Anuncio
Taller de Programación Paralela
Fernando R. Rannou
Departamento de Ingenierı́a Informática
Universidad de Santiago de Chile
April 26, 2007
Concurrencia
Concurrencia y sincronización . . . . . . . . . . . .
Beneficios de concurrencia . . . . . . . . . . . . . .
Ejemplo de problema . . . . . . . . . . . . . . . . .
Definición de términos. . . . . . . . . . . . . . . . .
Modelo de concurrencia. . . . . . . . . . . . . . . .
Requerimientos para una solución . . . . . . . . .
Soluciones por hardware 1 . . . . . . . . . . . . . .
Soluciones por hardware 2, testset() . . . . . . .
EM por instrucciones de máquina . . . . . . . . .
Soluciones por software 1 . . . . . . . . . . . . . .
Solución de Peterson. . . . . . . . . . . . . . . . . .
Semáforos . . . . . . . . . . . . . . . . . . . . . . . . .
Primitivas sobre semáforos . . . . . . . . . . . . . .
Semáforo binario o mutex . . . . . . . . . . . . . .
EM usando semáforos . . . . . . . . . . . . . . . . .
El problema del productor/consumidor. . . . . .
Solución productor/consumidor con semáforos
Sincronización con hebras POSIX . . . . . . . . .
Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . .
Variables de condición . . . . . . . . . . . . . . . . .
Productor/consumidor usando pthreads . . . . .
El Productor . . . . . . . . . . . . . . . . . . . . . . .
El Consumidor . . . . . . . . . . . . . . . . . . . . . .
Barreras para hebras . . . . . . . . . . . . . . . . . .
Implementación barreras con pthreads . . . . . .
Inicialización de barrera . . . . . . . . . . . . . . . .
Espera con barreras . . . . . . . . . . . . . . . . . .
Uso de barreras . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Concurrencia
2 / 30
Concurrencia y sincronización
■
Cuando dos o má tareas (procesos o hebras) comparten algún recurso en forma concurrente o paralela, debe existir
un mecanismo que sincronice sus actividades
■
El riesgo: corrupción del recurso compartido
■
Ejemplos:
1. Acceso a impresora en un sistema distribuido
2. Consulta y actualización de una base de datos
3. Ejecuci’on paralela de tareas para resolver un problema en conjunto
■
Los problemas de sincronización no sólo ocurren en sistemas multiprocesadores, sino también (y
fundamentalmente) en monoprocesadores
Fernando R. Rannou
Diinf-USACH
3 / 30
Beneficios de concurrencia
■
Aumento en el rendimiento mediante múltiples procesadores
u Paralelsimo
■
Aumento del throughput de las aplicaciones
u Un llamado a una operación de I/O sólo bloquea una hebra
■
Mejora en interactividad de las aplicaciones
u Asignar mayor prioridad a hebras que atiendan al usuario
■
Mejora en la estructuración de aplicaciones
■
Sistemas distribuidos
Fernando R. Rannou
Diinf-USACH
4 / 30
2
* de problema
Ejemplo
■
Considere dos procesos que ejecutan concurrentemente a la funcion echo() del SO:
void echo()
{
chin = getchar();
chout = chin;
putchar(chout);
}
■
*
Asuma que chin es variable compartida
Proceso 1
.
chin = getchar();
<- interrupcion
Proceso 2
.
chin = getchar();
chout = chin;
<- interrupcion
chout = chin;
putchar(chout);
putchar(chout);
■
Solución: permitir que sólo un proceso ejecute echo() a la vez
Fernando R. Rannou
Diinf-USACH
5 / 30
Definición de términos
■
Una sección crı́tica (SC) es una sección de código de un proceso o hebra que accesa recursos compartidos, la cual
(la sección) no puede ser ejecutada mientras otro proceso está ejecutando su SC correspondiente
■
Por ejemplo, echo() en el ejemplo anterior es SC.
■
Exclusión mútua es el requerimiento que cuando un proceso está en una SC que accesa ciertos recursos
compartidos, ningún otro proceso puede estar ejecutando su correspondiente SC en la cual accesa alguno de
dichos recursos
■
Deadlock ocurre cuando dos o más procesos no pueden progresar porque cada uno está esperando que otro
proceso realize alguna acción
■
Inhanición es cuando un proceso en estado de listo, nunca es planificado en el procesador.
Fernando R. Rannou
Diinf-USACH
6 / 30
3
Modelo de concurrencia
■
*
Asumimos una colección de procesos del tipo
Process(i) {
while (true) {
codigo no critico
...
enterSC();
SC();
exitSC();
..
codigo no critico
}
}
■
enterSC() representa las acciones que el proceso debe realizar para poder entrar a su SC
■
exitSC() representa las acciones que el proceso debe realizar para salir la SC y dejarla habilitada a otros procesos
■
El código no crı́tico es cualquier código que el proceso ejecuta que no accede recursos compartidos
Fernando R. Rannou
Diinf-USACH
7 / 30
Requerimientos para una solución
■
El objetivo es proveer menanismos que implementen enterSC() y exitSC() que satisfagan los siguientes 3
requerimientos
1. Exclusión mútua: Cuando Pi está en su SC, ningún otro proceso Pj está en su correspondiente SC. Esto
significa que la ejecución de operaciones de las secciones crı́ticas no son concurrentes
2. Sin deadlock: Deadlock ocurrirı́a cuando todos los procesos quedan ejecutando enterSC() indefinidamente,
y por lo tanto, ninguno entra y ninguno progresa
3. Sin inhanición: Se debe garantizar que un proceso Pi que ejecuta enterSC(), eventualmente lo haga
■
Notas
u Un proceso puede tener más de un SC
u Libre de deadlock no garantiza que algún proceso se bloquee indefinidamente
u Libre de inhanición no dice cuando un proceso entra a la SC
u La solución no debe realizar suposiciones sobre la velocidad relativa y orden de ejecución de los procesos
Fernando R. Rannou
Diinf-USACH
8 / 30
4
Soluciones por hardware 1
■
Deshabilitación de interrupciones Recordar que un proceso se ejecuta hasta que invoca un llamado al SO o es
interrumpido. Entonces para garantizar EM, el proceso deshabilita las interrupciones justo antes de entrar en su SC
while (true)
{
deshabilitar_interrupciones();
SC();
habilitar_interrupciones();
}
■
Habilidad del procesador para hacer context-switch queda limitada
■
No sirve para multiprocesadores
Fernando R. Rannou
Diinf-USACH
9 / 30
Soluciones por hardware 2, testset()
■
Uso de instrucciones especiales de máquina que realizan en forma atómica más de una operación.
■
Por ejemplo testset()
boolean testset(var int i) {
if (i == 0) {
i = 1;
return true;
} else return false;
}
int bolts;
P(i) {
while (true) {
codigo no critico
while (!testset(bolt));
SC();
bolt = 0;
codigo no critico
}
}
void main() {
bolt = 0;
parbegin(P(1), P(2), ..., P(n));
}
Fernando R. Rannou
Diinf-USACH
10 / 30
5
EM por instrucciones de máquina
■
Ventajas
u Aplicable a cualquier número de procesos y procesadores que comparten memoria fı́sica
u Simple y fácil de verificar
u Puede ser usada con varias SC, cada una controlada por su propia variable
■
Desventajas
u Busy-waiting (o spin-lock) consume tiempo de procesador
u Es posible inhanición
Fernando R. Rannou
Diinf-USACH
11 / 30
Soluciones por software 1
■
Dos procesos comparten la variable turno
int turno;
P(i) {
while (true) {
codigo no critico
while (turno != 0);
SC();
turno = 1;
codigo no critico
}
}
P(i) {
while (true) {
codigo no critico
while (turno != 1);
SC();
turno = 0;
codigo no critico
}
}
void main() {
turno = 0;
parbegin(P(0), P(1));
}
■
Garantiza exclusión mútua
■
Sólo aplicable a dos procesos
■
Alternación estricta de ejecución
Fernando R. Rannou
Diinf-USACH
12 / 30
6
Solución de Peterson
■
Dos procesos comparten dos variable: flag[2] y turno
boolean flag[2];
int turno;
P(i) {
while (true) {
codigo no critico
flag[0] = true;
turno = 1;
while (flag[1] && turno == 1);
SC();
flag[0] = false;
codigo no critico
}
}
void main(){
flag[0] = flag[1] = false;
parbegin(P(0), P(1));
}
P(i) {
while (true) {
codigo no critico
flag[1] = true;
turno = 0;
while (flag[0] && turno == 0);
SC();
flag[1] = false;
codigo no critico
}
}
Fernando R. Rannou
Diinf-USACH
13 / 30
Semáforos
■
Una semáforo es una variable especial usada para que dos o más procesos se señalicen mútuamente
■
Un semáforo es una variable entera, pero
■
Accesada sólo por dos operaciones
1. wait(s) decrementa el semáforo; si el valor resultante es negativo, el proceso se bloquea; sino, continúa su
ejecución
2. signal(s) incrementa el semáforo; si el valor resultante es menor o igual que cero, entonces se despierta un
proceso que fue bloqueado por wait()
■
Inicializada con un nḿero no negativo
Fernando R. Rannou
Diinf-USACH
14 / 30
7
Primitivas sobre semáforos
struct semaphore {
int count;
queueType queue;
}
void wait(semaphore s)
{
s.count--;
if (s.count < 0) {
place this process in s.queue;
block this process
}
}
void signal(semaphore s)
{
s.count++;
if (s.count <= 0) {
remove a process P from s.queue;
place process P on ready state
}
}
Fernando R. Rannou
Diinf-USACH
15 / 30
Semáforo binario o mutex
■
Un semáforo binario sólo puede tomar los valores 0 o 1
wait(s)
{
if (s.value == 1)
s.value = 0;
else {
place this process in s.queue
block this process
}
}
signal(s)
{
if (s.queue is empty())
s.value = 1
else {
remove a process P from
s.queue;
place P on the ready list;
}
}
Fernando R. Rannou
Diinf-USACH
16 / 30
8
EM usando semáforos
semaphore s;
Process(i) {
while (true) {
codigo no critico
...
wait(s)
SC();
signal(s);
..
codigo no critico
}
}
void main() {
s = 1;
parbegin(P(1), P(2),...,P(n));
}
Fernando R. Rannou
Diinf-USACH
17 / 30
El problema del productor/consumidor
■
Uno o más procesos productores generan datos y los almacenan en un buffer compartido
■
Un proceso consumidor toma (consume) los datos del buffer uno a la vez
■
Claramente, sólo un agente (productor o consumidor) pueden accesar el buffer a la vez
producer() {
while (true) {
v = produce();
while ((in + 1) % n == out);
/* do nothing */
b[in] = v;
in = (in + 1) % n
}
}
consumer() {
while (true) {
while (in == out);
/* do nothing */
w = b[out];
out = (out + 1) % n;
consume(w);
}
■
El buffer es de largo n y tratado circularmente
■
in indica la siguiente posición libre y out el siguiente elemento a consumir
Fernando R. Rannou
Diinf-USACH
18 / 30
9
Solución productor/consumidor con semáforos
const int
semaphore
semaphore
semaphore
sizeofbuffer;
s = 1;
full = 0;
empty = sizeofbuffer;
producer()
{
while(true) {
v = produce();
wait(empty);
wait(s);
put_in_buffer(v);
signal(s);
signal(full);
}
}
consumer()
{
while(true) {
wait(full);
wait(s);
w = take_from_buffer();
signal(s);
signal(empty);
consume(w);
}
}
Fernando R. Rannou
Diinf-USACH
19 / 30
Sincronización con hebras POSIX
■
Hebras POSIX definen funciones para la sincronización de hebras
1. mutexes: parecidos a los semáforos binarios y sirven para proveer exclusión mútua a cualquier número de
hebras de un proceso
2. variables de condición: un mecanismo asociado a los mutexes. Permiten que una hebra se bloquee y libere la
SC en la que se encuentra
■
Estos mecanismos no sirven para sincronizar hebras de distintos procesos
Fernando R. Rannou
Diinf-USACH
20 / 30
10
Mutex
■
Un
* mutex es la forma más básica de sincronización y provee el mismo servicio que un semáforo binario
■
Generalmente se utilizan para implementar acceso exclusivo a SC de las hebras
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_destroy(pthread_mutex_t *mutex);
■
Si una hebra invoca pthread_mutex_lock(m) y el mutex m ya está tomado, entonces la hebra se bloquea (en ese
mutex), sino toma (cierra) el mutex y continúa su ejecución
■
Si una hebra invoca pthread_try_lock(m) y el mutex m ya está tomado, entonces pthread_try_lock(m)
retorna un código de error EBUSY; la hebra no se bloquea y puede continuar su ejecución (fuera de la SC)
Fernando R. Rannou
Diinf-USACH
21 / 30
Variables de condición
■
¿ Qué sucederı́a si una hebra se bloquea dentro de una SC?
■
Una variable de condición permite que una hebra se bloquee dentro de una SC y al mismo tiempo libere la sección
crı́tica
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t * mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t * attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
■
La hebra que invoca pthread_cond_wait(c, m) se bloquea hasta que la condición c se señalice; además libera el
mutex m
■
pthread_cond_signal(c) señaliza o despierta alguna otra hebra que está bloqueada en la variable de condición c
■
pthread_cond_broadcast(c) desbloquea todas las hebras esperando en c
Fernando R. Rannou
Diinf-USACH
22 / 30
11
Productor/consumidor usando pthreads
typedef struct {
int buf[QUEUESIZE];
int head, tail;
int full, empty;
pthread_mutex_t mutex;
pthread_cond_t notFull, notEmpty;
} buffer_t;
void main()
{
buffer_t *buffer;
pthread_t pro, con;
buffer = bufferInit();
pthread_mutex_init(&buffer->mutex, NULL);
pthread_cond_init(&buffer->notFull, NULL);
pthread_cond_init(&buffer->notEmpty, NULL);
pthread_create(&pro, NULL, producer, (void *) buffer);
pthread_create(&con, NULL, consumer, (void *) buffer);
pthread_join (pro, NULL);
pthread_join (con, NULL);
exit 0;
}
Fernando R. Rannou
Diinf-USACH
23 / 30
El Productor
void *producer(void *arg)
{
int v;
buffer_t *buffer;
buffer = (buffer_t *) arg;
while (true) {
v = produce();
pthread_mutex_lock (&buffer->mutex);
while (buffer->full) {
pthread_cond_wait (&buffer->notFull, &buffer->mutex);
}
put_in_buffer(buffer, v);
pthread_cond_signal(&buffer->notEmpty);
pthread_mutex_unlock(&buffer->mutex);
}
}
Fernando R. Rannou
Diinf-USACH
24 / 30
12
El Consumidor
void *consumer (void *arg)
{
int v;
buffer_t *buffer;
buffer = (buffer_t *) arg;
while (true) {
pthread_mutex_lock (&buffer->mutex);
while (buffer->empty) {
pthread_cond_wait (&buffer->notEmpty, &buffer->mutex);
}
v = take_from_buffer(buffer);
pthread_cond_signal(&buffer->notFull);
pthread_mutex_unlock(&buffer->mutex);
}
}
Fernando R. Rannou
Diinf-USACH
25 / 30
Barreras para hebras
■
Una barrera es un mecanismo de sincronización detener (bloquear) la ejecución de un grupo de hebras en un
mismo punto del programa
■
Cuando la barrera está a bajo las hebras se detienen en ella en el orden en que llegan
■
Cuando la barrera se levanta, las hebras continúan su ejecución
■
Las barreras son útiles para implementar puntos de sincronización globales en un algoritmo
■
Usamos mutex y variables de condición para implementar barreras
■
Implementamos las siguientes funciones
1. barrier_init()
2. barrier_wait()
3. barrier_destroy()
Fernando R. Rannou
Diinf-USACH
26 / 30
13
Implementación barreras con pthreads
■
Una posible forma de implementación es usando dos mutexes y dos variables de condición
■
Cada par representa una barrera
struct _sb {
pthread_cond_t cond;
pthread_mutex_t mutex;
int runners;
};
typedef struct {
int maxcnt;
struct _sb sb[2];
struct _sb *sbp;
} barrier_t;
Fernando R. Rannou
Diinf-USACH
27 / 30
Inicialización de barrera
int barrier_init(barrier_t *bp, int count)
{
int i;
if (count < 1) {
printf("Error: numero de hebras debe ser mayor que 1\n");
exit(-1);
}
bp->maxcnt = count;
bp->sbp = &bp->sb[0];
for (i=0; i < 2; i++) {
struct _sb *sbp = &(bp->sb[i]);
sbp->runners = count;
pthread_mutex_init(&sbp->mutex, NULL);
pthread_cond_init(&sbp->cond, NULL);
}
return(0);
}
Fernando R. Rannou
Diinf-USACH
28 / 30
14
Espera con barreras
int barrier_wait(barrier_t *bp)
{
struct _sb *sbp = bp->sbp;
pthread_mutex_lock(&sbp->mutex);
if (sbp->runners == 1) {
if (bp->maxcnt != 1) {
sbp->runners = bp->maxcnt;
bp->sbp = (bp->sbp = &bp->sb[0])? &bp->sb[1] : &bp->sb[0];
pthread_cond_broadcast(&sbp->cond);
}
} else {
sbp->runners--;
while (sbp->runners != bp->maxcnt)
pthread_cond_wait(&sbp->cond, &sbp->mutex);
}
pthread_mutex_unlock(&sbp->wait_mutex);
}
Fernando R. Rannou
Diinf-USACH
29 / 30
Uso de barreras
void *proceso(void *arg) {
int *tidptr, tid;
tidptr = (int *) arg; tid = *tidptr;
printf("hola justo antes de la barrera%d\n", tid);
barrier_wait(&barrera);
}
int main(int argc, char *argv[])
{
int i, status;
pthread_t hebra[10];
barrier_init(&barrera, 10);
for (i=0; i < 10; i++){
taskids[i] = (int *) malloc(sizeof(int));
*taskids[i] = i;
pthread_create(&hebra[i], NULL, &proceso, taskids[i]);
}
for (i=0; i < 10; i++)
pthread_join(hebra[i], (void **) &status);
barrier_destroy(&barrera);
}
Fernando R. Rannou
Diinf-USACH
30 / 30
15
Descargar