Passing Struct Array to a Thread - c

I am trying to pass a whole array of a struct to a thread, where I need to have their index to differentiate the different arrays inside the thread.
typedef struct {
int x;
int y;
} StructA;
typedef struct {
StructaA str;
pthread_mutex_t* mutex;
} Parameters;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int n=3;
main(){
pthread_t thread;
StructA str[n];
Parameters thParam[n];
for (int i=0; i<n; i++){
thParam[i].str = &str[i];
thParam[i].mutex = &mutex;
}
for (int i=0; i<n; i++){
if(pthread_create(&thread[i], NULL, &Thread1, (void*)&thParam))
exit;
}
etc...
}
Thread1(params*){
Parameters * param[n];
StructA stra[n];
for (int i=0; i<n; i++){
??????????????????
}
}
I have thought about something like this:
for(int i=0; i<ghostN; i++){
param[i] = ((Parameters*) params+i);
stra[i] = param[i];
}
but I am just messing more and more the code. What would be the correct way to do this?
Consider that I must do this in order to see each str[n] values (the struct inside the main which I passed to the thread) inside the thread itself.

The memory of the main process is shared between all thereads. So, every thread has an ability to access the same variable or
arrays. The only thing which makes sense to pass to a thread startup function is somethign uniquie. Note, you cannot pass anything
to a thread, thread is not a function, but you can pass something to the thread start-up function to keep it on the stack of this
function. Every call to a function allocates stack unique to this function.
So, in your example I would keep the thParam array in the global scope to make it accessible by all threads, something like the following
Parameters thParam[n];
StructA str[n];
void *startThread(void *arg) {
long int i = (long int)arg;
use(thParam[i]);
}
main(){
pthread_t thread[n];
for (long int i=0; i<n; i++){
thParam[i].str = &str[i];
thParam[i].mutex = &mutex;
}
for (int i=0; i<n; i++){
if(pthread_create(&thread[i], NULL, &startThread, (void*)i))
exit;
}
...
}
Note that in the above case all writes to thParam is done before the thread starts. So there is no need to provide any
synchronization here. Also, since all threads access their own portion of the array only, defined by i, there is no need to
synchronize either.
You need to pass i by value, to avoid synchronization issues. Therefore you'd better have 'long int' to match its size to the size of the void* pointer.
And in your cases the thread must be an array as well.

Related

How can I use multiple arguments when calling a method with a pthread?

I have a problem with my C program, because I don't really know, how to use the pthread_create method with a function that has multiple arguments.
My code shall find primes in an array. Therefor I am forced to use n threads, each looking in one part of the array.
Here is what my code looks like:
for (int i = 0; i< n - 1; i++) {
pthread_create(&threads[i], NULL, checkArrayPart,(size*i, size*(i+1),values));
}
pthread_create(&threads[n-1], NULL, checkArrayPart,(size*i, size*(i+1),values)));
the method checkArrayPart looks like this:
int checkArrayPart(int begin, int end, int arr[]){
int localCounter = 0;
for (int i = begin; i <= end; i++) {
if (isPrime(arr[i])) {
localCounter++;
}
}
return localCounter;
}
I tried to compile my code and it is not working. I think the problem is in the part where I give the new thread the arguments for the method it shall run. So, is there a way to use multiple arguments in a method given to a pthread?
I appreciate any help. Thank you... :)
So, is there a way to use multiple arguments in a method given to a pthread?
Yes: you have to wrap multiple arguments in a struct:
struct Args {
int begin, end;
int *arr;
};
void *call_checkArrayPart(void *p) {
struct Args *args = (struct Args *) p;
int rc = checkArrayPart(args->begin, args->end, args->arr);
return (void *) rc;
}
At creation time, you need to pack your args into this struct:
struct Args args[n];
for (int i = 0; i< n - 1; i++) {
struct Args *arg = &args[i];
arg->begin = size * i;
args->end = args->begin + size;
args->arr = values;
pthread_create(&threads[i], NULL, call_checkArrayPart, arg);
}

Dining Philosophers in C memory leaks

