X-Git-Url: https://git.llucax.com/z.facultad/75.74/practicos.git/blobdiff_plain/6d12425d217477390d8772843d167e9d31d7cc19..15d27049e86bc6f836ff6163ea78a8a3e40b3c59:/practicas/practica2/P02e1101.cpp?ds=sidebyside diff --git a/practicas/practica2/P02e1101.cpp b/practicas/practica2/P02e1101.cpp index 185d14f..4d8989e 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,88 @@ 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; + do + { + shm_id = shmget(SHM_KEY, sizeof(Molinete), + (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0 + } + while (proc != 0 && shm_id == -1); + Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0); + if (molinete == (Molinete*) -1) + { + cerr << "Error al attachear shared memory.\n"; + return 3; + } + + // Si somos el primer proceso inicializamos el molinete + if (proc == 0) molinete_init(*molinete); + + // 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) + { + 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 :