/* * Codificação do algoritmo de Dijkstra (modificada * para ficar semelhante aos outros exemplos) * * Sleeps para induzir starvation. Colaboração de * Andre Luis Macedo * Marcelo Oliveira de Moraes * Thaís Almeida Brito Fernandes */ #include #include #include #include #define N 5 volatile int s = 0; /* Variável compartilhada */ volatile int vez = -1; /* Indica de qual thread tem prioridade entrar na região crítica */ volatile int interesse[N] = {0, 0, 0, 0, 0}; /* Indica quais threads estão interessadas em entrar na região crítica */ volatile int quantasVezesExecutei[ N ] = { 0, 0, 0, 0, 0 }; volatile int contadorRecursos = 50; int existe_outra_interessada(int thr_id) { int i; for (i = 0; i < N; i++) if (i != thr_id && interesse[i]) return 1; return 0; } void* f_thread(void *v) { int thr_id = *(int*)v; while ( 1 ) { interesse[thr_id] = 1; /* Marca que esta thread está interessada */ /* Aqui vamos sincronizar todas as threads, para garantir que todas tenham interesse.*/ sleep(1); while (existe_outra_interessada(thr_id)){ if (vez != thr_id) { /* Todas dormem, para que todas entrem na trava.*/ sleep( 1 ); interesse[thr_id] = 0; while (vez != -1); /*Garante que a thread 1 sempre é a primeira a pegar a vez*/ if( thr_id == 1 ) sleep( 1 ); else sleep( 2 ); vez = thr_id; /*Sincroniza novamente todas as threads*/ if( thr_id == 1 ) sleep( 2 ); else sleep( 1 ); interesse[thr_id] = 1; sleep(1); } } if( contadorRecursos <= 0 ) { vez = -1; interesse[thr_id] = 0; return NULL; } s = thr_id; printf("Thread %d, s = %d.\n", thr_id, s); quantasVezesExecutei[ thr_id ] ++; contadorRecursos --; vez = -1; interesse[thr_id] = 0; /* Marca que saiu da região crítica */ sleep(1); /* Deixa outra thread executar */ } return NULL; } int main() { pthread_t thr[N]; int id[N], i; for (i = 0; i < N; i++) { id[i] = i; pthread_create(&thr[i], NULL, f_thread, &id[i]); } for (i = 0; i < N; i++) pthread_join(thr[i], NULL); for( i = 0; i < N; i ++ ) { printf( "Thread %d executou %d vezes\n", i, quantasVezesExecutei[ i ] ); } return 0; }