Ok I am trying to pass pair of numbers through struct to pthread_create function in pthread. But the numbers i am passing and numbers i am getting when the function is called are different and random
Here is the struct
struct Pairs {
long i,j;
};
And inside main
void main()
{
long thread_cmp_count = (long)n*(n-1)/2;
long t,index = 0;
struct Pairs *pair;
pair = malloc(sizeof(struct Pairs));
cmp_thread = malloc(thread_cmp_count*sizeof(pthread_t));
for(thread = 0;(thread < thread_cmp_count); thread++){
for(t = thread+1; t < n; t++){
(*pair).i = thread;
(*pair).j = t;
pthread_create(&cmp_thread[index++], NULL, Compare, (void*) pair);
}
}
for(thread= 0;(thread<thread_cmp_count); thread++){
pthread_join(cmp_thread[thread], NULL);
}
free(cmp_thread);
}
And function Compare
void* Compare(void* pair){
struct Pairs *my_pair = (struct Pairs*)pair;
printf("\nThread %ld, %ld", (*my_pair).i, (*my_pair).j);
return NULL;
}
Number I am getting and it is also random.
Thread 0,2
Thread 1,2
Thread 2,3
Thread 2,3
Thread 2,3
Thread 2,3
am i passing the struct wrong ?
That is because you are passing the same pointer to all pthreads.
When you invoke pthread_create(..., (void*) pair) you are passing the pointer to the new thread, but in the next iteration you are overwriting that memory (potentially before the new thread has extracted those values).
long thread_cmp_count = (long)n*(n-1)/2;
long t,index = 0;
struct Pairs *pair;
cmp_thread = malloc(thread_cmp_count*sizeof(pthread_t));
for(thread = 0;(thread < thread_cmp_count); thread++){
for(t = thread+1; t < n; t++){
// allocate a separate pair for each thread
pair = malloc(sizeof(struct Pairs));
(*pair).i = thread;
(*pair).j = t;
pthread_create(&cmp_thread[index++], NULL, Compare, (void*) pair);
}
}
for(thread= 0;(thread<thread_cmp_count); thread++){
pthread_join(cmp_thread[thread], NULL);
}
free(cmp_thread);
.
void* Compare(void* pair){
struct Pairs *my_pair = (struct Pairs*)pair;
printf("\nThread %ld, %ld", (*my_pair).i, (*my_pair).j);
// free that memory after it has been used
free (pair);
return NULL;
}
Problem solved. Problem was with overlap. using pointer as an array of type struct Pairs it is solved
Here is the correct code
long thread_cmp_count = (long)n*(n-1)/2;
long t,index = 0;
Pair * pair;
pair = malloc(thread_cmp_count*sizeof(Pair));
free(thread_handles);
thread_handles = malloc(thread_cmp_count*sizeof(pthread_t));
for(thread = 0;(thread < n-1); thread++){
for(t = thread+1; t < n; t++){
(pair+index)->i = thread;
(pair+index)->j = t;
pthread_create(&thread_handles[index], NULL, Compare, (void*) (pair+index));
index++;
}
}
for(thread= 0;(thread<thread_cmp_count); thread++){
pthread_join(thread_handles[thread], NULL);
}
free(thread_handles);
And the function Compare
void* Compare(void* pair){
long t,i,j;
Pair *my_pair = (Pair*)pair;
i = my_pair->i;
j = my_pair->j;
printf("\n..................................................................");
if((x_array[i] < x_array[j])&&(x_array[i] != x_array[j])){
w_array[i] = 0;
printf(
"\nThread T(%ld,%ld)"
" compares x[%ld] = %ld and x[%ld] = %ld,"
" and writes 0 to w[%ld]", i, j,
i,x_array[i],
j,x_array[j],
i);
}
else if((x_array[i] > x_array[j])&&(x_array[i] != x_array[j])){
w_array[j] = 0;
printf(
"\nThread T(%ld,%ld)"
" compares x[%ld] = %ld and x[%ld] = %ld,"
" and writes 0 to w[%ld]", i, j,
i,x_array[i],
j,x_array[j],
j);
}
else
return NULL;
return NULL;
}
Related
I am attempting to create threads and pass each thread the value from a for loop. Here is the code segment
pthread_t *threadIDs;
int i = 0;
if(impl == 1)
{
threadIDs = (pthread_t *)malloc(sizeof(pthread_t)*reduces);
for(;i < reduces; i++)
{
pthread_create(&threadIDs[i], NULL, reduce,&i);
}
}
It is not passing the correct values of the loop, which makes sense since I am creating a race condition. What is the simplest way to pass the correct value of i from my loop?
Another question, will each thread finish executing before the next one is created and called?
You've already dynamically created an array of thread IDs. Do the same for the values you want to pass in.
pthread_t *threadIDs;
int *values;
int i = 0;
if(impl == 1)
{
threadIDs = malloc(sizeof(pthread_t)*reduces);
values = malloc(sizeof(int)*reduces);
for(;i < reduces; i++)
{
values[i] = i;
pthread_create(&threadIDs[i], NULL, reduce, &values[i]);
}
}
Each thread will be working with a different array member, so there's no race condition.
You can define a structure and assign i to the variable of the object.
#include <stdio.h>
#include <pthread.h>
typedef struct Param_ {
int index;
}Param;
static void* thread(void* p) {
Param* param = p;
printf("index: %d\n", param->index);
}
int main() {
int i = 0;
int reduces = 10;
pthread_t *threadIDs;
threadIDs = (pthread_t *)malloc(sizeof(pthread_t)*reduces);
for(; i < reduces; i++)
{
Param* p;
p = (Param*)malloc(sizeof(*p));
p->index = i;
pthread_create(&threadIDs[i], NULL, thread, p);
}
return 0;
}
What is the simplest way to pass the correct value of i from my loop?
What is to be considered "simple" depends on the use case, so here another approach to solve the issues you present:
#include <pthread.h>
pthread_mutex_t m_init;
pthread_cond_t c_init;
int init_done = 1;
void* thread_function(void * pv)
{
pthread_mutex_lock(&m_init);
size_t i = *((size_t*) pv);
init_done = 1;
pthread_cond_signal(&c_init);
pthread_mutex_unlock(&m_init);
...
}
#define THREADS_MAX (42)
int main(void)
{
pthread_t thread[THREADS_MAX];
pthread_mutex_init(&m_init, NULL);
pthread_cond_init(&c_init, NULL);
for(size_t i = 0; i < THREADS_MAX; ++i)
{
pthread_mutex_lock(&m_init);
init_done = 0;
pthread_create(&thread[i], NULL, thread_function, &i);
while (!init_done)
{
pthread_cond_wait(&c_init);
}
pthread_mutex_unlock(&m_init);
}
...
}
(error checking omitted for the sake of legibility)
I'm new with threads and I’m trying to create a program where four threads do some parallel computations using values from a global array. But, The problem that the threads are not loading the data in order.
#define QUARTER 64
#define RANGE_STEP 256
struct thread_data
{
unsigned start;
unsigned stop;
__m256* re_fc;
__m256* im_fc;
};
#define NUM_THREADS 4
struct thread_data thread_data_array[NUM_THREADS];
void *routine(void *thread_info)
{
int n,t;
unsigned t_start,t_stop;
__m256 *Re_fac , *Im_fac;
struct thread_data *mydata;
mydata = (struct thread_data*) thread_info;
t_start = mydata->start;
t_stop = mydata->stop;
Re_fac = mydata->re_fc;
Im_fac = mydata->im_fc;
t = t_start;
for (n = t_start; n < t_stop; n += 8)
{
// computations
RE_m256_fac = Re_fac[t];
IM_m256_fac = Im_fac[t];
// computations
t++;
}
pthread_exit(NULL);
}
int main()
{
unsigned t,i=0;
for(t=0;t<RANGE_STEP;t+=QUARTER)
{
thread_data_array[i].start = t;
thread_data_array[i].stop = t+QUARTER;
thread_data_array[i].re_fc = RE_factors;
thread_data_array[i].im_fc = IM_factors;
pthread_create(&threads[i],NULL,routine,(void *)&thread_data_array[i]);
i++;
}
for(i=0; i<NUM_THREADS; i++)
{
int rc = pthread_join(threads[i], NULL);
if (rc)
{
fprintf(stderr, "failed to join thread #%u - %s\n",i, strerror(rc));
}
}
}
The problem that I am talking about is occurring in the routine of the thread inside the for() loop exactly with these two load instructions RE_m256_fac = Re_fac[t];and IM_m256_fac = Im_fac[t]; the loaded data is not correct ... I think the index t is a local variable so no synchros is needed , or I am wrong?
After some digging it turned to be that since I am reading from a global shared array I have to use the mutex mechanism to prevent the mutual exclusion as so:
void *routine(void *thread_info)
{
int n,t;
unsigned t_start,t_stop;
__m256 *Re_fac , *Im_fac;
struct thread_data *mydata;
mydata = (struct thread_data*) thread_info;
t_start = mydata->start;
t_stop = mydata->stop;
Re_fac = mydata->re_fc;
Im_fac = mydata->im_fc;
t = t_start;
for (n = t_start; n < t_stop; n += 8)
{
pthread_mutex_lock(&mutex);
// computations
RE_m256_fac = Re_fac[t];
IM_m256_fac = Im_fac[t];
// computations
pthread_mutex_unlock(&mutex);
t++;
}
pthread_exit(NULL);
}
and since then, I can see that the threads are loading the values correctly from the shared array.
I have realized that my code was too lengthy and rather hard to read.
Can you check over the way I pass in the arguments and constructing the arguments in the main body?
Essentially, provided that I have correct implementation of "produce" and "consume" functions, I want to pass in a shared circular queue and semaphores and mutexes to each produce/consume threads.
typedef struct circularQueue
{
int *items;
int *head;
int *tail;
int numProduced;
int numConsumed;
} circularQueue;
typedef struct threadArg
{
int id;
circularQueue *queue;
pthread_mutex_t *mutex;
sem_t *spaces;
sem_t *itemAvail;
int numItems;
int bufferSize;
int numProducer;
int numConsumer;
} threadArg;
pthread_t *producerThd;
pthread_t *consumerThd;
int main(int argc, char* argv[])
{
pthread_attr_t attr;
// In fo to pass to thread arg
circularQueue *myQueue;
pthread_mutex_t useSharedMem;
sem_t spaces;
sem_t itemAvail;
int numItems;
int bufferSize;
int numProducer;
int numConsumer;
int i, j, k, l;
if(argc != 5)
{
printf("Enter in 4 arguments - N B P C\n");
return -1;
}
numItems = atoi(argv[1]);
bufferSize = atoi(argv[2]);
numProducer = atoi(argv[3]);
numConsumer = atoi(argv[4]);
if(numItems == 0 || bufferSize == 0 || numProducer == 0 || numConsumer == 0)
{
printf("Parameters should not be 0\n");
return -1;
}
// Initialize list of threads
producerThd = malloc(sizeof(pthread_t) * numProducer);
consumerThd = malloc(sizeof(pthread_t) * numConsumer);
// Initialize semaphores
sem_init(&spaces, 0, bufferSize);
sem_init(&itemAvail, 0, 0);
// Initialize mutex
pthread_mutex_init(&useSharedMem, NULL);
// Initialzie thread attributes
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Initialize queue
myQueue = (circularQueue*)malloc(sizeof(circularQueue));
myQueue->items = (int*)malloc(sizeof(int)*bufferSize);
myQueue->head = myQueue->items;
myQueue->tail = myQueue->items;
myQueue->numProduced = 0;
myQueue->numConsumed = 0;
// thread arguments
for(i = 0; i < numProducer; i++)
{
// Initialize thraed args
threadArg *args = (threadArg*)malloc(sizeof(threadArg));
args->queue = (circularQueue*)malloc(sizeof(circularQueue));
args->mutex = &useSharedMem;
args->spaces = &spaces;
args->itemAvail = &itemAvail;
args->numItems = numItems;
args->bufferSize = bufferSize;
args->numProducer = numProducer;
args->numConsumer = numConsumer;
args->id = i;
pthread_t thisThread = *(producerThd + i);
pthread_create(&thisThread, &attr, produce, args);
}
for(j = 0; j < numConsumer; j++)
{
// Initialize thraed args
threadArg *args = (threadArg*)malloc(sizeof(threadArg));
args->queue = (circularQueue*)malloc(sizeof(circularQueue));
args->mutex = &useSharedMem;
args->spaces = &spaces;
args->itemAvail = &itemAvail;
args->numItems = numItems;
args->bufferSize = bufferSize;
args->numProducer = numProducer;
args->numConsumer = numConsumer;
args->id = j;
pthread_t thisThread = *(consumerThd + i);
pthread_create(&thisThread, &attr, consume, args);
}
for(k = 0; k < numProducer; k++)
{
pthread_join(*(producerThd+k), NULL);
}
printf("Finished waiting for producers\n");
for(l = 0; l < numConsumer; l++)
{
pthread_join(*(consumerThd+l), NULL);
}
printf("Finished waiting for consumers\n");
free(producerThd);
free(consumerThd);
free(myQueue->items);
free(myQueue);
sem_destroy(&spaces);
sem_destroy(&itemAvail);
fflush(stdout);
return 0;
}
Thank you
There are multiple sources of undefined behavior in your code, you are either compiling without enabling compilation warnings, or what I consider worst you ignore them.
You have the wrong printf() specifier in
printf("cid %d found this item %d as valid item %d\n", myArgs->id, thisItem, validItem);
because validItem is a double, so the last specifier should be %f.
Your thread functions never return a value, but you declare them to return void * which is the signature required for such functions.
You are freeing and dereferencing myQueue in the main() function but you have not initialized it because that code is commented.
Your code is also too hard to read because you have no consistent style and you mix declarations with statements, which make everything very confusing, e.g. determining the scope of a variable is very difficult.
Fixing the code will not only help others read it, but will also help you fix it and find issues quickly.
I am getting a seg fault error at my pthread_join line. Below is my thread creation and joining code as well as my my_func thread function that I am calling. The program is supposed to create a variable amount of threads to execute a grep like function.
int
parallelSearchStatic(char **argv)
{
pthread_t worker_thread[NUM_THREADS];
ARGS_FOR_THREAD *args_for_thread;
queue_element_t *element;
int i;
int num_occurrences = 0;
int queue_count = 0;
queue_t *queue = createQueue(); /* Create and initialize the queue data structure. */
DIR *d;
struct dirent *dir;
d = opendir(argv[2]);
if (d)
{
while ((dir = readdir(d)) != NULL)
{
element = (queue_element_t *)malloc(sizeof(queue_element_t));
if(element == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(element->path_name, argv[2]);
strcat(element->path_name, "/");
strcat(element->path_name, dir->d_name);
insertElement(queue, element);
queue_count++;
}
closedir(d);
}
int increment = queue_count/NUM_THREADS;
for(i=0;i<NUM_THREADS;i++){
args_for_thread = (ARGS_FOR_THREAD *)malloc(sizeof(ARGS_FOR_THREAD));
args_for_thread->threadID=i;
args_for_thread->queue=createQueue();
args_for_thread->args=argv;
for(i = 0; i < increment; i++)
{
insertElement(args_for_thread->queue, removeElement(queue));
queue_count--;
}
if(i == (NUM_THREADS - 1) && queue_count != 0)
{
for(i = 0; i < queue_count; i++)
{
insertElement(args_for_thread->queue, removeElement(queue));
}
}
if((pthread_create(&worker_thread[i], NULL, my_func, (void *)args_for_thread))!=0){
printf("Cannot create thread \n");
exit(0);
}
}
for(i=0;i<NUM_THREADS;i++)
{
pthread_join(worker_thread[i], NULL);
}
for(i = 0; i < NUM_THREADS; i++)
num_occurrences += countArray[i];
return num_occurrences;
}
void *my_func(void *this_arg)
{
ARGS_FOR_THREAD *args_for_me = (ARGS_FOR_THREAD *)this_arg; // Typecast the argument passed to this function to the appropriate type
int threadID = args_for_me->threadID;
queue_t *queue = args_for_me->queue;
char** args = args_for_me->args;
int count = 0;
while(queue->head != NULL)
{
queue_element_t *element = removeElement(queue);
char *a[5];
a[0] = args[0];
a[1] = args[1];
a[2] = element->path_name;
a[3] = args[3];
a[4] = args[4];
count += serialSearch(a);
}
countArray[threadID] = count;
free((void *)args_for_me); // Free up the structure
pthread_exit(NULL);
}
You are using re-using i in nested loops within an outer loop that also uses i as its counter variable:
for(i = 0; i < increment; i++)
and
for(i = 0; i < queue_count; i++)
This means that your pthread_create() (which follows these inner loops) is using the wrong value of i to access worker_thread[i], so some values of worker_thread[] remain uninitialised and then cause pthread_join() to crash.
Use a different variable (eg. j) for the inner loops.
I'm trying to make a function that has to create a series of pthreads. I'm trying to keep track of each thread by assigning it a unique int t. However, when I try to make more than one thread, the value of t changes, every time I increment it in the main function. It should be pass by value so why is it changing?
// Struct //
typedef struct threadArg {
int verbose;
int listSize;
int thread;
int (*list)[];
} threadArg;
// In main //
for(t=0; t < numThreads; t++){
printf("Creating thread %ld...\n", t);
struct threadArg arg = {
.verbose = verbose,
.list = &arr,
.listSize = size,
.thread = t
};
printf("t: %d\n", (arg.thread));
status = pthread_create(&threadID[t], NULL, threadSort, (void*)&arg);
if (status){
printf("ERROR: failed to create thread", t);
exit(-1);
}
}
// Thread Sort function //
void *threadSort(void* arguments) {
// *** Bubble Sort ***
threadArg* arg = (threadArg*) arguments;
int verbose = arg->verbose;
int size = arg->listSize;
int (*arr)[size] = arg->list;
int t = arg->thread;
if (verbose & INIT) { printf("Thread %d initalized!\n", t); }
}
Thank you for your help,
Wally
It should be pass by value
No, this line passes it "by reference", that is passes the address of arg:
status = pthread_create(&threadID[t], NULL, threadSort, (void*)&arg)
The instance of arg in your code is used and destroyed and recreated for each iteration of the loop.
To fix this modfiy you code like follows:
void * threadSort(void * arguments);
[...]
struct threadArg arg = {
.verbose = verbose,
.list = &arr,
.listSize = size,
.thread = 0,
};
struct threadArg args[t] = {0};
for(t=0; t < numThreads; t++)
{
printf("Creating thread %ld...\n", t);
args[t] = arg;
args[t].thread = t;
printf("t: %d\n", arg.thread);
status = pthread_create(threadID + t, NULL, threadSort, args + t);
[...]
This introduces an array of struct arg with an element for each sperate thread, being nitialised by the value of threadArg, which is not used elsewhere but to have a common initialisation of whag is being passed to the thread function.