/*
 * Algoritmo do desempate para N threads (sem campeonato).
 */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define N 5         /* Número de threads */
#define N_VEZES 10  /* Número de acessos por thread
		       à região crítica */

volatile int s = 0; /* Variável compartilhada */

volatile int interesse[N]; /* Indica se as threads estão ou 
			      não interessadas em entrar na região crítica */
volatile int fase[N]; /* Indica a fase da disputa desta thread */
volatile int vez[N-1]; /* Indica qual thread fez a atribuição
			  por último em cada fase */

/* Função executada pelas threads */
void* f_thread(void *v) {
  int thr_id = *(int *)v;
  int n_vezes, j, f; 

  for (n_vezes = 0; n_vezes < N_VEZES; n_vezes++) {
    interesse[thr_id] = 1;
    sleep(1); /* Todas podem ficar interessadas */
    for (f = 0; f < N-1; f++) {
      fase[thr_id] = f;
      vez[f] = thr_id; 
      for (j = 0; j < N && vez[f] == thr_id; j++)
	if (j != thr_id && interesse[j])
	  while (fase[j] >= f && vez[f] == thr_id); 
    }
    
    s = thr_id;
    sleep(1);
    printf("Thread %d, s = %d.\n", thr_id, s); 
  
    interesse[thr_id] = 0;
    fase[thr_id] = -1;
  }
  return NULL;
}

int main() {
  pthread_t thr[N];
  int i, id[N];

  for (i = 0; i < N; i++) {
    interesse[i] = 0;
    fase[i] = -1;
  }
 
  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); 

  return 0;
}