Parallel program with one mutex for the entire linked list (based on Pthreads)

This program which is implemented in C supports Member( ), Insert( ), and Delete( ) functions. Initially populate the linked list with n and unique values. Each value between 0 and 2¹⁶– 1. Then perform m random Member, Insert, and Delete operations on the link list.
 
 How to run (in Linux)
 
 Compile: gcc -g -Wall -o linkedlist_mutex linkedlist_mutex.c -lpthread
 Run: ./linkedlist_mutex <number of threads> <n> <m> <m_member_frac> <m_insert_frac> <m_delete_frac> 
 * n is the number of initial values in the linked List.
 * m is number of values to carry out operations on the linked list.
 * m_member_frac is the fractions of operations for Member operation. 
 * m_insert_frac is the fractions of operations for Insert operation. 
 * m_delete_frac is the fractions of operations for Delete operation.
 
 Output: This prints the execution time required for the parallel program based on Pthreads with one mutex for the entire linked list.
 
 Code : linkedlist_mutex.C

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>

struct list_node_s
{
int data;
struct list_node_s* next;
};
void *thread_function(void *);
int Member(int value);
int Insert(int value);
int Delete(int value);
int n;                 //number of values 
int m; //number of operations in each execution
float m_member_frac; //member fraction
float m_insert_frac; //insert fraction
float m_delete_frac; //delete fraction
pthread_mutex_t mutex, mutex1;
int count, count_m, count_i, count_d = 0;
int m_member, m_insert, m_delete;
int thread_count; //number of threads
struct list_node_s* head_p = NULL;
int* opr_values;

int main(int argc, char* argv[]){    //argc : no. of arguments and argv : vector of arguments
 long thread;
pthread_t* thread_handles;
clock_t start, end;
double cpu_time_used;
srand (time(NULL));
int i, ins_value;

 if (argc != 7)
{
//error in input values
fprintf(stderr, "error in input format. correct format: <thread_count> <n> <m> <m_member_frac> <m_insert_frac> <m_delete_frac>\n");
exit(0);
}
 thread_count = strtol(argv[1], NULL, 10);
if (thread_count <= 0)
{
fprintf(stderr, "error. thread count should be greater than 0\n");

  exit(0);
 }
 n = (int) strtol(argv[2], NULL, 10);
m = (int) strtol(argv[3], NULL, 10);
 m_member_frac = (float) atof(argv[4]);
m_insert_frac = (float) atof(argv[5]);
m_delete_frac = (float) atof(argv[6]);
 if(n < 0 || m < 0 || m_member_frac < 0 || m_insert_frac < 0 || m_delete_frac < 0 || m_member_frac+m_insert_frac+m_delete_frac != 1.0){
//error
  fprintf(stderr, "error in input values.\n");
fprintf(stderr, "n: no of initial values in the linkedlist.\n");
fprintf(stderr, "m: no. of values for carrying out operations\n");
fprintf(stderr, "m_member_frac: fraction of operations for member function\n");
fprintf(stderr, "m_insert_frac: fraction of operations for insert function\n");
fprintf(stderr, "m_delete_frac: fraction of operations for delete function\n");
exit(0);
}

 opr_values = malloc(m*sizeof(int));
 m_member = m * m_member_frac;
m_insert = m * m_insert_frac;
m_delete = m - (m_member + m_insert);

 for (i = 0; i < n; i++)
{
ins_value = rand() % 65535; //value should be between 2^16 - 1
Insert(ins_value);
}
 for (i = 0; i < m; i++)
{
opr_values[i] = rand() % 65535; //value should be between 2^16 - 1
}

 thread_handles = malloc(thread_count*sizeof(pthread_t));
 start = clock();
pthread_mutex_init(&mutex, NULL);
 for (thread = 0; thread < thread_count; thread++)
{
pthread_create(&thread_handles[thread], NULL, thread_function, (void*) thread);
}
 for (thread = 0; thread < thread_count; thread++)
{
pthread_join(thread_handles[thread], NULL);
}
 end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
FILE *pFile;
pFile=fopen("data-mutex.txt", "a");
fprintf(pFile, "%f\n", cpu_time_used);
 printf("execution time is : %f\n", cpu_time_used);
 free(thread_handles);
 return 0;
}
void *thread_function(void* rank){ 

//int *opr_values = (int *) arg;
//long my_rank = (long)rank;

 pthread_mutex_lock( &mutex1 ); 
int i = count++;
pthread_mutex_unlock( &mutex1 );

 while(i < m){
  //only one thread can get access to the linked-list at a time
  if(count_m < sizeof(m_member)){
   pthread_mutex_lock( &mutex );    
Member(opr_values[i]);
pthread_mutex_unlock( &mutex );
  }

  else if(count_i < sizeof(m_insert) + sizeof(m_member)){
   pthread_mutex_lock( &mutex );    
Insert(opr_values[i]);
pthread_mutex_unlock( &mutex );
  }

  else{
   pthread_mutex_lock( &mutex );    
Delete(opr_values[i]);
pthread_mutex_unlock( &mutex );
  }

  pthread_mutex_lock( &mutex1 ); 
i = count++;
pthread_mutex_unlock( &mutex1 );
}
 return NULL;
}
//Member function
int Member(int value){
 count_m++;
struct list_node_s* curr_p = head_p;
while(curr_p != NULL && curr_p->data < value){
curr_p = curr_p->next;
}
 if(curr_p == NULL || curr_p->data > value){
return 0;
}
else{
return 1;
}
}
//insert function
int Insert(int value){
 count_i++;
struct list_node_s** head_pp = &head_p;
struct list_node_s* curr_p = *head_pp;
struct list_node_s* pred_p = NULL;
struct list_node_s* temp_p;
 while(curr_p != NULL && curr_p->data < value){
pred_p = curr_p;
curr_p = curr_p->next;
}
 if(curr_p == NULL || curr_p->data > value){
temp_p = malloc(sizeof(struct list_node_s));
temp_p->data = value;
temp_p->next = curr_p;
if(pred_p == NULL) //new first node
*head_pp = temp_p;
else
pred_p->next = temp_p;
return 1;
}
else{
return 0; //value already in the list
}
}

//delete function
int Delete(int value){
 count_d++;
struct list_node_s** head_pp = &head_p;
struct list_node_s* curr_p = *head_pp;
struct list_node_s* pred_p = NULL;
 while(curr_p != NULL && curr_p->data < value){
pred_p = curr_p;
curr_p = curr_p->next;
}
 if(curr_p != NULL && curr_p->data == value){
if(pred_p == NULL){
*head_pp = curr_p->next; //deleting the first node in the list
free(curr_p);
}
else{
pred_p->next = curr_p->next;
free(curr_p);
}
return 1;
}
else{
return 0; //value not in the list
}
}