Skip to content
Extraits de code Groupes Projets
Valider 9433e6e6 rédigé par Mélanie Colasse's avatar Mélanie Colasse
Parcourir les fichiers

Upload New File

parent 8afe5ef0
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
#define NT 4
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <semaphore.h>
typedef struct{
int file_descriptor;
pthread_mutex_t mutex;
} threadf_t;
typedef struct{
pthread_mutex_t mutex;
sem_t empty, full;
long w, x, y, *z;
threadf_t *out;
} buffer_t;
typedef struct{
size_t len;
char *str;
} word_t;
typedef struct _link{
void *data;
struct _link *nx;
} link_t;
threadf_t *threadf_init(const char *fn){
threadf_t *new = malloc(sizeof(threadf_t));
if(new == NULL) exit(EXIT_FAILURE);
new->file_descriptor = open(fn, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
if(new->file_descriptor == -1) exit(EXIT_FAILURE);
pthread_mutex_init(&new->mutex, NULL);
return new;
}
void threadf_destroy(threadf_t *threadf){
pthread_mutex_destroy(&threadf->mutex);
if(close(threadf->file_descriptor) == -1)
strerror(errno);
free(threadf);
}
buffer_t *buffer_init(const char *fn){
buffer_t *new = malloc(sizeof(buffer_t));
if(new == NULL) exit(EXIT_FAILURE);
new->w = 2 * NT; new->x = 0; new->y = 0;
new->z = malloc(sizeof(long) * new->w);
if(new->z == NULL) exit(EXIT_FAILURE);
new->out = threadf_init(fn);
pthread_mutex_init(&new->mutex, NULL);
sem_init(&new->empty, 0, new->w);
sem_init(&new->full, 0, 0);
return new;
}
void buffer_put(buffer_t *bf, long v){
sem_wait(&bf->empty); // WAITING FOR AT LEAST ONE FREE CASE IN THE BUFFER
pthread_mutex_lock(&bf->mutex);
bf->z[bf->x % bf->w] = v;
bf->x = (bf->x + 1) % bf->w;
pthread_mutex_unlock(&bf->mutex);
sem_post(&bf->full); // SIGNALING THAT THERE'S ONE MORE ELEMENT IN THE BUFFER
}
long buffer_get(buffer_t *bf){
long output;
sem_wait(&bf->full); // WAITING FOR AT LEAST ONE ELEMENT IN THE BUFFER TO CONSUME
pthread_mutex_lock(&bf->mutex);
output = bf->z[bf->y % bf->w];
bf->y = (bf->y + 1) % bf->w;
pthread_mutex_unlock(&bf->mutex);
sem_post(&bf->empty);
return output;
}
void buffer_destroy(buffer_t *bf){
free(bf->z);
sem_destroy(&bf->full);
sem_destroy(&bf->empty);
threadf_destroy(bf->out);
pthread_mutex_destroy(&bf->mutex);
free(bf);
}
word_t *word_init(char *str, size_t len){
word_t *new = malloc(sizeof(word_t));
if(new == NULL) exit(EXIT_FAILURE);
new->str = str; new->len = len;
return new;
}
word_t *long_to_str(long value){
size_t len = 1;
long tmp = value;
while(tmp /= 10) len++;
int len_copy = len;
char *str = malloc(sizeof(char) * len);
if(str == NULL) exit(EXIT_FAILURE);
while(len_copy--){ str[len_copy] = (char) ((value % 10) + '0'); value /= 10; }
return word_init(str, len);
}
void *word_destroy(word_t *word){
free(word->str);
free(word);
}
link_t *link_init(void *data){
link_t *new = malloc(sizeof(link_t));
if(new == NULL) exit(EXIT_FAILURE);
new->data = data;
new->nx = new;
return new;
}
void link_enqueue(link_t **link, void *data){
if((*link)->data){
link_t *new = link_init(data);
new->nx = (*link)->nx;
(*link)->nx = new;
*link = new;
}
else{
(*link)->data = data;
}
}
void *link_dequeue(link_t **link){
void *output;
if(*link == (*link)->nx){
output = (*link)->data;
(*link)->data = NULL;
}
else{
link_t *tmp = (*link)->nx;
(*link)->nx = tmp->nx;
output = tmp->data;
free(tmp);
}
return output;
}
void fermat_slave(link_t **link, long x){
if(x == 1) return;
long a = ceil(sqrt(x));
long sq = a * a;
if(sq == x){
fermat_slave(link, a);
}
else{
long b, c;
do {
b = (a * a) - x;
c = floor(sqrt(b));
} while ((c * c) != b && ++a);
if(a - c == 1){
long *a_plus_c = malloc(sizeof(long));
if(a_plus_c == NULL) exit(EXIT_FAILURE);
*a_plus_c = a + c;
int is_in = 0;
if((*link)->data){
link_t *tmp = (*link);
is_in = (*a_plus_c == *(long *) tmp->data);
tmp = tmp->nx;
while (!is_in && tmp != *link){
is_in = (*a_plus_c == *(long *) tmp->data);
tmp = tmp->nx;
}
}
if(!is_in)
link_enqueue(link, a_plus_c);
}
else{
fermat_slave(link, a - c);
fermat_slave(link, a + c);
}
}
}
void fermat(link_t **link, long x){
long tmp = x;
if(x != 2){
if(x % 2 == 0){
long *two = malloc(sizeof(long));
if(two == NULL) exit(EXIT_FAILURE);
*two = 2; link_enqueue(link, two);
x /= 2;
while(x % 2 == 0){
x /= 2;
}
}
fermat_slave(link, x);
if(*(long *) (*link)->data == tmp){
link_dequeue(link);
}
}
}
void *consumer(void *arg){
char *space = malloc(sizeof(char)), *new_line = malloc(sizeof(char));
if(space == NULL) exit(EXIT_FAILURE); if(new_line == NULL) exit(EXIT_FAILURE);
*space = ' '; *new_line = '\n';
buffer_t *bf = (buffer_t *) arg;
while(1){
long value = buffer_get(bf);
if(value < 0){ break; } // IF BUFFER SIGNALS END THEN QUIT
link_t *line = link_init(NULL);
fermat(&line, value);
// modif here
pthread_mutex_lock(&bf->out->mutex);
word_t *first = long_to_str(value);
write(bf->out->file_descriptor, first->str, first->len);
while(line->data){
word_t *out = long_to_str(*(long *) link_dequeue(&line));
write(bf->out->file_descriptor, space, 1);
write(bf->out->file_descriptor, out->str, out->len);
word_destroy(out);
}
write(bf->out->file_descriptor, new_line, 1);
pthread_mutex_unlock(&bf->out->mutex);
}
free(space); free(new_line);
return NULL;
}
// gcc implem.c -o files/implem -lpthread -lm
// ./files/implem test_input.txt files/implem.txt
// valgrind --leak-check=yes ./files/implem files/example_input.txt files/ouput.txt
int main(int argc, char const *argv[]){
pthread_t threads[NT];
buffer_t *bf = buffer_init(argv[2]);
int input_fd = open(argv[1], O_RDONLY);
if(input_fd == -1) strerror(errno);
struct stat fs;
if(fstat(input_fd, &fs) == -1){ strerror(errno); close(input_fd); }
char *proj = mmap(NULL, fs.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
if(proj == MAP_FAILED){ strerror(errno); close(input_fd); }
// BOOTING CONSUMERS
for(uint8_t t = 0; t < NT; t++){
if(pthread_create(&threads[t], NULL, consumer, bf)){
printf("Error while creating a thread \n"); exit(EXIT_FAILURE);
}
}
long current = 0;
size_t len = fs.st_size / sizeof(char);
for(size_t i = 0; i < len; i++){
if(proj[i] != '\r'){
long tmp = proj[i] - '0';
if(0 <= tmp && tmp <= 9){
current = (current * 10) + tmp;
}
else{
printf("Wrong file format \n"); exit(EXIT_FAILURE);
}
}
else{
buffer_put(bf, current);
current = 0;
i++;
}
}
// ENDING CONSUMERS ACTIVITY
for(uint8_t t = 0; t < NT; t++){ buffer_put(bf, -1); }
for(uint8_t t = 0; t < NT; t++){
if(pthread_join(threads[t], NULL)){
printf("Error on joining !"); exit(EXIT_FAILURE);
}
}
// TERMINATE TODO: HANDLE MEMORY PROPERLY
buffer_destroy(bf);
if(munmap(proj, fs.st_size) == -1)
strerror(errno); close(input_fd);
if(close(input_fd) == -1)
strerror(errno);
return 0;
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter