моя C-программа, использующая pthreads, застревает, и я не могу понять, почему - PullRequest
0 голосов
/ 19 мая 2019

Кажется, я не вижу, в чем проблема моей программы, она выполняет все мои вычисления, но в какой-то момент застревает.и я не могу понять, какие-либо рекомендации?

сначала я определяю структуру

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>

int barreira;
int *buffer;
int items_buffer;
int bloqueio_buffer;
int soma_global;

typedef struct {

  pthread_mutex_t * mutex;
  pthread_cond_t * cond;
  pthread_cond_t * produzir;
  pthread_cond_t * consumir;

  int * matriz;
  int numero_thread;
  int inicio;
  int interacoes;

}estrutura_geral;

void * funcao_calculadora(void *);
void * funcao_somadora(void *);

Кажется, у меня все нормально, возможно, проблема в том, что функции void не работают правильно

    int main(int argc, char ** argv){

  int i, n, nt, nbloco, nsomadores;

  n=atoi(argv[2]);
  nt=atoi(argv[1]);
  nbloco=atoi(argv[3]);
  nsomadores=1;
  barreira=n+1;

  if(argc!=4){
      printf("Utilização: ./mtss nt n nbloco\n");
      exit(1);}

    if(nt<1){
      printf("O numero de processos terá que ser pelo menos 1\n");
      exit(1);}

    if(n<1||n>999){
      printf("O n tem que estar compreendido entre 1 e 999\n");
      exit(1);}

   if(nbloco<1){
      printf("O bloco tem que ser pelo menos 1\n");
      exit(1);
  }
    if(n<nt){
    nt = n;
  }

  pthread_t * calculadoras = malloc(sizeof(pthread_t)*nt);
  pthread_t * somadoras = malloc(sizeof(pthread_t)*nsomadores);

  estrutura_geral * estrutura = malloc(sizeof(estrutura_geral));

  estrutura->mutex = malloc(sizeof(pthread_mutex_t));
  pthread_mutex_init(estrutura->mutex,NULL);

  estrutura->cond = malloc(sizeof(pthread_cond_t));
  pthread_cond_init(estrutura->cond,NULL);

  estrutura->produzir = malloc(sizeof(pthread_cond_t));
  estrutura->consumir = malloc(sizeof(pthread_cond_t));

  estrutura->matriz = malloc(sizeof(int)*n);
  buffer = malloc(sizeof(int)*nt);
  soma_global = 0;
  items_buffer=0;
  bloqueio_buffer=nt;

  for(i=0;i<n;++i)
    estrutura->matriz[i]=i+1;

  pthread_mutex_lock(estrutura->mutex);

  estrutura->interacoes = nbloco;
  if(nbloco==n&&n==nt){
    estrutura->interacoes =1;  
  }
  if(nbloco<n/nt || nbloco>n/nt){
      estrutura->interacoes =n/nt;
  }
  estrutura->numero_thread = 0;

  for(i=0;i<nsomadores;++i){

    pthread_create(&somadoras[i],NULL,funcao_somadora,estrutura);

    pthread_cond_wait(estrutura->cond,estrutura->mutex);
  }

  for(i=0;i<nt;++i){

    pthread_create(&calculadoras[i],NULL,funcao_calculadora,estrutura);

    ++estrutura->numero_thread;
    estrutura->inicio = i*estrutura->interacoes;

    if(i==(nt-1) && n%nt)
      estrutura->interacoes = n-estrutura->interacoes*i;

    pthread_cond_wait(estrutura->cond,estrutura->mutex);
  }


  pthread_mutex_unlock(estrutura->mutex);

     for(i=0;i<nt;++i){
     pthread_join(calculadoras[i],NULL);}

     for(i=0;i<nsomadores;++i){
     pthread_join(somadoras[i],NULL);}

  printf("A soma do quadrado dos numeros de 1 to %d e %d\n", n,soma_global);

  free(estrutura->matriz);

  free(buffer);

  pthread_cond_destroy(estrutura->cond);
  free(estrutura->cond);

  pthread_cond_destroy(estrutura->produzir);
  free(estrutura->produzir);

  pthread_cond_destroy(estrutura->consumir);
  free(estrutura->consumir);


  pthread_mutex_destroy(estrutura->mutex);
  free(estrutura->mutex);

  free(estrutura);

  free(calculadoras);
  free(somadoras);

  return 0;

}

это мои первые функции, он действует как калькулятор, который выдает дату в буфер, который будет потребляться из другого потока, являющегося потребителем

void * funcao_calculadora(void * ts){

  int i, soma_parcial = 0;

  estrutura_geral * const estrutura = ts;

  pthread_mutex_lock(estrutura->mutex);

  int * const matriz = estrutura->matriz;
  int const numero_thread = estrutura->numero_thread;
  int const inicio = estrutura->inicio;
  int const interacoes = estrutura->interacoes;

  pthread_cond_signal(estrutura->cond);

  pthread_mutex_unlock(estrutura->mutex);

  int const end = interacoes + inicio;

  for(i=inicio;i<end;++i){
      pthread_mutex_lock(estrutura->mutex);
      while(items_buffer == bloqueio_buffer) {
            pthread_cond_wait(estrutura->produzir, estrutura->mutex);
        } 

    soma_parcial += matriz[i]*matriz[i];
    buffer[items_buffer]=soma_parcial;
    items_buffer++;

    printf("A thread %d: calculou a soma dos quadrados do bloco de %d to %d, que a soma e %d, estão %d elemnetos no buffer\n",numero_thread,inicio+1,end,soma_parcial, items_buffer);

    pthread_cond_signal(estrutura->consumir);
    pthread_mutex_unlock(estrutura->mutex);
  }

  printf("A Thread %u de saida\n",numero_thread);
  pthread_exit(NULL);

}

Это моя функция потребителяпотребляет данные и очищает буфер, поскольку он потребляет данные.

void * funcao_somadora(void * es){

  int i;

  estrutura_geral * const estrutura = es;

  pthread_mutex_lock(estrutura->mutex);

  pthread_cond_signal(estrutura->cond);

  pthread_mutex_unlock(estrutura->mutex);

  for(i=0;i<barreira;++i){
  pthread_mutex_lock(estrutura->mutex);
    while(items_buffer == 0) {
            pthread_cond_wait(estrutura->consumir, estrutura->mutex);
  }

     soma_global+=buffer[items_buffer];
     items_buffer--;

     printf("A thread somadora: somou %d, existem %d elemnetos no buffer\n",buffer[items_buffer],items_buffer);

    if(items_buffer==0){
    sched_yield();
    //pthread_cond_signal(estrutura->produzir);

    }
    pthread_mutex_unlock(estrutura->mutex);    

}
  printf("A tarefa somadora está de saída\n");
  pthread_exit(NULL);

}
...