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

Upload New File

parent a73ee42f
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
#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>
int NT;
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 third.c -o files/third -lpthread -lm
// ./files/third files/example_input.txt files/third.txt
// valgrind --leak-check=yes ./files/third files/example_input.txt files/ouput.txt
int normalMode(int n, const char *to_open, const char *to_create){
NT = n;
pthread_t threads[NT];
buffer_t *bf = buffer_init(to_create);
int input_fd = open(to_open, 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] != '\n'){
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;
}
}
// 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;
}
\ No newline at end of file
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