[](https://classroom.github.com/online_ide?assignment_repo_id=16344778&assignment_repo_type=AssignmentRepo) # Etapa 3 - Projeto PPC ## Equipe responsável: * Nayla Sahra Santos das Chagas - 202000024525 * Túlio Sousa de Gois - 202000024599 --- # Explicação da Integração do Sistema Produtor Consumidor com o Sistema de Relógios Vetoriais ## Solução A nossa solução implementa um sistema distribuído de relógios vetoriais usando MPI para comunicação entre processos e pthreads para concorrência dentro de cada processo. O sistema segue um modelo produtor-consumidor com buffers intermediários. * **Relógio Vetorial** O relógio vetorial é implementado como uma estrutura `VectorClock` que contém um array de inteiros. O tamanho deste array é igual ao número de processos no sistema (definido por `THREAD_NUM`). ```c typedef struct { int clock[THREAD_NUM]; } VectorClock; ``` * **Buffer** Dois buffers compartilhados são utilizados: `buffer_entrada` e `buffer_saida`. Ambos são arrays de `VectorClock` com tamanho fixo `BUFFER_SIZE`. ```c VectorClock buffer_entrada[BUFFER_SIZE]; VectorClock buffer_saida[BUFFER_SIZE]; ``` * **Sincronização** A sincronização é implementada usando mutexes e variáveis de condição para acessar os buffers, evitando condições de corrida: ```c pthread_mutex_t mutex_entrada, mutex_saida; pthread_cond_t can_produce_entrada, can_consume_entrada; pthread_cond_t can_produce_saida, can_consume_saida; ``` ### Componentes Principais 1. **Thread de Entrada** - Recebe mensagens via MPI - Atualiza o relógio vetorial local - Coloca o relógio atualizado no buffer de entrada 2. **Thread de Relógios** - Consome relógios do buffer de entrada - Atualiza o relógio local (evento local) - Coloca o relógio atualizado no buffer de saída 3. **Thread de Saída** - Consome relógios do buffer de saída - Envia o relógio para o próximo processo via MPI ### Funcionamento 1. **Inicialização** - O programa inicia `THREAD_NUM` processos MPI - Cada processo cria 3 threads: entrada, relógios e saída - O processo 0 envia uma mensagem inicial para iniciar o fluxo 2. **Comunicação** - Os processos formam um anel lógico - Cada processo envia mensagens para o próximo e recebe do anterior 3. **Atualização do Relógio** - Na recepção de uma mensagem, o relógio é atualizado com o máximo entre o local e o recebido - Um evento local incrementa apenas o contador do processo atual ### Cenários de teste Os cenários de teste estão implementados nas funções de cada thread. O cenário principal é o de buffer cheio/vazio, que é tratado usando as variáveis de condição. 1. **Buffer de Entrada Cheio** ```c while (buffer_entrada_count == BUFFER_SIZE) { printf("Processo %d: Thread Entrada - Fila cheia, aguardando...\n", rank); pthread_cond_wait(&can_produce_entrada, &mutex_entrada); } ``` 2. **Buffer de Saída Vazio** ```c while (buffer_saida_count == 0) { printf("Processo %d: Thread Saída - Fila de saída vazia, aguardando...\n", rank); pthread_cond_wait(&can_consume_saida, &mutex_saida); } ``` # Dificuldades encontradas - Sincronização das threads; - Validação do resultado dos relógios vetoriais;