Pthread_create hangs

Hi,

My code gets stuck after pthread_create. The funtion which is supposed to be called by pthread is not being called.Any idea?

Actually if i remove the join method it goes ahead but still the function is NOT called.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <float.h>
#include <pthread.h>

/* function prototupes */
int **k_means(double ***data, int height, int width, int m);

void allocate_2D_int_matrix (int ***matrix, int dim0, int dim1);
void free_2D_int_matrix (int ***matrix);
void allocate_2D_double_matrix (double ***matrix, int dim0, int dim1);
void free_2D_double_matrix (double ***matrix);
void free_3D_double_matrix (double ****matrix);
void allocate_3D_double_matrix (double ****matrix,int dim0, int dim1, int dim2);
struct commonvariables
{
    double **c;
    double **c1;    

    int *counts;   
    int **labels;   
    double ***data;
    int nchannels;
    int nclusters;
    double error;
    int height;
    int width;
};

struct commonvariables var1;
/* Pthread variables */
#define MAX_NUM_THREADS 8
pthread_mutex_t mymutex;
int num_threads;

/* constants */
#define NUM_CHANNELS 24


int main(int argc, char **argv) 
{
  int height, width;
  int **labels=NULL;
  FILE *fpa;
  double ***data;
  /*
  ** Step 1: determine what we have to do
  */
  if (argc != 6 ) {
    printf("usage: %s <inputfile> <outputfile> <height> <width> <number of threads> \n", argv[0]);
    exit(0);
  }

  /* argv[1] is name of the input file name */
  /* argv[2] is name of the output file name */
  /* argv[3] is height of image */
  /* argv[4] is width of image */
  height = atoi ( argv[3]);
  width  = atoi ( argv[4]); 
  num_threads= atoi ( argv[5]);
  /*
  ** Step 2: read the image from file
  */
  allocate_3D_double_matrix ( &data, height, width, NUM_CHANNELS );
  fpa = fopen ( argv[1], "rb");
  fread ( &(data[0][0][0]), sizeof(double), height*width*NUM_CHANNELS, fpa);
  fclose ( fpa );

  /*
  ** Step 3: Perform k_means clustering over the data items
  */
  labels = k_means ( data, height, width, NUM_CHANNELS);
  
  /*
  ** Step 4:  write final output file
  */
  printf("Writing final result\n");
  fpa = fopen ( argv[2], "wb" );
  fwrite ( &(labels[0][0]), sizeof(int), height*width, fpa);
  fclose ( fpa);

  free_2D_int_matrix ( &labels);
  free_3D_double_matrix ( &data);
  return 0;
}

/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/


void *commonfunction(void *arg)
{
       
	printf("*********************************** %####################### %d",var1.height);

	int h, h1, h2, i, j; /* loop counters */
       
	//for (h = 0; h < n; h++) {
	for ( h1 = 0; h1 < var1.height; h1++) {
	  for ( h2 = 0; h2 < var1.width; h2++) {
	    /* identify the closest cluster */
	    double min_distance = DBL_MAX;
	    for (i = 0; i < var1.nclusters; i++) {
	      double distance = 0;
	      for (j = 0; j<var1.nchannels; j++ ) {
		distance += pow(var1.data[h1][h2][j] - var1.c[i][j], 2);
	      }

		pthread_mutex_lock(&mymutex);

	      if (distance < min_distance) {
		var1.labels[h1][h2] = i;
		min_distance = distance;
	      }
	    }
	    
	    /* update size and temp centroid of the destination cluster */
	    for (j = 0; j<var1.nchannels; j++) {
	      var1.c1[var1.labels[h1][h2]][j] += var1.data[h1][h2][j];
	    }
	    var1.counts[var1.labels[h1][h2]]++;
	    
	    /* update standard error */
	    var1.error += min_distance;
	pthread_mutex_unlock(&mymutex);
	  }
	}

}

