X-Git-Url: https://git.llucax.com/z.facultad/75.74/practicos.git/blobdiff_plain/eed78fbb7c396cd3be666be8f2517bb828ae1353..865c286c8c17594d33075e9696d85968eea8dd3b:/practicas/practica2/P02e2111.cpp diff --git a/practicas/practica2/P02e2111.cpp b/practicas/practica2/P02e2111.cpp index 1a5c8d7..932638f 100644 --- a/practicas/practica2/P02e2111.cpp +++ b/practicas/practica2/P02e2111.cpp @@ -14,6 +14,10 @@ #include #include +using std::cerr; +using std::cout; +using std::endl; + /// Clave de nuestro segmento shm y semaforo #define SHM_KEY 0x77891220 #define SEM_KEY 0x77891221 @@ -30,131 +34,135 @@ enum proc_t { PRODUCTOR, CONSUMIDOR }; /// 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 :