-
Notifications
You must be signed in to change notification settings - Fork 1
/
T2L3G9GarciaOrtega.c
executable file
·194 lines (148 loc) · 4.91 KB
/
T2L3G9GarciaOrtega.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/* Sergio Garcia Prado */
/* Roberto Ortega Sanchez */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>
//Semáforo mutex para exclusión mutua al acceder al buffer.
pthread_mutex_t buffer_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t datosLeidos_lock = PTHREAD_MUTEX_INITIALIZER;
//Semáforos que indican si el buffer tiene datos y sitio disponible.
sem_t hay_datos;
sem_t hay_sitio;
//Declaraciones de variables
int Nhilos, Nnumeros, Tambuffer;
int datosLeidos = 0;
int *buffer;
int in = 0;
int out = 0;
//Cálculo de la primalidad del número generado.
int esPrimo(int num){
int i ;
int sq = ( int ) sqrt ( num );
for (i = 2 ; i <= sq ; i++ ) {
if ( num % i == 0 ) {
return 0;
}
}
return 1;
}
//Función que añade un número al buffer, asegurándose previamente la exclusión mutua.
void meteNumero(int value){
pthread_mutex_lock(&buffer_lock);
buffer[in] = value;
in = (in + 1) % Tambuffer;
pthread_mutex_unlock(&buffer_lock);
}
//Función que extrae un número del buffer, asegurándose previamente la exclusión mutua.
void sacaNumero(int *value){
pthread_mutex_lock(&buffer_lock);
*value = buffer[out];
out = (out + 1) % Tambuffer;
pthread_mutex_unlock(&buffer_lock);
}
//Función que comprueba si quedan o no datos que leer en el buffer.
int quedanDatos(int *dato){
int a = 0;
if (datosLeidos < Nnumeros){
a = 1;
pthread_mutex_lock(&datosLeidos_lock);
*dato = datosLeidos;
datosLeidos++;
pthread_mutex_unlock(&datosLeidos_lock);
}
return a;
}
//Inicialización del hilo productor.
void *productor(void *arg1){
//Inicializamos el random.
srand ( time(NULL) );
int i;
for (i = 0; i < Nnumeros; i++) {
//Esperamos en el caso de que el buffer este lleno.
sem_wait(&hay_sitio);
//Al llegar a este punto, hemos asegurado que hay al menos un hueco libre en el buffer.
//Llamamos a la función meteNumero para que cree un dato y lo introduzca en el buffer.
meteNumero(rand() % 9999);
//Avisamos de que hay un nuevo dato.
sem_post(&hay_datos);
}
pthread_exit(NULL);
}
//Inicialización de los hilos consumidores.
void *consumidor(void* arg2){
int *idHilo = (int *) arg2;
int num, idDato;
char primo[3];
while (quedanDatos(&idDato)){
//Esperamos en el caso de que no haya datos en el buffer.
sem_wait(&hay_datos);
//Al llegar a este punto, estamos seguros de que en el buffer hay al menos un dato que leer.
//Llamamos a la función sacaNumero.
sacaNumero(&num);
//Avisamos de que hay un nuevo hueco en el buffer.
sem_post(&hay_sitio);
if (esPrimo(num)){
strcpy(primo, "si");
} else{
strcpy(primo, "no");
}
printf("Hilo numero %d : Ha sido consumido el %d valor generado. El numero %d %s es primo. \n", *idHilo+1, idDato+1,num, primo);
}
pthread_exit(NULL);
}
//Programa principal.
int main(int argc, char *argv[]){
//Validación del número de argumentos pasados al programa.
if(argc != 4){
printf("Error: numero de argumentos invalido.\n");
return 1;
}
//Validación del valor del primer argumento introducido. Corresponde al número de hilos que se desean crear.
if ( (Nhilos = atoi(argv[1]) ) <= 0) {
printf("Error: el numero de hilos debe ser mayor que cero.\n");
return 1;
}
//Validación del valor del segundo argumento introducido. Corresponde a la cantidad de números que se desean crear.
if ( (Nnumeros = atoi(argv[2]) ) <= 0) {
printf("Error: la cantidad de numeros para analizar debe ser mayor que cero.\n");
return 1;
}
//Las siguientes dos sentencias if realizar la validación del valor del tercer y último argumento introducido. Corresponde al tamaño del buffer.
if ( (Tambuffer = atoi(argv[3]) ) <= 0) {
printf("Error el tamano del buffer debe ser mayor que cero.\n");
return 1;
}
if (Tambuffer > (Nnumeros / 2)){
printf("Error: el tamano del buffer es demasiado grande.\n");
return 1;
}
//Comprobación de la correcta reserva de memoria del buffer que servirá para almacenar los datos que se generen posteriormente.
if ( (buffer=(int*)malloc(Tambuffer * sizeof(int))) == NULL) {
printf("ERROR al reservar memoria\n");
return 1;
}
//Declaracion de los procesos, tanto productor, como consumidores.
pthread_t producer, consumer[Nhilos];
//Inicializamos los semáforos.
//El semáforo hay_datos a 0 para indicar que el buffer esta vacío al principio.
//El semáforo hay_sitio con el tamaño del buffer, ya que éstos son los huecos disponibles.
sem_init(&hay_datos, 0, 0);
sem_init(&hay_sitio, 0, Tambuffer);
//Creación del proceso productor.
pthread_create(&producer, NULL, productor,(void *) NULL);
//Creación de los procesos consumidores.
int i;
int id[Nhilos];
for (i = 0; i < Nhilos; i++){
id[i] = i;
pthread_create(&consumer[i], NULL, consumidor,(void*) &id[i]);
}
//Se espera a que los hilos terminen.
pthread_join(producer, NULL);
for (i = 0 ; i< Nhilos; i++){
pthread_join(consumer[i], NULL);
}
}