i am trying to implement Dining Philosophers in C using Resource hierarchy solution. when i am using valgrind everything goes fine. Unfortunately when i done this using console im getting random seqfaults. One time my program will be succesful,one time it will broke on the beginning. I would be grateful if anybody could point where i did mistake and why it's 100% succesfull.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_PHILOSPHERS 5
sem_t forks[NUM_PHILOSPHERS];
void *philosopher(void *param){
printf("Thread created!");
int *id = (int *)param;
int L = 0;
sem_t* Myforks[2];
int par = *id;
if(par == 4){
Myforks[0] = &forks[4];
Myforks[1] = &forks[0];
}else{
Myforks[0] = &forks[par];
Myforks[1] = &forks[par+1];
}
while(L!=5){
printf("Eat spaghetti!",*id);
sem_wait(Myforks[0]);
sem_wait(Myforks[1]);
//.....
printf("EAT spaghetti!",*id);
sem_post(Myforks[1]);
sem_post(Myforks[0]);
L=L+1;
}
pthread_exit(NULL);
}
int main(){
int i;
pthread_t threads[NUM_PHILOSPHERS];
for(i = 0; i < NUM_PHILOSPHERS; i++)
sem_init(&forks[i], 0, 1);
for(i = 0; i < NUM_PHILOSPHERS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)&i);
return 0;
}
int i;
...
for(i = 0; i < NUM_PHILOSPHERS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)&i);
^^
Passing a pointer to a local variable isn't going to work. You're passing the same address to all of the threads, so there's an inherent race condition. You point them a pointer to i and them almost immediately you increment i. What value will they read when they access *param? Who knows!
You'll want to create an array with NUM_PHILOSPHERS (sic) slots in it and pass a different address to each thread. You'll also want to make sure that array isn't destroyed when main() exits—i.e., make the array global or static, not local.

Thread struct as function parameter C

