]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/practica2/P02e2111.cpp
Ya estamos fragmentando! (falta testing intensivo pero parece andar)
[z.facultad/75.74/practicos.git] / practicas / practica2 / P02e2111.cpp
1 /**
2  * Leandro Lucarella (77891)
3  *
4  * Ejercicio 2.1.1. Implementa productor-consumidor con semaforos binarios y
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 using std::cerr;
18 using std::cout;
19 using std::endl;
20
21 /// Clave de nuestro segmento shm y semaforo
22 #define SHM_KEY 0x77891220
23 #define SEM_KEY 0x77891221
24
25 /// Elemento a producir/consumir
26 typedef int Elemento;
27
28 /// Nombres de los semaforos a utilizar
29 enum sem_num_t { MUTEX, FULL, EMPTY };
30
31 /// Nombres de los procesos
32 enum proc_t { PRODUCTOR, CONSUMIDOR };
33
34 /// Hace un wait (P) al semaforo (devuelve false si hubo error).
35 void sem_wait(int sem_id, sem_num_t sem_num)
36 {
37     struct sembuf op;
38     op.sem_op = -1; // sacar 1
39     op.sem_num = sem_num; // al semaforo sem_num
40     op.sem_flg = 0; // esperando
41     if (semop(sem_id, &op, 1) > 0)
42     {
43         cerr << "No se pudo sacar al semaforo.\n";
44         exit(100);
45     }
46 }
47
48 /// Hace un signal (V) al semaforo (devuelve false si hubo error).
49 void sem_signal(int sem_id, sem_num_t sem_num)
50 {
51     struct sembuf op;
52     op.sem_op =  1; // agregar 1
53     op.sem_num = sem_num; // al semaforo sem_num
54     op.sem_flg = 0; // esperando
55     if (semop(sem_id, &op, 1) > 0)
56     {
57         cerr << "No se pudo poner al semaforo.\n";
58         exit(101);
59     }
60 }
61
62 void productor(int sem_id, Elemento* elem)
63 {
64         int val = rand();
65         // espera que este vacio segun sea productor
66         sem_wait(sem_id, EMPTY);
67         sem_wait(sem_id, MUTEX); // lock
68         // produzco
69         *elem = val;
70         sem_signal(sem_id, MUTEX); // unlock
71         // indica que esta lleno
72         cout << "Productor puso elem = " << val << endl;
73         sem_signal(sem_id, FULL);
74 }
75
76 void consumidor(int sem_id, Elemento* elem)
77 {
78         int val;
79         // espera que este lleno segun sea consumidor
80         sem_wait(sem_id, FULL);
81         sem_wait(sem_id, MUTEX); // lock
82         // consumo
83         val = *elem;
84         sem_signal(sem_id, MUTEX); // unlock
85         // indica que esta vacio
86         cout << "Consumidor saco elem = " << val << endl;
87         sem_signal(sem_id, EMPTY);
88 }
89
90 int main(int argc, char *argv[])
91 {
92     if (argc < 2)
93     {
94         cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n";
95         return 1;
96     }
97     proc_t proc = (proc_t) atoi(argv[1]);
98
99     // Shared memory
100     int shm_id;
101     do
102     {
103         shm_id = shmget(SHM_KEY, sizeof(Elemento),
104             (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0
105     }
106     while (proc == CONSUMIDOR && shm_id == -1);
107     Elemento* elem = (Elemento*) shmat(shm_id, NULL, 0);
108     if (elem == (Elemento*) -1)
109     {
110         cerr << "Error al attachear shared memory.\n";
111         return 3;
112     }
113
114     // Semaforos
115     int sem_id;
116     do
117     {
118         sem_id = semget(SEM_KEY, 3,
119             (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0
120     }
121     while (proc == CONSUMIDOR && sem_id == -1);
122
123     // Si somos los primeros inicializamos
124     if (proc == PRODUCTOR)
125     {
126         if (semctl(sem_id, MUTEX, SETVAL, 1) < 0)
127         {
128             cerr << "No se pudo inicializar semaforo.\n";
129             return 5;
130         }
131         if (semctl(sem_id, FULL, SETVAL, 0) < 0)
132         {
133             cerr << "No se pudo inicializar semaforo.\n";
134             return 6;
135         }
136         if (semctl(sem_id, EMPTY, SETVAL, 1) < 0)
137         {
138             cerr << "No se pudo inicializar semaforo.\n";
139             return 7;
140         }
141     }
142
143     // Maxima cantidad de iteraciones (puede venir por parametro)
144     int max_iter = 10;
145     if (argc > 2)
146         max_iter = atoi(argv[2]);
147
148     srand(getpid());
149
150     // Loop principal
151     for (int i = 0; i < max_iter; ++i)
152     {
153         if (proc == PRODUCTOR)
154             productor(sem_id, elem);
155         else
156             consumidor(sem_id, elem);
157     }
158
159     if (shmdt(elem) == -1)
160     {
161         cerr << "Error al detachear shared memory.\n";
162         return -1;
163     }
164
165     return 0;
166 }
167
168 // vim: set et sw=4 sts=4 :