]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/practica2/P02e1201.cpp
Práctica 2, ejercicio 1 completo.
[z.facultad/75.74/practicos.git] / practicas / practica2 / P02e1201.cpp
1 /**
2  * Leandro Lucarella (77891)
3  *
4  * Ejercicio 1.1. Implementa problema del museo usando solamente variables
5  * (shared memory)
6  */
7
8 #include <iostream>
9 #include <cstdlib>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <sys/ipc.h>
14 #include <sys/shm.h>
15 #include <sys/sem.h>
16
17 /// Clave de nuestro segmento shm y semaforo
18 #define SHM_KEY 0x77891120
19 #define SEM_KEY 0x77891121
20
21 /// Ahora el contador es un simple unsigned
22 typedef unsigned Molinete;
23
24 /// Union para utilizar semaforo
25 union semun
26 {
27         int val;
28         struct semid_ds* buf;
29         unsigned short* array;
30 };
31
32 int main(int argc, char *argv[])
33 {
34         using std::cerr;
35         using std::cout;
36
37         if (argc < 2)
38         {
39                 cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n";
40                 return 1;
41         }
42         int proc = atoi(argv[1]);
43
44         // Shared memory
45         int shm_id = shmget(SHM_KEY, sizeof(Molinete), IPC_CREAT | 0666);
46         if (shm_id == -1)
47         {
48                 cerr << "Error al crea/obtener shared memory.\n";
49                 return 2;
50         }
51         Molinete* molinete = (Molinete*) shmat(shm_id, NULL, 0);
52         if (molinete == (Molinete*) -1)
53         {
54                 cerr << "Error al attachear shared memory.\n";
55                 return 3;
56         }
57         cout << "Shared memory id = " << shm_id << "\n";
58
59         // Semaforo
60         int sem_id = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
61         if (sem_id == -1)
62         {
63                 cerr << "Error al crea/obtener semaforo.\n";
64                 return 4;
65         }
66         semun sem_arg;
67         sem_arg.val = 0;
68         if (semctl(sem_id, 0, SETVAL, sem_arg) < 0)
69         {
70                 cerr << "No se pudo inicializar semaforo.\n";
71                 return 5;
72         }
73         struct sembuf ops; 
74         ops.sem_op = 1; // agregar 1
75         ops.sem_num = 0; // al semaforo 1
76         ops.sem_flg = 0; // esperando
77         if (semop(sem_id, &ops, 1) < 0)
78         {
79                 cerr << "No se pudo agregar al semaforo.\n";
80                 return 6;
81         }
82         cout << "Semaforo inicializado id = " << sem_id << "\n";
83
84         // Si somos el primer proceso inicializamos el molinete
85         if (!proc) *molinete = 0;
86
87         // Maxima cantidad de iteraciones (puede venir por parametro)
88         int max_iter = 100000;
89         if (argc > 2)
90                 max_iter = atoi(argv[2]);
91
92         // Loop principal
93         for (int i = 0; i < max_iter; ++i)
94         {
95                 bool dec = rand() % 2;
96                 int count;
97                 // lock
98                 ops.sem_op = -1; // saco 1 (== adquirir el mutex)
99                 if (semop(sem_id, &ops, 1) < 0)
100                 {
101                         cerr << "No se pudo sacar al semaforo.\n";
102                         return 6;
103                 }
104                 if (dec && molinete) // Decremento sólo si no es 0
105                         count = --*molinete;
106                 else
107                         count = ++*molinete;
108                 // unlock
109                 ops.sem_op = 1; // pongo 1 (== liberar el mutex)
110                 if (semop(sem_id, &ops, 1) < 0)
111                 {
112                         cerr << "No se pudo sacar al semaforo.\n";
113                         return 6;
114                 }
115                 // Uso cout directamente porque es line-buffered, mientras que
116                 // no use threads no es problema el buffer de cout. Y de todas
117                 // formas pongo un flush (el endl es \n+flush) por las dudas.
118                 cout << "Proceso " << proc << ": molinete = " << count << std::endl;
119                 //sched_yield(); // Para ver como se entrelazan mejor
120         }
121
122         if (shmdt(molinete) == -1)
123         {
124                 cerr << "Error al detachear shared memory.\n";
125                 return -1;
126         }
127
128         return 0;
129 }