I'm having a trouble passing a struct pointer into a function because I'm a bit confused with those pointers and references. I want to modify the thread.thread_num value from the thread_startfunction.
#include <stdio.h>
#include <stdlib.h> //malloc, free
#include <pthread.h>
#define N 5
// void *malloc(size_t);
struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
};
void *thread_start(void *thread)
{
struct thread *my_data;
my_data = (struct thread *)thread;
printf("num T: %i\n", my_data->thread_num);
my_data->thread_num=4;
printf("num T: %i\n", my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread = &pthread_data;
thread->thread_num=2;
pthread_create(&thread->thread_id, NULL, thread_start, (void *)&thread);
printf("num: %i\n",thread->thread_num);
pthread_exit(NULL);
return 0;
}
But the value that print the main doesn't change (2).
And then I want to create an array of thread struct, but I don't know how exactly do that:
I guess it should be something like this:
int main(int argc, char *argv[])
{
int i;
struct thread pthread_data;
struct thread *thread[N-1] = &pthread_data; // I don't know how to manage this.
for(i=0; i<N; i++)
{
thread->thread_num=i;
pthread_create(&thread[i]->thread_id, NULL, thread_start, (void *)&thread[i]);
printf("num %i: %i\n",i,thread[i]->thread_num);
}
pthread_exit(NULL);
return 0;
}
Any thoughts?
I recommend you to read http://www.advancedlinuxprogramming.com/alp-folder/alp-ch04-threads.pdf
And here what you wanted:
#define N 5
typedef struct thread {
pthread_t thread_id;
int thread_num;
// int thread_sum;
} ThreadData;
void *thread_start(void *thread)
{
ThreadData *my_data = (ThreadData*)thread;
//there is no guarantee that prints will be in order
// we will use its initial thread->num ,cause it differs for each thread
//plus you will see how threads will behave
int order=my_data->thread_num;
printf("%i) before num T: %i\n",order, my_data->thread_num);
my_data->thread_num=4;
printf("%i) after assignment num T: %i\n",order ,my_data->thread_num);
return NULL;
}
int main(int argc, char *argv[])
{
int i;
ThreadData thread[N];
for(i=0; i<N; i++)
{
thread[i].thread_num=i;
pthread_create(&(thread[i].thread_id), NULL, thread_start, (void *)(thread+i));
}
//wait for all threads
for (i = 0; i < N; i++)
pthread_join(thread[i].thread_id, NULL);
//print results of each thread
for (i = 0; i < N; i++)
printf(" %i)thread: number %i\n",i,thread[i].thread_num);
return 0;
}
I can see multiple mistakes in your code.
First you have your pointers wrong. In the first example, it is enough to pass &pthread_data to pthread_create, &thread is the address of the thread pointer, so you are passing struct thread ** to your function instead of struct thread *. In the second example you should use (void *) thread[i]. &thread[i] is again struct thread **.
When you want each thread to write to its own thread data, then you should make an array of thread data, so that each thread has its own piece, else you will run into race conditions.
As others have already pointed out, you should call pthread_join before calling printf to ensure that the main thread will wait for all worker threads.
Also note that if you are calling pthread_join from other function that the one that spawned those threads, you have to ensure that the array of tread data will not go out of scope (in this case it would be probably better to use malloc or a global array).
You can't. As soon as main exits, which it does when you call pthread_exit, pthread_data ceases to exist, since it's local to the main function. So it can't be modified.

Threads receiving the same ID in C

Here is a block of code that creates a number of threads provided by the user, each thread then generates a random number and calculates its squareroot. I cannot figure out why the threads are getting the same ID, line 64 is the culprit as it is where the threads are being created. I suspect that there is something happening in the loop that is causing the threads to all be generated at the same time.
////////////////////////////////////////////////
//
//
// Zach
//
//
//
//
////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *squareroot(void *num1)
{
int *id = (int *)num1;
int incoming = rand()/100;
float *outgoing = (float *)malloc(sizeof(float));
printf("%d \n", *id);
printf("%d\n", incoming);
*outgoing = 5.000;
//Calculate the square root of the number passed to the function
*outgoing = sqrt(incoming);
return outgoing;
}
int main(int argc, char* argv[])//testing funcion
{
srand(time(NULL));
int i, j;
int *temp = (int *)malloc(sizeof(int));
if (argc != 2)
{
printf ("ERROR: Enter a number\n");
return 1;
}
int loop = atoi(argv[1]); //grabbing the integer supplied by user
pthread_t thread_id[loop];
void *exit_status;
float *thread_result;
for(i = 0; i < loop; i++)
{
pthread_create(&thread_id[i], NULL, squareroot, &i);
}
for(j = 0; j < loop; j++)
{
pthread_join(thread_id[j], &exit_status);
thread_result = (float *)exit_status;
printf("%f\n", *thread_result);
}
}
I think what is happening is that your loop finishes creating all the threads (or at least some of them) before any of the threads actually run and extract their unique id.
Because you're passing a pointer to i, when each thread finally gets around to checking its parameter, i is already finished... Or at least partway through. The danger is that multiple threads might see the same value for i. It's even worse that you never copy the value out of that pointer - you always dereference it. That means it might change in the middle of your thread's execution.
What you should do instead is pretend it is a pointer:
pthread_create(&thread_id[i], NULL, squareroot, (void*)i);
And in your thread function:
int id = (int)num1;
This works because the pointer is passed by value. Whatever value you provide is the value that goes into the thread function. Previously it didn't work because you passed a pointer to a value that could change in another thread.
PS: Don't forget to free the result from each thread in your loop at the end. At the moment you're not cleaning up memory that you allocated.

pthread with unique struct as parameter C

I have this piece of code that is giving me trouble.
I know all the threads are reading the same struct. But I have no idea how to fix this.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a,b;
} s_param;
void *
threadfunc(void *parm)
{
s_param *param2 = parm;
printf("ID:%d and v:%d\n",param2->a,param2->b);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t thread[3];
int rc=0,i;
void * status;
for(i=0; i<3 ; ++i){
s_param param;
param.b=10;
param.a=i;
rc = pthread_create(&thread[i], NULL, threadfunc, &param ); // !!!!
if(rc){
exit(1);
}
}
for(i=0; i<3 ; ++i){
pthread_join(thread[i],&status);
}
return 0;
}
output:
ID:2 and v:10
ID:2 and v:10
ID:2 and v:10
and what I need:
ID:0 and v:10
ID:1 and v:10
ID:2 and v:10
The scope of the sparam in the for loop is static within that loop. When you set .a and .b you are writing to the same struct over and over, and all three threads are getting a pointer to that same single struct.
Instead, you could create three separate instances of the struct by making an array of them like so..
int main(int argc, char **argv)
{
pthread_t thread[3];
s_param param[3];
int rc=0,i;
void * status;
for(i=0; i<3 ; ++i){
param[i].b=10;
param[i].a=i;
rc = pthread_create(&thread[i], NULL, threadfunc, &param[i] ); // !!!!
if(rc){
exit(1);
}
}
... etc
Should mention that creating the structs (and the threads) in an array like this is only feasible since you clearly do a join() with the main thread. If you didn't do that join, you would be advised to either statically allocate the structs outside of the main function, or malloc them from the heap, because as soon as the entry thread exits the main function, the stack frame containing the array will become invalid and will soon be overwritten in an unpredictable way.
param lives on the same place in the stack during the execution of your main function. Every time you set new values, they're wiping out the old values, and all the threadfuncs are looking at the same spot in memory. malloc the structs, or otherwise create them from different memory locations. (Also, using stack memory for cross-thread data structures is worrisome; as soon as the function you're setting them up in exits, the memory is invalid.)
param is a local variable. It goes out of scope at the end of the loop's braces. You need to malloc a new s_param with each thread.
Or better, define a struct containing both a pthread_t and an s_param and use that type for thread[3].
typedef struct {
int a,b;
pthread_t t;
} s_param;
int main(int argc, char **argv)
{
s_param thread[3]; // declare threads + params together
int rc=0,i;
void * status;
for(i=0; i<3 ; ++i){
s_param *param = &thread[i]; // no persistent data declared here
param->b=10;
param->a=i;
rc = pthread_create(&thread[i].t, NULL, threadfunc, &thread[i] ); // !!!!
if(rc){
exit(1);
}
}
…

Resources