/****************************************************************************** * Grupo: * * Gustavo Sverzut Barbieri * * Ivens Prates Telles Alves * * Tiago Moreira de Melo * ****************************************************************************** * * * Solução para o problema dos filósofos famintos * * * * Idéia: * * Se fecharmos a mesa para apenas N-1 filósofos, sempre haverá ao menos* * um filósofo comendo e portanto o sistema não entra em deadlock. Também * * pode-se pensar que por existirem N-1 filósofos e N garfos, a situação de* * deadlock do problema anterior nunca ocorrerá pois se todos os filósofos * * pegarem o garfo da esquerda, ainda haverá um filósofo que conseguirá * * o garfo da direita, alimentando-se então. * * * ****************************************************************************** * * * This code is documented using the Doxygen tags, so you can run: * * doxygen Doxyfile * * If "Doxyfile" doesn't exist you may create one using doxywizard * * You can get Doxygen at: http://www.doxygen.org * * * ****************************************************************************** * * * Libraries used: * * - pthread * * Compilation Example: * * gcc -g 02_nodeadlock-alt.c -o 02_nodeadlock-alt -lpthread * * * ****************************************************************************** * (C) GPL - General Public License * * http://www.fsf.org * ****************************************************************************** */ #include "02_nodeadlock-alt.h" void *pthread_philosopher( void *p ) { int i = *(int *)p; philosopher(i); return NULL; } void philosopher( int i ) { while ( meals < MAX_MEALS ) { think( i ); take_forks( i ); eat( i ); put_forks( i ); } } void think(int i) { /* think */ sleep( 1 ); } void eat(int i) { meals++; /* note: here we are not using a MUTEX because if we have some meals more doesn't matter at all. */ /* eat */ sleep( 1 ); } void take_forks( int i ) { /* * Say he is HUNGRY */ /* "lock" the table (table was init with value N-1) */ sem_wait( &table ); /* if printing, wait. If not, continue, blocking the printing */ sem_wait( &printing ); /* Say he is hungry */ state[ i ] = HUNGRY ; /* Print the table */ print_table(); /* signal others can print */ sem_post( &printing ); /* * Get the forks */ /* get the right fork */ sem_wait( &forks[ ( i + 1 ) % N ] ); forks_position[ ( i + 1 ) % N] = '<'; /** * Here is almost the deadlock case of the first problem (01_deadlock) * however since there is N-1 philosophers N forks, if all the philosophers * get they left fork, still one will be able to get his right fork, not going * into deadlock, but only one philosopher will be able do eat. */ sleep( 1 ); /* get the left fork */ sem_wait( &forks[ i ] ); forks_position[ i ] = '>'; /* if printing, wait. If not, continue, blocking the printing */ sem_wait( &printing ); /* Say he is eating */ state[ i ] = EATING ; /* Print the table */ print_table(); /* signal others can print */ sem_post( &printing ); } void put_forks( int i ) { /* if printing, wait. If not, continue, blocking the printing */ sem_wait( &printing ); /* * Put the forks */ /* put the left fork */ sem_post( &forks[ i ] ); forks_position[ i ] = '|'; /* put the right fork */ sem_post( &forks[ ( i + 1 ) % N ] ); forks_position[ ( i + 1 ) % N ] = '|'; /* * change state to thinking, since we're not eating anymore */ /* Say he is thinking */ state[ i ] = THINKING ; /* Print the table */ print_table(); /* signal others can print */ sem_post( &printing ); /* "unlock" the table */ sem_post( &table ); } void print_table() { int i; /* print the philosophers states */ for ( i = 0; i < N; i++ ) { switch ( forks_position[ i ] ) { case '|': printf( " | " ); break; case '>': printf( " >" ); break; case '<': if ( i == 0 ) printf( " " ); else printf( "< " ); break; default: break; } #ifndef COLOR printf( "%c", state_letters[ state[ i ] ] ); #else switch (state[ i ]) { case HUNGRY: printf( "\033[0;31m" ); break; case THINKING: printf( "\033[1;33m" ); break; case EATING: printf( "\033[0;32m" ); break; default: break; } printf( "%c\033[0m", state_letters[ state[ i ] ] ); #endif if ( ( i == N - 1 ) && ( forks_position[ ( i + 1 ) % N ] == '<' ) ) printf( "<"); } printf( "\n" ); } /** * The main program */ int main() { int i; /* general counter */ pthread_t threads[ N ]; /* philosopher/thread */ int id[ N ]; /* philosopher/thread id */ /* * Init */ for ( i = 0; i < N; i++ ) { /* forks semaphores */ sem_init( &forks[ i ], 0, 1 ); /* forks position */ forks_position[ i ] = '|'; } /* printing semaphore */ sem_init( &printing, 0, 1 ); /* init the table, allow only N-1 philosophers */ sem_init( &table, 0, N-1 ); /* states */ for ( i = 0; i < N; i++ ) state[i] = THINKING ; /* print the table */ print_table(); /* * Lauch threads */ for ( i = 0; i < N; i++ ) { id[ i ] = i ; pthread_create( &threads[ i ], NULL, pthread_philosopher , &id[ i ] ); } /* * Wait for threads */ for ( i = 0; i < N; i++ ) { pthread_join( threads[ i ], NULL ); } return 0; } /* author: Gustavo Sverzut Barbieri (http://www.gustavobarbieri.com.br) */