From 2d0aa03246e924c53fb2e5c3a3af3dcaa3a7eab5 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Sat, 22 Apr 2006 15:48:54 +0000 Subject: [PATCH] Mejora y coding style de 1.1 y 1.2 (terminados). --- practicas/practica2/P02e1101.cpp | 179 ++++++++++++++------------- practicas/practica2/P02e1201.cpp | 200 +++++++++++++++++-------------- 2 files changed, 204 insertions(+), 175 deletions(-) diff --git a/practicas/practica2/P02e1101.cpp b/practicas/practica2/P02e1101.cpp index 185d14f..4c5cd03 100644 --- a/practicas/practica2/P02e1101.cpp +++ b/practicas/practica2/P02e1101.cpp @@ -24,41 +24,41 @@ enum state_t { RELEASED, ACQUIRED }; */ struct Mutex { - // Estados para un flag - /// indica el estado del proceso - state_t state[2]; - /// el proceso que tiene prioridad ante un race - int turn; + // Estados para un flag + /// indica el estado del proceso + state_t state[2]; + /// el proceso que tiene prioridad ante un race + int turn; }; /// Inicializa un mutex void mutex_init(Mutex& m) { - m.state[0] = RELEASED; - m.state[1] = RELEASED; - m.turn = 0; + m.state[0] = RELEASED; + m.state[1] = RELEASED; + m.turn = 0; } /// Adquiere un mutex para el proceso indicado por nproc void mutex_acquire(Mutex& m, int proc) { - m.state[proc] = ACQUIRED; - while (m.state[(proc+1)%2] == ACQUIRED) - { - if (m.turn != proc) - { - m.state[proc] = RELEASED; - while (m.turn != proc); - m.state[proc] = ACQUIRED; - } - } + m.state[proc] = ACQUIRED; + while (m.state[(proc+1)%2] == ACQUIRED) + { + if (m.turn != proc) + { + m.state[proc] = RELEASED; + while (m.turn != proc); + m.state[proc] = ACQUIRED; + } + } } /// Libera un mutex para el proceso indicado por proc void mutex_release(Mutex& m, int proc) { - m.turn = (proc+1)%2; - m.state[proc] = RELEASED; + m.turn = (proc+1)%2; + m.state[proc] = RELEASED; } /** @@ -67,75 +67,90 @@ void mutex_release(Mutex& m, int proc) */ struct Molinete { - unsigned count; - Mutex mutex; + unsigned count; + Mutex mutex; }; /// Inicializa el molinete void molinete_init(Molinete& m) { - m.count = 0; - mutex_init(m.mutex); + m.count = 0; + mutex_init(m.mutex); } int main(int argc, char *argv[]) { - using std::cerr; - using std::cout; - - if (argc < 2) - { - cerr << "Faltan parametros: " << argv[0] << " (0|1) [max_iter]\n"; - return 1; - } - int proc = atoi(argv[1]); - - int shm_id = shmget(SHM_KEY, sizeof(Molinete), IPC_CREAT | 0666); - if (shm_id == -1) - { - cerr << "Error al crea/obtener shared memory.\n"; - return 2; - } - Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0); - if (molinete == (Molinete*) -1) - { - cerr << "Error al attachear shared memory.\n"; - return 3; - } - - cout << "Shared memory id = " << shm_id << "\n"; - - // Si somos el primer proceso inicializamos el molinete - if (!proc) molinete_init(*molinete); - - // Maxima cantidad de iteraciones (puede venir por parametro) - int max_iter = 100000; - if (argc > 2) - max_iter = atoi(argv[2]); - - // Loop principal - for (int i = 0; i < max_iter; ++i) - { - bool dec = rand() % 2; - int count; - mutex_acquire(molinete->mutex, proc); - if (dec && molinete->count) // Decremento sólo si no es 0 - count = --molinete->count; - else - count = ++molinete->count; - mutex_release(molinete->mutex, proc); - // Uso cout directamente porque es line-buffered, mientras que - // no use threads no es problema el buffer de cout. Y de todas - // formas pongo un flush (el endl es \n+flush) por las dudas. - cout << "Proceso " << proc << ": molinete = " << count << std::endl; - //sched_yield(); // Para ver como se entrelazan mejor - } - - if (shmdt(molinete) == -1) - { - cerr << "Error al detachear shared memory.\n"; - return -1; - } - - return 0; + using std::cerr; + using std::cout; + + if (argc < 2) + { + cerr << "Faltan parametros: " << argv[0] << " (0|1) [max_iter]\n"; + return 1; + } + int proc = atoi(argv[1]); + + int shm_id = shmget(SHM_KEY, sizeof(Molinete), IPC_CREAT | 0666); + if (shm_id == -1) + { + cerr << "Error al crea/obtener shared memory.\n"; + return 2; + } + Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0); + if (molinete == (Molinete*) -1) + { + cerr << "Error al attachear shared memory.\n"; + return 3; + } + + cout << "Shared memory id = " << shm_id << "\n"; + + // Si somos el primer proceso inicializamos el molinete + if (!proc) molinete_init(*molinete); + else usleep(1000); // espero que el 1er proceso inicialice + + // Maxima cantidad de iteraciones (puede venir por parametro) + int max_iter = 100000; + if (argc > 2) + max_iter = atoi(argv[2]); + + srand(getpid()); + + // Loop principal + for (int i = 0; i < max_iter; ++i) + { + char sdec[] = "sale"; + char sinc[] = "entra"; + char* s; + bool dec = rand() % 2; + int count; + mutex_acquire(molinete->mutex, proc); + if (dec && molinete->count) // Decremento sólo si no es 0 + { + s = sdec; + count = --molinete->count; + } + else + { + s = sinc; + count = ++molinete->count; + } + mutex_release(molinete->mutex, proc); + // Uso cout directamente porque es line-buffered, mientras que + // no use threads no es problema el buffer de cout. Y de todas + // formas pongo un flush (el endl es \n+flush) por las dudas. + cout << "Proceso " << proc << " (" << s << "): molinete = " << count + << std::endl; + sched_yield(); // Para ver como se entrelazan mejor + } + + if (shmdt(molinete) == -1) + { + cerr << "Error al detachear shared memory.\n"; + return -1; + } + + return 0; } + +// vim: set et sw=4 sts=4 : diff --git a/practicas/practica2/P02e1201.cpp b/practicas/practica2/P02e1201.cpp index 9c0cb6b..b53feaa 100644 --- a/practicas/practica2/P02e1201.cpp +++ b/practicas/practica2/P02e1201.cpp @@ -1,8 +1,8 @@ /** * Leandro Lucarella (77891) * - * Ejercicio 1.1. Implementa problema del museo usando solamente variables - * (shared memory) + * Ejercicio 1.2. Implementa problema del museo usando variables (shared memory) + * y semaforos. */ #include @@ -22,111 +22,125 @@ typedef unsigned Molinete; /// Hace un wait (P) al semaforo (devuelve false si hubo error). -bool sem_wait(int sem_id) +void sem_wait(int sem_id) { - struct sembuf op; - op.sem_op = -1; // sacar 1 - op.sem_num = 0; // al semaforo 1 - op.sem_flg = 0; // esperando - return semop(sem_id, &op, 1) >= 0; + struct sembuf op; + op.sem_op = -1; // sacar 1 + op.sem_num = 0; // al semaforo 1 + op.sem_flg = 0; // esperando + if (semop(sem_id, &op, 1) < 0) + { + std::cerr << "No se pudo sacar al semaforo.\n"; + exit(100); + } } /// Hace un signal (V) al semaforo (devuelve false si hubo error). -bool sem_signal(int sem_id) +void sem_signal(int sem_id) { - struct sembuf op; - op.sem_op = 1; // agregar 1 - op.sem_num = 0; // al semaforo 1 - op.sem_flg = 0; // esperando - return semop(sem_id, &op, 1) >= 0; + struct sembuf op; + op.sem_op = 1; // agregar 1 + op.sem_num = 0; // al semaforo 1 + op.sem_flg = 0; // esperando + if (semop(sem_id, &op, 1) < 0) + { + std::cerr << "No se pudo poner en el semaforo.\n"; + exit(101); + } } int main(int argc, char *argv[]) { - using std::cerr; - using std::cout; + using std::cerr; + using std::cout; - if (argc < 2) - { - cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n"; - return 1; - } - int proc = atoi(argv[1]); + if (argc < 2) + { + cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n"; + return 1; + } + int proc = atoi(argv[1]); - // Shared memory - int shm_id = shmget(SHM_KEY, sizeof(Molinete), IPC_CREAT | 0666); - if (shm_id == -1) - { - cerr << "Error al crea/obtener shared memory.\n"; - return 2; - } - Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0); - if (molinete == (Molinete*) -1) - { - cerr << "Error al attachear shared memory.\n"; - return 3; - } - cout << "Shared memory id = " << shm_id << "\n"; + // Shared memory + int shm_id = shmget(SHM_KEY, sizeof(Molinete), IPC_CREAT | 0666); + if (shm_id == -1) + { + cerr << "Error al crea/obtener shared memory.\n"; + return 2; + } + Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0); + if (molinete == (Molinete*) -1) + { + cerr << "Error al attachear shared memory.\n"; + return 3; + } + cout << "Shared memory id = " << shm_id << "\n"; - // Semaforo - int sem_id = semget(SEM_KEY, 1, 0666 | IPC_CREAT); - if (sem_id == -1) - { - cerr << "Error al crea/obtener semaforo.\n"; - return 4; - } - // Si es el primero, inicializo - if (!proc) - { - *molinete = 0; - if (semctl(sem_id, 0, SETVAL, 1) < 0) - { - cerr << "No se pudo inicializar semaforo.\n"; - return 5; - } - cout << "Semaforo inicializado id = " << sem_id << "\n"; - } - else // Si soy otro espero un poco por las dudas para que corra el 1ro - { - usleep(1000); - } + // Semaforo + int sem_id = semget(SEM_KEY, 1, 0666 | IPC_CREAT); + if (sem_id == -1) + { + cerr << "Error al crea/obtener semaforo.\n"; + return 4; + } + // Si es el primero, inicializo + if (!proc) + { + *molinete = 0; + if (semctl(sem_id, 0, SETVAL, 1) < 0) // pongo 1 en el sem + { + cerr << "No se pudo inicializar semaforo.\n"; + return 5; + } + cout << "Semaforo inicializado id = " << sem_id << "\n"; + } + else // Si soy otro espero un poco por las dudas para que corra el 1ro + { + usleep(10000); + } - // Maxima cantidad de iteraciones (puede venir por parametro) - int max_iter = 100000; - if (argc > 2) - max_iter = atoi(argv[2]); + srand(getpid()); - // Loop principal - for (int i = 0; i < max_iter; ++i) - { - bool dec = rand() % 2; - int count; - if (!sem_wait(sem_id)) // lock - { - cerr << "No se pudo sacar al semaforo.\n"; - return 6; - } - if (dec && *molinete) // Decremento sólo si no es 0 - count = --*molinete; - else - count = ++*molinete; - if (!sem_signal(sem_id)) // unlock - { - cerr << "No se pudo sacar al semaforo.\n"; - return 6; - } - // Uso cout directamente porque es line-buffered, mientras que - // no use threads no es problema el buffer de cout. Y de todas - // formas pongo un flush (el endl es \n+flush) por las dudas. - cout << "Proceso " << proc << ": molinete = " << count << std::endl; - //sched_yield(); // Para ver como se entrelazan mejor - } + // Maxima cantidad de iteraciones (puede venir por parametro) + int max_iter = 100000; + if (argc > 2) + max_iter = atoi(argv[2]); - if (shmdt(molinete) == -1) - { - cerr << "Error al detachear shared memory.\n"; - return -1; - } + // Loop principal + for (int i = 0; i < max_iter; ++i) + { + char sdec[] = "sale"; + char sinc[] = "entra"; + char* s; + bool dec = rand() % 2; + int count; + sem_wait(sem_id); // lock + if (dec && *molinete) // Decremento sólo si no es 0 + { + s = sdec; + count = --*molinete; + } + else + { + s = sinc; + count = ++*molinete; + } + sem_signal(sem_id); // unlock + // Uso cout directamente porque es line-buffered, mientras que + // no use threads no es problema el buffer de cout. Y de todas + // formas pongo un flush (el endl es \n+flush) por las dudas. + cout << "Proceso " << proc << " (" << s << "): molinete = " << count + << std::endl; + sched_yield(); // Para ver como se entrelazan mejor + } - return 0; + if (shmdt(molinete) == -1) + { + cerr << "Error al detachear shared memory.\n"; + return -1; + } + + return 0; } + +// vim: set et sw=4 sts=4 : -- 2.43.0