Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pthread.h>
- #include <stdio.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <unistd.h>
- /* Macros */
- #define print_info \
- printf("*** Type q, then press ret to exit!\n"); \
- sleep(3)
- #define ec_zero(s,m) \
- if((s) != 0){perror(m); exit(err);}
- #define ec_killing(s,m) \
- if((s) != 0){printf("WARNING: Couldn't kill this thread: %d\n",m);}
- #define ec_null(s,m) \
- if((s) == NULL){perror(m); exit (errno);}
- #define LOCK(s) {ec_zero((pthread_mutex_lock(&s)),("Couldn't lock"))}
- #define UNLOCK(s) {ec_zero((err=pthread_mutex_unlock(&s)),("Couldn't unlock"))}
- #define WAIT(s,m) {ec_zero((err=pthread_cond_wait(&s,&m)),("Couldn't wait"))}
- #define SIGNAL(s) {ec_zero((err=pthread_cond_signal(&s)),("Couldn't send signal"))}
- /* Dichiarazione di variabile mutex ed array di condition*/
- pthread_cond_t *cond_array = NULL;
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- /* Dichiarazione variabili e array globali*/
- static int N;
- int *fks;
- pthread_t *tid_array = NULL;
- /* Dichiarazione funzioni */
- void* phi(void* args);
- void gcollector();
- static void cleanup_handler(void* arg);
- int main(){
- int i, err;
- char ctrl = NULL;
- /* Ricevo in input il numero ed alloco dinamicamente un array di tid */
- printf("Please tell me how many philosophes you want at the table...\n");
- scanf("%d",&N);
- ec_null((tid_array = (pthread_t*) malloc(N*sizeof(pthread_t))),"Couldn't allocate tid array");
- /* Creo i threads filosofo salvando i tid nell'array predisposto */
- for(i=0;i<N;i++){
- ec_zero((err = pthread_create(&tid_array[i], NULL, &phi, (void*) i)),"Couldn't create a thread");
- printf("*** Philosopher no. %d created !\n",i);
- }
- /* Creo l' array di conditions e le inizializzo */
- ec_null((cond_array = (pthread_cond_t*) malloc(N*sizeof(pthread_cond_t))),"Couldn't allocate cond array");
- for(i=0;i<N;i++) ec_zero((pthread_cond_init(&cond_array[i], NULL)),"Couln't initialize a condition");
- /* Creo l'array di stato e lo inizializzo */
- ec_null((fks = (int*) malloc(N*sizeof(int))),"Couldn't allocate forks's status array");
- for(i=0;i<N;i++) fks[i]=0;
- /* Condizione di terminazione del programma */
- while(ctrl != 'q'){
- scanf("%c",&ctrl);
- if(ctrl!='q') {print_info;}
- else{
- /* Uccido i threads */
- for(i=0;i<N;i++){
- printf("*** Killing the philosopher no. %d !\n",i);
- ec_killing((err = pthread_cancel(tid_array[i])),i);
- }
- /* Invoco la atextit */
- if(atexit(gcollector)) perror("Atexit failed! Possible memory leak\n");
- return 0;
- }
- }
- return ECANCELED;
- }
- /* Implementazione della funzione filosofo */
- void* phi(void *args){
- pthread_cleanup_push(cleanup_handler,NULL);
- while(1){
- /* Recupero l'identità del filosofo */
- int my_id = (int) args, err;
- /* Fase 1 : il filosofo è affamato */
- LOCK(mutex);
- printf("# I'm %d and I'm hungry!\n",my_id);
- /* Testo le var di condizione sulle forchette*/
- while(fks[((my_id)%N)] || fks[((my_id+1)%N)]) WAIT(cond_array[my_id],mutex);
- /* Occupo le forchette */
- fks[((my_id)%N)]=1;
- fks[((my_id+1)%N)]=1;
- UNLOCK(mutex);
- /* Fase 2 : il filosofo mangia se può */
- printf("# I'm %d and I'm eating spaghetti!\n",my_id);
- sleep(3);
- LOCK(mutex);
- /* Libero le forchette */
- fks[((my_id)%N)]=0;
- fks[((my_id+1)%N)]=0;
- /* Invio le signal alle var di condizione */
- SIGNAL(cond_array[((my_id-1)%N)]);
- SIGNAL(cond_array[((my_id+1)%N)]);
- UNLOCK(mutex);
- /* Fase 3 : il filosofo pensa */
- printf("# I'm %d and I'm pondering about the meaning of life!\n",my_id);
- sleep(3);
- }
- pthread_cleanup_pop(0);
- return (void*) 0;
- }
- /* Implementazione della funzione spazzino */
- void gcollector(){
- printf("*** Collecting some garbage...\n");
- free(tid_array);
- free(cond_array);
- free(fks);
- printf("Bye!\n");
- }
- static void cleanup_handler(void* arg){
- int err =0;
- printf("*** Running cleanup handler...\n");
- UNLOCK(mutex);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement