philosophers.c
codice:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>

#define N 5
#define MUTEX N
#define LOCK_STDOUT N + 1
#define POLL_INTERVAL 2

#define THINKING	0
#define HUNGRY 		1
#define EATING 		2

#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
       /* union semun is defined by including <sys/sem.h> */
       #else
       /* according to X/OPEN we have to define it ourselves */
       union semun {
               int val;                    /* value for SETVAL */
               struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
               unsigned short int *array;  /* array for GETALL, SETALL */
               struct seminfo *__buf;      /* buffer for IPC_INFO */
       };
#endif

int semid;
int shmid;

struct statistica
{
	int state;
	time_t sec;
	int eat;
}*State;

void down(int i);
void up(int i);
void think();
void eat ();
void poll_status();
void sigterm_hdl(int n);
void take_forks(int i);
void put_forks(int i);
void test(int i);
void philosopher(int i);

void poll_status()
{
    int i;
    int t;
    char *messages[] = {"THINKING", "HUNGRY", "EATING"};

    signal(SIGTERM, sigterm_hdl);
    down(MUTEX);    
	printf("Processo poll pid %d\n", getpid());
    up(MUTEX);
    while(1)
    {
        down(MUTEX);
        for(i=0; i<N;i++)
        {
            /*wmove(stdscr,i+1,1);*/
            printf("filosofo %2d: %8s %6d", i, messages[State[i].state], State[i].eat);
            if(State[i].state == HUNGRY)
            	printf(" %3d\n", time(NULL) - State[i].sec);            
            else
            	printf("\n");

           /* wrefresh(stdscr);*/
        }
        printf("premere invio per terminare\n\n");	
        up(MUTEX);
        sleep(POLL_INTERVAL);
    }
}


void think ()
{    
   sleep(3);   
}

void eat ()
{      
   sleep(3);   
}


void down(int i)
{
    struct sembuf g_lock_sembuf;
    g_lock_sembuf.sem_num   =  i;
    g_lock_sembuf.sem_op    = -1;
    g_lock_sembuf.sem_flg   =  0;
    if(semop(semid, &g_lock_sembuf, 1) == -1)
    {	
    	perror("semop fallita "); 
	exit(1);
    }
    if(i == MUTEX)
    {
    	printf("*************** %d in sezione critica\n" , getpid());
    	fflush(stdout);
    }
}

void up(int i)
{
    struct sembuf g_lock_sembuf;
    g_lock_sembuf.sem_num   = i;
    g_lock_sembuf.sem_op    = 1;
    g_lock_sembuf.sem_flg   = 0;
    if(semop(semid, &g_lock_sembuf, 1) == -1)
    {	
   	perror("semop fallita ");
	exit(1);
    }
    if(i == MUTEX)
    {
    	printf("+++++++++++++++ %d lascia sezione critica\n" , getpid());
    	    	fflush(stdout);
    }
}
int main ()
{
   ushort sems[N+1];
   int i, j, ActiveProcesses=0; 
   pid_t PIDS[N+1];   
   int retcode = 0;   
     
   union semun {			
      int val;
      struct semid_ds *stat;
      ushort *array;
    } ctl_arg;

   semid = shmid = -1;

   /*initscr();
   wclear(stdscr);*/
   
   srand(time(NULL));   

   ctl_arg.array = sems;

   semid = semget(0, N+1,  0666 |  IPC_PRIVATE);   
   
   if (semid == -1)
   {
       perror  ("Impossibile ottenere semafori dal sistema.");
       retcode = 1;
       goto cleanup;
   }
   else
   {
   	printf("semafori creati\n");
   }
   
   shmid = shmget(0, N*sizeof(struct statistica),  0666 |  IPC_PRIVATE);
   
   if(shmid == -1)
   {
   	perror("Impossibile allocare memoria condivisa\n");
   	retcode = 2;
   	goto cleanup;
   }
   else
   {
   	printf("memoria condivisa creata\n");
   }
   	
   for(i=0; i<N+1; i++)
	sems[i]=0;
	
   if(semctl(semid, 0, SETALL, ctl_arg)==-1)
   {
   	perror("Impossibile impostare i semafori");
   	retcode = 2;
   	goto cleanup;
   }    
   else
   {
   	printf("semafori inizializzati\n");
   }	
   
   State = (struct statistica*) shmat(shmid, 0, 0);
   

   printf("Processo main pid %d\n", getpid());


   //il mutex è down i base all'inizializzazione
 
   for(ActiveProcesses=0, i=0; i<N;i++, ActiveProcesses++)
   {
       PIDS[i] = fork();
       {
           if(PIDS[i]==-1)
           {
           	fprintf(stderr, "Impossibile creare il processo %d\n", i);
           	retcode = 3;
           	goto cleanup;
           }
           else if(PIDS[i] == 0)
           {
           	State[i].state = 0;
           	State[i].sec = 0;
           	State[i].eat = 0;
           	philosopher(i); //il filosofo non parte finchè mutex down 
           }
       }       
   }	   
       
   PIDS[i] = fork();
   {
      if(PIDS[i]==-1)
      {
          fprintf(stderr, "Impossibile creare il processo %d\n", i);
          retcode = 3;
          goto cleanup;
      }
      else if(PIDS[i] == 0)
      {
          poll_status(); /*Inizia il polling dello stato dei filosofi*/
      }
   }
   
   ActiveProcesses++;   
   /*wmove(stdscr, i, 1);   */
   printf("Premere invio per terminare\n\n");   
   /*wrefresh(stdscr);*/
   up(MUTEX);
   
   getchar(); 
cleanup:  

   
   
   for(i=0;i<ActiveProcesses;i++) //raccoglie retcode di tutti i figli
   {
   	kill(PIDS[i], SIGTERM); //avvisa tutti i figli di terminare
	fprintf(stderr, "waitpid %d ", PIDS[i]);
	if(waitpid(PIDS[i], &j, 0)==-1)
		perror("waitpid fallita\n");
	else
		fprintf(stderr, "= %d\n", j);
   }

   if(semid!=-1 && semctl(semid, 0, IPC_RMID, 0)==-1) //rimuove semafori
	perror("impossibile rimuovere set di semafori\n");
   else printf("Semafori chiusi\n");
	
   if(shmid!=-1 && shmctl(shmid, 0, IPC_RMID, 0)==-1) //rimuove memoria condivisa
	perror("Impossibile rimuovere memoria condivisa\n");
   else printf("Memoria condivisa liberata\n");
   		
   /*endwin();*/	//dealloca il terminale virtuale
   return retcode;    
}


void philosopher (int i)
{
   signal(SIGTERM, sigterm_hdl);
   down(MUTEX);
   printf("Salve, sono il filosofo %d con pid %d\n", i, getpid());
   up(MUTEX);
   while(1)
   {
   	think();
   	take_forks(i);
   	eat();
   	put_forks(i);
   }   
}

void take_forks(int i)
{
    down(MUTEX);
    State[i].state = HUNGRY;
    State[i].sec = time(NULL);
    test(i);
    up(MUTEX);
    down(i);	
}

#define LEFT  (i-1)%N
#define RIGHT  (i+1)%N

void put_forks(int i)
{
    down(MUTEX);
    State[i].state = THINKING;
    test(LEFT);
    test(RIGHT);
    up(MUTEX);
}



void test(int i)
{
    if(State[i].state == HUNGRY && State[LEFT].state!= EATING && State[RIGHT].state!=EATING)
    {
    	State[i].state = EATING;
    	State[i].sec = 0;
    	State[i].eat ++;
    	up(i);
    }
}


void sigterm_hdl(int n)
{	
	exit(0);
}