#include <sys/shm.h>
#include <sys/sem.h>
+using std::cerr;
+using std::cout;
+using std::endl;
+
/// Clave de nuestro segmento shm y semaforo
#define SHM_KEY 0x77891220
#define SEM_KEY 0x77891221
/// 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)
- {
- std::cerr << "No se pudo sacar al semaforo.\n";
- exit(100);
- }
+ 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)
- {
- std::cerr << "No se pudo poner al semaforo.\n";
- exit(101);
- }
+ 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 productor(int sem_id, Elemento* elem)
+{
+ int val = rand();
+ // espera que este vacio segun sea productor
+ sem_wait(sem_id, EMPTY);
+ sem_wait(sem_id, MUTEX); // lock
+ // produzco
+ *elem = val;
+ sem_signal(sem_id, MUTEX); // unlock
+ // indica que esta lleno
+ cout << "Productor puso elem = " << val << endl;
+ sem_signal(sem_id, FULL);
+}
+
+void consumidor(int sem_id, Elemento* elem)
+{
+ int val;
+ // espera que este lleno segun sea consumidor
+ sem_wait(sem_id, FULL);
+ sem_wait(sem_id, MUTEX); // lock
+ // consumo
+ val = *elem;
+ sem_signal(sem_id, MUTEX); // unlock
+ // indica que esta vacio
+ cout << "Consumidor saco elem = " << val << endl;
+ sem_signal(sem_id, EMPTY);
}
int main(int argc, char *argv[])
{
- using std::cerr;
- using std::cout;
-
- 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 = shmget(SHM_KEY, sizeof(Elemento), IPC_CREAT | 0666);
- if (shm_id == -1)
- {
- cerr << "Error al crea/obtener shared memory.\n";
- return 2;
- }
- Elemento* elem = (Elemento*) shmat(shm_id, NULL, 0);
- if (elem == (Elemento*) -1)
- {
- cerr << "Error al attachear shared memory.\n";
- return 3;
- }
- cout << "Shared memory id = " << shm_id << "\n";
-
- // Semaforos
- int sem_id = semget(SEM_KEY, 3, 0666 | IPC_CREAT);
- if (sem_id == -1)
- {
- cerr << "Error al crea/obtener semaforos.\n";
- return 4;
- }
- // Si somos los primeros inicializamos
- if (!proc)
- {
- if (semctl(sem_id, MUTEX, SETVAL, 1) < 0)
- {
- cerr << "No se pudo inicializar semaforo.\n";
- return 5;
- }
- if (semctl(sem_id, FULL, SETVAL, 0) < 0)
- {
- cerr << "No se pudo inicializar semaforo.\n";
- return 6;
- }
- if (semctl(sem_id, EMPTY, SETVAL, 1) < 0)
- {
- cerr << "No se pudo inicializar semaforo.\n";
- return 7;
- }
- cout << "Semaforos inicializados id = " << sem_id << "\n";
- }
- else // Si soy otro espero un poco por las dudas para que corra el 1ro
- {
- usleep(1000);
- }
-
- // Maxima cantidad de iteraciones (puede venir por parametro)
- int max_iter = 10;
- if (argc > 2)
- max_iter = atoi(argv[2]);
-
- // Loop principal
- for (int i = 0; i < max_iter; ++i)
- {
- int val = rand();
- // espera que este lleno/vacio segun sea consumidor/productor
- if (proc == PRODUCTOR)
- sem_wait(sem_id, EMPTY);
- else
- sem_wait(sem_id, FULL);
- sem_wait(sem_id, MUTEX); // lock
- // produzco / consumo
- if (proc == PRODUCTOR)
- *elem = val;
- else
- val = *elem;
- sem_signal(sem_id, MUTEX); // unlock
- // indica que esta lleno/vacio segun sea productor/consumidor
- if (proc == PRODUCTOR)
- {
- cout << "Productor (" << getpid() << ") puso elem = "
- << val << std::endl;
- sem_signal(sem_id, FULL);
- }
- else
- {
- cout << "Consumidor (" << getpid() << ") saco elem = "
- << val << std::endl;
- sem_signal(sem_id, EMPTY);
- }
- }
-
- if (shmdt(elem) == -1)
- {
- cerr << "Error al detachear shared memory.\n";
- return -1;
- }
-
- return 0;
+ 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 == CONSUMIDOR && 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 == CONSUMIDOR && sem_id == -1);
+
+ // Si somos los primeros inicializamos
+ if (proc == PRODUCTOR)
+ {
+ if (semctl(sem_id, MUTEX, SETVAL, 1) < 0)
+ {
+ cerr << "No se pudo inicializar semaforo.\n";
+ return 5;
+ }
+ if (semctl(sem_id, FULL, SETVAL, 0) < 0)
+ {
+ cerr << "No se pudo inicializar semaforo.\n";
+ return 6;
+ }
+ if (semctl(sem_id, EMPTY, SETVAL, 1) < 0)
+ {
+ cerr << "No se pudo inicializar semaforo.\n";
+ return 7;
+ }
+ }
+
+ // Maxima cantidad de iteraciones (puede venir por parametro)
+ int max_iter = 10;
+ if (argc > 2)
+ max_iter = atoi(argv[2]);
+
+ srand(getpid());
+
+ // Loop principal
+ for (int i = 0; i < max_iter; ++i)
+ {
+ if (proc == PRODUCTOR)
+ productor(sem_id, elem);
+ else
+ consumidor(sem_id, elem);
+ }
+
+ if (shmdt(elem) == -1)
+ {
+ cerr << "Error al detachear shared memory.\n";
+ return -1;
+ }
+
+ return 0;
}
+
+// vim: set et sw=4 sts=4 :