I am sending a sturct dataBlock to my threads which contains a pointer to same listRoot(for all threads), an int indexInForLoop, and an int listSize; The Node from the list has a int value which ash to be processed and a int worker which is nrOfListElements % nrOfWorkers(Threads). But somehow I thing the struct I send to each thread is the same, but it shouldn’t each should have 1 different int variable with the indexFromForLoop. What am I doing wrong?
terminal output:
node #1 worker: 1 value: 86
node #2 worker: 0 value: 77
node #3 worker: 1 value: 15
node #4 worker: 0 value: 93
node #5 worker: 1 value: 35
? List got populated
workersInput: 2
in for, ret= 0
in for, ret= 0
* Thread start: id: 3067579200^
forID_ 1
->val: 86
valid for sqrt
* Thread start: id: 3075971904^
forID_ 1
->val: 86
valid for sqrt
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#define workTime 5
#define workersLimitNr 3
struct dataBlock{
struct node *root;
int listSize;
int forIndex;
};
struct node { // std linked list node
int value;
int worker;
struct node *next;
};
int slots = 0; // only 3 threads are allowed to access the list
int availableCheck(){ // check if thread can acces the list
if(slots < 3) return 0;
else return -1;
}
pthread_mutex_t mutp = PTHREAD_MUTEX_INITIALIZER; //condvar mutex
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; //condvar
void * worker( void *data ){
struct dataBlock *inData = (struct dataBlock *) data;
struct node *root = inData->root;
int listSize = inData->listSize;
int forIndex = inData ->forIndex;
printf( "* Thread start: ^\n");
pthread_mutex_lock( &mutp );
if(availableCheck() < 0){
printf( " ^^^ List not available yet... \n" );
pthread_cond_wait( &condvar, &mutp );
}
struct node *it = root;
printf("forID_ %d \n", forIndex);
while(it->next != NULL){
if(forIndex == it->worker){
printf("valid for sqrt \n");
if(it->value > 2){
sqrt(it->value);
break;
}
}
it = it->next;
printf("->val: %d \n", it->value);
}
pthread_cond_signal( &condvar ); //
pthread_mutex_unlock( &mutp );
return NULL;
}
int main( int argc, char *argv[] ){
if ( argc != 3 ){
printf( "Programm must be called with \n NR of elements and NR of workers! \n " );
exit( 1 );
}
int i;
struct node *root;
struct node *iterator;
//prepare list for task
int listSize = atoi(argv[1]);
int nrWorkers = atoi(argv[2]);
root = malloc(sizeof( struct node) );
root->value = rand() % 100;
root->worker = 0;
iterator = root;
for( i=1; i<listSize; i++ ){
iterator->next = malloc(sizeof(struct node));
iterator = iterator->next;
iterator->value = rand() % 100;
iterator->worker = i % nrWorkers;
printf("node #%d worker: %d value: %d\n", i, iterator->worker,iterator->value);
}
printf("? List got populated\n");
// Create all threads to parse the link list
int ret;
printf("workersInput: %d\n",nrWorkers);
pthread_t w_thread;
pthread_t* w_threads = malloc(nrWorkers * sizeof(w_thread));
struct dataBlock *data = malloc(sizeof(struct dataBlock));
data->root = root;
data->listSize = listSize;
for( i=0; i < nrWorkers; i++ ){
data->forIndex = i;
ret = pthread_create ( &w_threads[i], NULL, worker, (void *) data );
if( ret ) {
perror("Thread creation fail");
exit(2);
}
printf("in for, ret= %d\n",ret);
}
for ( i = 0; i < nrWorkers; i++){
pthread_join(w_threads[i],NULL);
}
free(root);
free(iterator);
return 0;
}
EDIT: I used a pthread_self() and I confirm there are different threats
Using
you overwrite the previous value(s). And since you have only one
dataBlockeach thread will look to the same place. And since creating a thread does not mean “start it before the next statement in the loop is executed” it is pure luck what value each thread sees.You have to allocate one
dataBlockfor each thread and give eachdataBLockonly to one thread.