int **k_means(double ***data, int height, int width, int nchannels)
{
    pthread_t threads[MAX_NUM_THREADS];
       pthread_attr_t threadAttribute;
	pthread_mutex_init(&mymutex,NULL);

    int n=height*width;
    int nclusters=5; /* number of clusters to be formed */
int h, h1, h2, i, j; /* loop counters */

    double t=1e-04; /* required precision */
    
    double old_error, error = DBL_MAX; /* sum of squared euclidean distance */

    double **c=NULL;
    double **c1=NULL;    /* temp centroids */

    int *counts=NULL;   /* size of each cluster */
    int **labels=NULL;   /* output cluster label for each data point */
    int dims[2] ={nclusters,nchannels};
    
    allocate_2D_int_matrix ( &labels, height, width);
    memset ( &(labels[0][0]), 0, height*width*sizeof(int));
    counts = (int*)calloc(nclusters, sizeof(int)); 
    if ( NULL == counts || NULL == labels ) {
	printf("k_means: error allocating memory\n");
	exit (-1);
    }

    /* for debugging */
    assert(data && nclusters > 0 && nclusters <= n && nchannels > 0 && t >= 0); 
    
    /* initialization */
    allocate_2D_double_matrix ( &c1, dims[0], dims[1] );
    allocate_2D_double_matrix ( &c, dims[0], dims[1] );
	
    var1.data=data;
    var1.labels=labels;
    var1.c1=c1;
    var1.c=c;
    var1.error=error ;	
    var1.counts=counts;
    var1.nchannels=nchannels;
    var1.nclusters=nclusters;
    var1.height=height/num_threads;
    var1.width=width;


    

    /* pick nclusters points as initial centroids */
    for (h = i = 0; i < nclusters; h += width / nclusters, i++) {
      for (j = 0; j<nchannels; j++) {
	c[i][j] = data[h/width][h%width][j];
      }
    }
    
    /* main loop */
    do {
	/* save error from last step */
	old_error = error;
	error = 0;
	
	/* clear old counts and temp centroids */
	for (i = 0; i < nclusters; i++) {
	    counts[i] = 0;
	    for (j = 0; j < nchannels; j++) {
		c1[i][j] =0;
	    }
	}
    long t;
    for(t=0; t<num_threads; t++){
      printf("In main: creating thread %ld\n", t);
      int rc = pthread_create(&threads[t], NULL, commonfunction, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }
	printf("HI-----------------------");
	for(t=0; t<num_threads; t++){
     (void) pthread_join(threads[t], NULL);
   }
	

	for (i = 0; i < nclusters; i++) { /* update all centroids */
	  for (j = 0; j < nchannels; j++) {
	    c[i][j] = counts[i] ? c1[i][j] / counts[i] : c1[i][j];
	  }
	}
	
	printf("Error is: %lf\n", error);
    } while (fabs(error - old_error) > t);
    
    
    /* Memory Management */
    free_2D_double_matrix (&c1 );
    free_2D_double_matrix (&c );
    free(counts);
    
    return labels;
}
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
void free_2D_int_matrix (int ***matrix)
{
  int *matrix_tmp0;
  int **matrix_tmp1;

  matrix_tmp0=**matrix;
  matrix_tmp1=*matrix;

  free(matrix_tmp0);
  free(matrix_tmp1);

  *matrix=NULL;
  return;
}
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
void allocate_2D_int_matrix (int ***matrix, int dim0, int dim1)
{
  int i;
  int ** tmp_field0;
  int *data;

  data = (int *) malloc(dim0*dim1*sizeof(int));
  if (data == NULL ) {
      printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
      return;
  }

  tmp_field0 = (int **) malloc (dim0*sizeof(int *));
  if (tmp_field0 == NULL ) {
      printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
      return;
  }
  for (i=0; i<dim0; i++) {
    tmp_field0[i] = &(data[i*dim1]);
  }

  *matrix=tmp_field0;
  return;
}

/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
void free_2D_double_matrix (double ***matrix)
{
  double *matrix_tmp0;
  double **matrix_tmp1;

  matrix_tmp0=**matrix;
  matrix_tmp1=*matrix;

  free(matrix_tmp0);
  free(matrix_tmp1);

  *matrix=NULL;
  return;
}
/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
void allocate_2D_double_matrix (double ***matrix, int dim0, int dim1)
{
  int i;
  double ** tmp_field0;
  double *data;

  data = (double *) malloc(dim0*dim1*sizeof(double));
  if (data == NULL ) {
      printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
      return;
  }

  tmp_field0 = (double **) malloc (dim0*sizeof(double *));
  if (tmp_field0 == NULL ) {
      printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
      return;
  }
  for (i=0; i<dim0; i++) {
    tmp_field0[i] = &(data[i*dim1]);
  }

  *matrix=tmp_field0;
  return;
}

/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
void allocate_3D_double_matrix (double ****matrix,int dim0, int dim1, int dim2)
{
    int i;
    double ***tmp_field1;
    double **tmp_field0;
    double *data;

    data = (double *) malloc(dim0*dim1*dim2*sizeof(double));
    if (data == NULL ) {
	printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
	exit (-1);
    }

    tmp_field0 = (double **) malloc (dim0*dim1*sizeof(double *));
    if (tmp_field0 == NULL ) {
	printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
	exit (-1);
    }
    for (i=0; i<(dim0*dim1); i++) {
	tmp_field0[i] = &(data[i*dim2]);
    }
    tmp_field1 = (double ***) malloc (dim0*sizeof(double **));
    if (tmp_field1 == NULL ) {
	printf("%d @ %s, Could not allocate memory\n",  __LINE__,__FILE__);
	exit (-1);
    }
    for (i=0; i<dim0; i++) {
	tmp_field1[i] = &(tmp_field0[i*dim1]);
    }

    *matrix=tmp_field1;
    return;
}

/**********************************************************************/
/**********************************************************************/
/**********************************************************************/
void free_3D_double_matrix (double ****matrix)
{
    double *matrix_tmp0;
    double **matrix_tmp1;
    double ***matrix_tmp2;

    matrix_tmp0=***matrix;
    matrix_tmp1=**matrix;
    matrix_tmp2=*matrix;

    free(matrix_tmp0);
    free(matrix_tmp1);
    free(matrix_tmp2);

    *matrix=NULL;
    return;
}

Open in new window

sriramvemaraju2000Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sriramvemaraju2000Author Commented:
surprisingly if i remove the join it goes ahead.
0
phoffricCommented:
A quick skim shows that line 101 printf has an extra %. May as well fix that.
0
sarabandeCommented:
a pthread_join makes the calling thread suspend. therefore the main thread locks after first call of pthread_join.

the threads would dead-lock when they call pthread_mutex_lock second time as there are no pthread_mutex_unlock calls for each lock.

Sara
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.