From 9392c3f27cfe0c6b4a128d827cc87c4756cc27bb Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Mon, 24 Apr 2006 04:40:58 +0000 Subject: [PATCH] Terminado 2.1.2 (con mucha bussy wait pero funciona). --- practicas/practica2/P02e2121.cpp | 214 +++++++++++++++++++++++++++++++ practicas/practica2/P02e2121.sh | 26 ++++ 2 files changed, 240 insertions(+) create mode 100644 practicas/practica2/P02e2121.cpp create mode 100755 practicas/practica2/P02e2121.sh diff --git a/practicas/practica2/P02e2121.cpp b/practicas/practica2/P02e2121.cpp new file mode 100644 index 0000000..7aedaec --- /dev/null +++ b/practicas/practica2/P02e2121.cpp @@ -0,0 +1,214 @@ +/** + * Leandro Lucarella (77891) + * + * Ejercicio 2.1.2. Implementa productor-consumidor con semaforos binarios y + * shared memory pero con 3 productores que producen 1/3 cada uno. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cerr; +using std::cout; +using std::endl; + +/// Clave de nuestro segmento shm y semaforo +#define SHM_KEY 0x77891222 +#define SEM_KEY 0x77891223 + +/// Maxima cantidad de partes y consumidores +#define MAX_PARTES 3 +#define MAX_CONSUM 2 + +/// Elemento a producir/consumir +struct Elemento +{ + int partes[MAX_PARTES]; ///> Partes del producto a producir + bool producido[MAX_PARTES]; ///> Indica que parte fue producida + bool consumido[MAX_CONSUM]; ///> Indica quien consumio +}; + +/// Inicializa elemento +void elemento_init(Elemento* e) +{ + e->producido[0] = e->producido[1] = e->producido[2] = false; + e->consumido[0] = e->consumido[1] = false; +} + +/// Nombres de los semaforos a utilizar +enum sem_num_t { MUTEX, FULL, EMPTY }; + +/// Nombres de los procesos +enum proc_t { PRODUCTOR1, PRODUCTOR2, PRODUCTOR3, CONSUMIDOR1, CONSUMIDOR2 }; + +void sem_init(int sem_id, sem_num_t sem_num, int val) +{ + if (semctl(sem_id, sem_num, SETVAL, val) < 0) + { + cerr << "No se pudo inicializar semaforo.\n"; + exit(99); + } +} + + +/// Hace un wait (P) al semaforo (devuelve false si hubo error). +void sem_wait(int sem_id, sem_num_t sem_num) +{ + struct sembuf op; + op.sem_op = -1; // sacar 1 + op.sem_num = sem_num; // al semaforo sem_num + op.sem_flg = 0; // esperando + if (semop(sem_id, &op, 1) > 0) + { + cerr << "No se pudo sacar al semaforo.\n"; + exit(100); + } +} + +/// Hace un signal (V) al semaforo (devuelve false si hubo error). +void sem_signal(int sem_id, sem_num_t sem_num) +{ + struct sembuf op; + op.sem_op = 1; // agregar 1 + op.sem_num = sem_num; // al semaforo sem_num + op.sem_flg = 0; // esperando + if (semop(sem_id, &op, 1) > 0) + { + cerr << "No se pudo poner al semaforo.\n"; + exit(101); + } +} + +void producir(int proc, int parte, int sem_id, Elemento* elem, int iter) +{ + for (int i = 0; i < iter; ++i) + { + int val = rand(); + sem_wait(sem_id, EMPTY); // espera que este vacio (que hayan leido los 2) + sem_wait(sem_id, MUTEX); // lock + // produzco mi parte + if (!elem->producido[parte]) + { + elem->partes[parte] = val; + elem->producido[parte] = true; + cout << "Productor " << parte << " puso su parte: " << val << endl; + } + else + --i; // no cuento esta iteración + // si esta todo listo, aviso + if (elem->producido[0] && elem->producido[1] && elem->producido[2]) + { + elem->consumido[0] = elem->consumido[1] = false; + sem_signal(sem_id, MUTEX); // unlock + sem_signal(sem_id, FULL); + } + else + { + sem_signal(sem_id, MUTEX); // unlock + sem_signal(sem_id, EMPTY); + } + } +} + +void consumir(int proc, int consumidor, int sem_id, Elemento* elem, int iter) +{ + for (int i = 0; i < iter; ++i) + { + sem_wait(sem_id, FULL); // espera que este lleno + sem_wait(sem_id, MUTEX); // lock + // consumo + if (!elem->consumido[consumidor]) + { + elem->consumido[consumidor] = true; + cout << "Consumidor " << consumidor << " consumio " + << elem->partes[0] << "," << elem->partes[1] + << "," << elem->partes[2] << endl; + } + else + --i; // no cuento esta iteracion + // si esta todo listo, aviso + if (elem->consumido[0] && elem->consumido[1]) + { + elem->producido[0] = elem->producido[1] + = elem->producido[2] = false; + sem_signal(sem_id, MUTEX); // unlock + sem_signal(sem_id, EMPTY); + } + else + { + sem_signal(sem_id, MUTEX); // unlock + sem_signal(sem_id, FULL); + } + } +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n"; + return 1; + } + proc_t proc = (proc_t) atoi(argv[1]); + + // Shared memory + int shm_id; + do + { + shm_id = shmget(SHM_KEY, sizeof(Elemento), + (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0 + } + while (proc != PRODUCTOR1 && shm_id == -1); + Elemento* elem = (Elemento*) shmat(shm_id, NULL, 0); + if (elem == (Elemento*) -1) + { + cerr << "Error al attachear shared memory.\n"; + return 3; + } + + // Semaforos + int sem_id; + do + { + sem_id = semget(SEM_KEY, 3, + (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0 + } + while (proc != PRODUCTOR1 && sem_id == -1); + + // Si somos los primeros inicializamos + if (proc == PRODUCTOR1) + { + elemento_init(elem); + sem_init(sem_id, MUTEX, 1); + sem_init(sem_id, FULL, 0); + sem_init(sem_id, EMPTY, 1); + } + + srand(getpid()); + + // Maxima cantidad de iteraciones (puede venir por parametro) + int max_iter = 10; + if (argc > 2) + max_iter = atoi(argv[2]); + + if (proc < 3) // es productor + producir(proc, proc, sem_id, elem, max_iter); + else // consumidor + consumir(proc, proc-3, sem_id, elem, max_iter); + + if (shmdt(elem) == -1) + { + cerr << "Error al detachear shared memory.\n"; + return -1; + } + + return 0; +} + +// vim: set et sw=4 sts=4 : diff --git a/practicas/practica2/P02e2121.sh b/practicas/practica2/P02e2121.sh new file mode 100755 index 0000000..a83df57 --- /dev/null +++ b/practicas/practica2/P02e2121.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Lanzo procesos +# Productores +./P02e2121 0 $1 & +p0=$! +./P02e2121 1 $1 & +p1=$! +./P02e2121 2 $1 & +p2=$! +# Consumidores +./P02e2121 3 $1 & +p3=$! +./P02e2121 4 $1 & +p4=$! + +# Espero que terminen +wait $p0 +wait $p01 +wait $p02 +wait $p03 +wait $p04 + +# Limpio IPC +ipcrm -M 0x77891222 +ipcrm -S 0x77891223 -- 2.43.0