Dereferencing an array within a struct being used by ptread_create - c

My ThreadData struct:
typedef struct threadData {
pthread_t *ths;
} threadData;
Where *ths is an array of pthread_t.
Now, I create a thread that uses as action the following function, which creates a new thread in ths[1]
void *rootThread(threadData *d) {
pthread_t *b = (*d).ths;
pthread_create(*(b+1),NULL,someRandomFunction,NULL);
}
But that doesn't seem to work.
I'm not sure if I'm dereferencing the pthread_t element well. Please help!
Thanks, :).

It looks like (for example) you are not allocating. You have to do something like this:
void* Thread(void* theCUstom);
pthread_t* threadHandle = malloc(sizeof(pthread_t));
pthread_mutex_t mutex; // mutex lock
pthread_attr_t attr; // thread attributes
pthread_mutex_init(&mutex, NULL);
pthread_attr_init(&attr);
unsigned long errRes = pthread_create(threadHandle, &attr, Thread, yourCustom);

You can't maintain an index to which pthread_t to use that way. b+1 will be constant every time you re-enter the rootThread(). You probably need a separate index variable in threadData, or a second pointer that can iterate through the list. Either that, or don't make a temporary variable pthread_t *b.
typedef struct threadData {
pthread_t *ths;
int thsIdx;
} threadData;
void *rootThread(threadData *d) {
pthread_create( &d->ths[d->thsIdx++],NULL,someRandomFunction,NULL);
}
Or your way:
void *rootThread(threadData *d) {
pthread_create( d->ths, NULL, someRandomFunction, NULL);
++d->ths; // this is nasty because you lose the pointer to the beginning of the array.
}

Related

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.

Mutex dynamic allocated

I sucessfully used a static mutex, but i got problem with dynamic version.
In output a variable should be equal to zero..
Please help.
Is any better way to write this?
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#define N 20
int beers=20;
void* drink(void*);
//pthread_mutex_t lockk = PTHREAD_MUTEX_INITIALIZER;
typedef struct st1{
pthread_mutex_t mutex;
int val;
}my_struct_t;
int main(){
pthread_t th[N];
int i;
void* return_val;
my_struct_t *data;
data = malloc(sizeof(my_struct_t));
data->val = 20;
pthread_mutex_init(&data->mutex,NULL);
for(i=0;i<N;i++)
pthread_create(&th[i], NULL, drink, &data);
for(i=0;i<N;i++)
pthread_join(th[i], &return_val);
pthread_mutex_destroy(&data->mutex);
printf("%d\n", beers);
}
void* drink(void* p){
int i;
my_struct_t *data = (my_struct_t *)p;
pthread_mutex_lock(&data->mutex);
beers--;
pthread_mutex_unlock(&data->mutex);
//}
return NULL;
}
Where i got fail? :)
There's a problem here:
pthread_create(&th[i], NULL, drink, &data);
You're passing the address of the pointer data, so a type my_struct_t**, but treating it as a my_struct_t* in the drink function. Remove the & in the caller and the code should work.
Please do some cleanup though. You have unused variables, define N but fail to use it when initializing beer and data->val, you initialize data->val but never use it...

Passing 2 structures as parameters to pthread in C

Can I pass two structures as parameters to a pthread in a C program. I need to do something like this:
void *funtion1(void *pass_arg, void *pass_arg1)
{
struct thread_arg *con = pass_arg;
struct thread_arg1 *con = pass_arg1;
//necessary code
}
int main()
{
pthread_t threaad;
//necessary code
while(1)
{
th1 = pthread_create(&threaad, NULL, function1, (void *)&pass_arg, (void*)&pass_arg);
//necessary codes
}
pthread_exit(NULL);
return 1;
}
I mean is there any way I can pass two structures into the same function while using pthread? Operating Platform: Linux.
Not directly, because the functions in libpthread accept only one user data argument. But that should be enough, shouldn't it?
struct user_struct {
void *p1, *p2;
} arg = { &arg1, &arg2 };
pthread_create(&tid, NULL, threadfunc, &arg);
Also, don't cast pointers to void *, it's superfluous, dangerous and decreases readability.
Define a new struct type which contains the two original types as members. Call it something meaningful like thread_args.
I solved the problem by nesting the two structures into a single structure like this:
struct s1
{
//variables
};
struct s2
{
//variables
}
struct s3
{
struct s1 ss1;
struct s2 ss2;
}
void *funtion1(void *pass_arg)
{
struct s3 *con = pass_arg;
//necessary code
}
int main()
{
//code
th1 = pthread_create(&thread, NULL, function1, (void *)&pass_arg);
}

Storing a pointer's address in an unsigned int in C

Is it possible to cast a pointer to an unsigned int, then later cast it back to a pointer? I'm trying to store the pointer to a struct in a pthread_t variable, but I can't seem to get it to work. Here's some snippets of my code (I'm creating a user-level thread management library). When I try to print out the tid of the thread it gives me some long garbage number.
Edit: Never mind, I got it to work.
I changed
thread = (pthread_t) currentThread;
to
*thread = (pthread_t) currentThread;
Figured it was something stupid like that.
Test program:
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1, NULL, runner, NULL);
pthread_create(&thread2, NULL, runner, NULL);
pthread_join(&thread2, NULL);
My library:
typedef struct queueItem
{
int tid;
ucontext_t context;
int caller;
struct queueItem *joiningOn;
struct queueItem *nextContext;
} queueItem;
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
thread = (pthread_t) currentThread;
}
...
int pthread_join(pthread_t thread, void **retval)
{
queueItem *t = (queueItem *) thread;
if(runningContext->joiningOn != NULL) // Current thread is already waiting on another
return EINVAL;
if(t == NULL) // If thread to join on is invalid
return 0;
fprintf(stdout, "JOINEE: %d\n", t->tid); // Prints weird number
runningContext->caller = JOIN;
runningContext->joiningOn = t;
swapcontext(&(runningContext->context), &scheduleContext);
}
No. On many systems pointer type is bigger than int type. If you have a problem to use pthread_t, ask about it, int is not the answer.
For example, on my machine, the following code:
#include <stdio.h>
int main() {
printf("unsigned int = %lu\n", sizeof(unsigned int));
printf("pointer = %lu\n", sizeof(void*));
return 0;
}
outputs:
unsigned int = 4
pointer = 8
Sure it's possible, if you make sure your unsigned int is the same size as a void* on your system.
If you have some code that's not working, post it.
Edit: You should read about intptr_t, e.g. here: Why / when to use `intptr_t` for type-casting in C?

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