2 * Leandro Lucarella (77891)
4 * Ejercicio 2.1.2. Implementa productor-consumidor con semaforos binarios y
5 * shared memory pero con 3 productores que producen 1/3 cada uno.
12 #include <sys/types.h>
21 /// Clave de nuestro segmento shm y semaforo
22 #define SHM_KEY 0x77891222
23 #define SEM_KEY 0x77891223
25 /// Maxima cantidad de partes y consumidores
29 /// Elemento a producir/consumir
32 int partes[MAX_PARTES]; ///> Partes del producto a producir
33 bool producido[MAX_PARTES]; ///> Indica que parte fue producida
34 bool consumido[MAX_CONSUM]; ///> Indica quien consumio
37 /// Inicializa elemento
38 void elemento_init(Elemento* e)
40 e->producido[0] = e->producido[1] = e->producido[2] = false;
41 e->consumido[0] = e->consumido[1] = false;
44 /// Nombres de los semaforos a utilizar
45 enum sem_num_t { MUTEX, FULL, EMPTY };
47 /// Nombres de los procesos
48 enum proc_t { PRODUCTOR1, PRODUCTOR2, PRODUCTOR3, CONSUMIDOR1, CONSUMIDOR2 };
50 void sem_init(int sem_id, sem_num_t sem_num, int val)
52 if (semctl(sem_id, sem_num, SETVAL, val) < 0)
54 cerr << "No se pudo inicializar semaforo.\n";
60 /// Hace un wait (P) al semaforo (devuelve false si hubo error).
61 void sem_wait(int sem_id, sem_num_t sem_num)
64 op.sem_op = -1; // sacar 1
65 op.sem_num = sem_num; // al semaforo sem_num
66 op.sem_flg = 0; // esperando
67 if (semop(sem_id, &op, 1) > 0)
69 cerr << "No se pudo sacar al semaforo.\n";
74 /// Hace un signal (V) al semaforo (devuelve false si hubo error).
75 void sem_signal(int sem_id, sem_num_t sem_num)
78 op.sem_op = 1; // agregar 1
79 op.sem_num = sem_num; // al semaforo sem_num
80 op.sem_flg = 0; // esperando
81 if (semop(sem_id, &op, 1) > 0)
83 cerr << "No se pudo poner al semaforo.\n";
88 void producir(int proc, int parte, int sem_id, Elemento* elem, int iter)
90 for (int i = 0; i < iter; ++i)
93 sem_wait(sem_id, EMPTY); // espera que este vacio (que hayan leido los 2)
94 sem_wait(sem_id, MUTEX); // lock
96 if (!elem->producido[parte])
98 elem->partes[parte] = val;
99 elem->producido[parte] = true;
100 cout << "Productor " << parte << " puso su parte: " << val << endl;
103 --i; // no cuento esta iteración
104 // si esta todo listo, aviso
105 if (elem->producido[0] && elem->producido[1] && elem->producido[2])
107 elem->consumido[0] = elem->consumido[1] = false;
108 sem_signal(sem_id, MUTEX); // unlock
109 sem_signal(sem_id, FULL);
113 sem_signal(sem_id, MUTEX); // unlock
114 sem_signal(sem_id, EMPTY);
119 void consumir(int proc, int consumidor, int sem_id, Elemento* elem, int iter)
121 for (int i = 0; i < iter; ++i)
123 sem_wait(sem_id, FULL); // espera que este lleno
124 sem_wait(sem_id, MUTEX); // lock
126 if (!elem->consumido[consumidor])
128 elem->consumido[consumidor] = true;
129 cout << "Consumidor " << consumidor << " consumio "
130 << elem->partes[0] << "," << elem->partes[1]
131 << "," << elem->partes[2] << endl;
134 --i; // no cuento esta iteracion
135 // si esta todo listo, aviso
136 if (elem->consumido[0] && elem->consumido[1])
138 elem->producido[0] = elem->producido[1]
139 = elem->producido[2] = false;
140 sem_signal(sem_id, MUTEX); // unlock
141 sem_signal(sem_id, EMPTY);
145 sem_signal(sem_id, MUTEX); // unlock
146 sem_signal(sem_id, FULL);
151 int main(int argc, char *argv[])
155 cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n";
158 proc_t proc = (proc_t) atoi(argv[1]);
164 shm_id = shmget(SHM_KEY, sizeof(Elemento),
165 (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0
167 while (proc != PRODUCTOR1 && shm_id == -1);
168 Elemento* elem = (Elemento*) shmat(shm_id, NULL, 0);
169 if (elem == (Elemento*) -1)
171 cerr << "Error al attachear shared memory.\n";
179 sem_id = semget(SEM_KEY, 3,
180 (proc ? 0 : IPC_CREAT) | 0666); // crea solo si es el proceso 0
182 while (proc != PRODUCTOR1 && sem_id == -1);
184 // Si somos los primeros inicializamos
185 if (proc == PRODUCTOR1)
188 sem_init(sem_id, MUTEX, 1);
189 sem_init(sem_id, FULL, 0);
190 sem_init(sem_id, EMPTY, 1);
195 // Maxima cantidad de iteraciones (puede venir por parametro)
198 max_iter = atoi(argv[2]);
200 if (proc < 3) // es productor
201 producir(proc, proc, sem_id, elem, max_iter);
203 consumir(proc, proc-3, sem_id, elem, max_iter);
205 if (shmdt(elem) == -1)
207 cerr << "Error al detachear shared memory.\n";
214 // vim: set et sw=4 sts=4 :