1
#include <pthread.h>
#include <stdio.h>

typedef struct {
   int id;
   char *filename;
   float sum;
   float dif;
} child;

void *calData(void *argv){

   child *tempChild = (child *) argv;
   FILE *fp;
   int id = tempChild->id;
   float max, min,buffer, sum , dif;

   if(fopen(tempChild->filename, "r") == NULL) {
       printf("Fail to open file");
       exit(1);
   }
   fp = fopen(tempChild->filename, "r");
   fscanf(fp, "%f", &buffer);
   /* initialize the max and min */
   max = buffer;
   min = buffer;
   /* scan every element in the dataset */
   while(!feof(fp)) {
       fscanf(fp, "%f", &buffer);
       if(buffer <= min) {
           min = buffer;
       }  
       if(buffer >= max) {
           max = buffer;
       }
   }
   fclose(fp);  
   /* pass the calculted results to child */
   sum = max + min;
   dif = max - min;

   tempChild->sum = sum;
   tempChild->dif = dif;
   printf("%.5f  %.5f %.5f\n", sum, dif, id);
  }

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

     /* initialize the of memory size of threads and children */
     pthread_t *threads;
     threads = (pthread_t *) malloc((argc-1) * sizeof(*threads));
     child *children;
     children = (child *) malloc((sizeof(child)) * (argc - 1));
     int i, j;

     /* start the threads */
     for(i=0; i < (argc - 1); i++)
     {
          children[i].id = i;
          children[i].filename = argv[i+1];
          pthread_create(threads+i, NULL, calData, (void *)children+i);
     }
    /* Synchronize the completion of each thread. */
    for(j=0; j < (argc-1); j++){
       pthread_join(threads[j], NULL);
    }
    printf("%.5f  %.5f \n",children[0].sum, children[0].dif);
 }

Hi, I am learning pthread. Here is the question, as you might see in the code, the input should consist of 3 txt file, and I want to process them and get the sum and dif by pthread. However, one input argument was okay, but it kept say 'fail to open file' when I tried to input 3 data file.

I searched that I might need some help with mutexes, can anyone tell me how to fix it?

P.P
  • 117,907
  • 20
  • 175
  • 238
Rob Ye
  • 63
  • 1
  • 7
  • Your code is seemed correct. Probably filename, passed as 3d argument, is incorrect. What is error code(value of `errno` variable) when 'fail to open file' occures? – Tsyvarev Jun 21 '15 at 21:20

2 Answers2

1

I suspect the problem is with how you pass the argument to the thread:

pthread_create(threads+i, NULL, calData, (void *)children+i);

Since cast operator has higher precedence than +, children is cast to void* first and i is add (note gcc allows pointer arithmetic on void pointers). Resulting in incorrect pointer value except for the first thread.

Instead try:

pthread_create(threads+i, NULL, calData, (void *)(children+i));

or

pthread_create(threads+i, NULL, calData, (void *)&children[i]);

Other issues:

  1. Don't case the return value of malloc. It's potentially dangerous.
  2. while(!feof(fp)) { is almost certainly not what you want. Your loop would run one more time than you wanted. See Why is “while ( !feof (file) )” always wrong?
Community
  • 1
  • 1
P.P
  • 117,907
  • 20
  • 175
  • 238
1

Here is obvious first problem:

pthread_create(threads+i, NULL, calData, (void *)children+i);

Check operations priority in C and replace it with:

pthread_create(threads+i, NULL, calData, (void *)(children + i));

Your address ariphmetics + operator has lower priority than (void *) type cast so children is incremented by i bytes instead of i child structure sizes.

But actually, if your C compiler permits, I do recommend to switch from pointers to arrays in your case. Much more safe so here is your main():

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

     pthread_t threads[argc -1];
     child children[argc - 1];

     int i, j;

     /* start the threads */
     for(i=0; i < (argc - 1); i++)
     {
          children[i].id = i;
          children[i].filename = argv[i+1];
          pthread_create(&threads[i], NULL, calData, &children[i]);
     }

    /* Synchronize the completion of each thread. */
    for(j=0; j < (argc-1); j++){
       pthread_join(threads[j], NULL);
    }
    printf("%.5f  %.5f \n",children[0].sum, children[0].dif);
}
Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
  • 1
    @user3804023: So why not then accept this answer, as answer to your question? – alk Jun 28 '15 at 11:55