Extract sub struct from main struct for thread creation - c

I am having issues trying to send multiple arguments to the pthread_create, the issue is basically because one of the arguments is another struct.
This is the node.
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define NUM_THREADS 4
struct arr {
char line[10];
};
struct args {
struct arr record; int count; int init; int end;
};
void* processarr(void *arguments)
{
int count; int init; int end;
struct args *argstmp=arguments;
init=argstmp->init;
count=argstmp->count;
end=argstmp->end;
struct arr record[count];
record=(struct arr)argstmp->record;
printf("Some of the vals are init %d count %d end %d\n",init, count, end);
printf("vals like record 0\n", record[0].line);
pthread_exit(NULL);
}/*end of processarr*/
int main (int argc, char *argv[])
{
int line_count;
FILE *ptr_file;
char buf[10];
ptr_file =fopen(argv[ 1 ],"r");
if (!ptr_file)
return 1;
while (fgets(buf,10, ptr_file)!=NULL)
{
line_count++ ;
}
rewind(ptr_file);
struct arr record[line_count];
line_count=0;
while (fgets(buf,10, ptr_file)!=NULL)
{
line_count++ ;
buf[strcspn(buf, "\r\n")] = 0; /* Removing end null chars*/
strcpy(record[line_count].line,buf);
}
float grptmp,group, lgroup;
grptmp=line_count/NUM_THREADS;
int counter1,counter2,init,end;
counter2=1;
struct args myargs;
//processarr(record, line_count, init, end);
pthread_t threads[NUM_THREADS];
for (counter1=0;counter1<=line_count;counter1++)
{
if(counter2==NUM_THREADS)
{
end=line_count;
}else{
end=counter1+grptmp;
}
init=counter1;
myargs.record=*record;
myargs.count=line_count;
myargs.init=init;
myargs.end=end;
printf ("Run job #%d with paramts Init=%d and End=%d\n",counter2, init, end);
//call here
//struct arr *record; int count; int init; int end;
int rc;
long t;
for(t=0;t<NUM_THREADS;t++){
rc = pthread_create(&threads[t], NULL,processarr,&myargs);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
counter1=counter1+grptmp;
counter2++;
}
return 0;
}
So, when I send my arguments,the one stored inside myargs.record=*record, for some reason I am not able to "unpack" it once in the function.
The function is was defined as void to be able to catch the whole big argument, and I am trying to re-map everything there, the counts are working fine, but the one called record, that is actually another struct is not working, looks like a cast issue.
void* processarr(void *arguments)
{
int count; int init; int end;
struct args *argstmp=arguments;
init=argstmp->init;
count=argstmp->count;
end=argstmp->end;
struct arr record[count];
record=(struct arr)argstmp->record;
printf("Some of the vals are init %d count %d end %d\n",init, count, end);
printf("vals like record 0\n", record[0].line);
pthread_exit(NULL);
}
I am getting the following error when compiling.
test4.c: In function processarr:
test4.c:31:7: error: assignment to expression with array type
record=(struct arr)argstmp->record;
Any idea why this is not working? This last one was my last change using the casting (struct arr) in front of the argstmp (which is supposed to have everything inside).

Elaborating a little more on my response, this is what I would do using another struct to pass the arguments.
typedef struct {char line[10];}mystruct;
typedef struct {mystruct struct1;char line[10];}wrapper;
struct wrapper2 {mystruct struct1;char line[10];};
void unwrap(struct wrapper2 args){
printf("val is %s\n",args.line);
mystruct tmp=args.struct1;
printf("val inside structure is %s\n\n", tmp.line);
}
int main ()
{
mystruct names;
strcpy(names.line,"TEST");
struct wrapper2 wrapper1;
wrapper1.struct1=names;
strcpy(wrapper1.line,"Value1");
unwrap (wrapper1);
}
I hope this example helps you fix the issue, you just need to pass the same thing using the pthread_create.
Update:
The final code could look like this:
#include <pthread.h>
#include <stdlib.h>
struct mystruct {
int val;
};
void * func (void *args){
struct mystruct *st1=args;
printf("Thread created..%d\n", st1->val);
pthread_exit(NULL);
}
int main ()
{
/* Thread creation logic as void * (*)(void *)
int pthread_create (pthread_t *, const pthread_attr_t *,
void *(*)(void *), void *);
* */
struct mystruct mystruct1;
mystruct1.val=230;
pthread_t threads;
pthread_create(&threads,NULL,&func,&mystruct1);
pthread_exit(NULL);
return 0;
}
I recommend you read the actual manual of pthread_create.
http://man7.org/linux/man-pages/man3/pthread_create.3.html

Related

How do I keep information in struct after returning from function?

So I am still a little confused about pointers in connection with structs.
I have a struct which represents a queue. The queue contains an array of queue elements (containers).
I now want to access these containers in order to assign values to them. This code is only for containers[0] to keep it simple.
How can I access the string at containers[0] in main after returning from writeContainer() function?
The signature of writeContainer() is given, so I can't change that.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct qElement {
char array[55];
int len;
} container;
typedef struct queue {
container containers[5];
int id;
} myq;
int writeContainer(myq anyq, void *buf, int buflen);
int main(void) {
myq *testq = malloc(sizeof(myq));
char *mainArray = "hello";
writeContainer(*testq, mainArray, 6);
printf("outside Array[0]: %s\n", testq->containers[0].array);
return EXIT_SUCCESS;
}
int writeContainer(myq anyq, void *buf, int buflen) {
container *elem = malloc(sizeof(container));
// into temp elemnt
elem->len = buflen;
memcpy(&elem->array, buf, buflen);
// into actual queue
memcpy(&anyq.containers[0], elem, buflen);
printf("qArray[0]: %s\n", &anyq.containers[0].array);
printf("exiting function\n");
free(elem);
return buflen;
}
so the output is:
qArray[0]: hello
exiting function
outside Array[0]:
but I expected:
qArray[0]: hello
exiting function
outside Array[0]: hello
Thanks in advance
With this prototype for writeContainer:
int writeContainer(myq anyq, void *buf, int buflen);
and the posted definition of myq, writeContainer cannot be written to have a side effect on the queue passed from main() because it is passed by value. The prototype is inconsistent on another aspect: if data from buf is only supposed to be read and copied to the container(s), this pointer should be declared as const void *buf and its size should be passed as a size_t buflen.
There is a * missing, either in the prototype or in the typedef for myq.

corrupted size vs. prev_size in C

I get "corrupted size vs prev_size" error whenever I allocate a dynamic memory in a thread. Whenever I allocate the memory in main() it works fine. But allocating dynamic memory in thread produces the error.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *fib(void *p);
struct mystruct
{
int *array;
int size;
};
int main(int argc, char *argv[])
{
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
struct mystruct obj;
obj.size = atoi(argv[1]);;
pthread_create(&tid, &attr, fib, (void *)&obj);
pthread_join(tid, NULL);
}
void *fib (void *p)
{
struct mystruct *x = (struct mystruct *)p;
x->array = (int *) malloc (x->size);
for (int i=0; i<x->size; i++){
x->array[i] = i;
printf("The array is = %d\n", x->array[i]);
}
}
I've added snapshot for details.
Thanks!
Try with the following line:
x->array = malloc (x->size*sizeof(int));
You need to allocate space for x->size integers. malloc accepts as parameter the number of bytes you need. And for n int you need n times the size in bytes of a single int.
Do not forget to return from the main.

How to pass an array properly to a threaded function with a structure

Ive been beating my head against the wall for days about this because I cant seem to find a good solution to this issue. I need to pass two arrays into a threaded function using a structure. One array is the structure Im needing to sum and the other is where the result of that summation needs to be stored and then I need to sum them one final time in the main program to get the total value.
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define NUMBER_OF_THREADS 2
typedef struct
{
double s[NUMBER_OF_THREADS];
double a[];
int tid;
} parmListType;
void *sum_arr(void *parms)
{
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t threads[NUMBER_OF_THREADS];
int status, i;
double arr[1000000]={};
double sum[NUMBER_OF_THREADS];
printf("debug_size_arr: %ld\n",sizeof(arr)/sizeof(double));
for(int i=0;i<sizeof(arr)/sizeof(double);i++)
{
arr[i]=i;
}
parmListType *parms;
for(i=0; i<NUMBER_OF_THREADS; i++)
{
printf("debug: Main here. Creating thread %d\n", i);
// dynamically create a structure to hold the parameter list
parms = (parmListType *)malloc( sizeof(parmListType));
//printf("debug_sizeof_paramA: %ld\n",sizeof(parms->a));
//parms->s[NUMBER_OF_THREADS/sizeof(double)]= *sum;
parms->tid = i;
status = pthread_create(&threads[i], NULL, sum_arr, (void *) parms);
if(status != 0)
{
printf("oops. pthread_create returned error code %d\n", status);
exit(-1);
}
printf("first for\n");
}
for(i=0; i<NUMBER_OF_THREADS; i++)
{
status=pthread_join(threads[i], NULL);
}
exit(0);
}
//// there are loads of errors in this code, I need guidance about how Im
////supposed to set this up right.
You can do st similar to the below:
struct ThreadArgs
{
int type;
//others
};
void* Thread(void* thread_args)
{
int type;
pthread_detach(pthread_self());
type = ((struct ThreadArgs *) thread_args)->type;
return NULL;
}
int main()
{
pthread_t thread_id;
struct ThreadArgs* thread_args;
thread_args = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs));
if (thread_args == NULL)
PanicWithError("malloc() failed");
thread_args->type = 1;
if (pthread_create(&thread_id, NULL, Thread, (void *) thread_args) != 0)
PanicWithError("pthread_create() failed");
while (1)
{}
return 0;
}

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.

create thread - passing arguments

I am attempting on creating multiple threads that each thread calculates a prime. I am trying to pass a second argument to a function using thread create. It keeps throwing up errors.
void* compute_prime (void* arg, void* arg2)
{
here is my main() with the create thread. &primeArray[i] after &max_prime is giving me the errors.
for(i=0; i< num_threads; i++)
{
primeArray[i]=0;
printf("creating threads: \n");
pthread_create(&primes[i],NULL, compute_prime, &max_prime, &primeArray[i]);
thread_number = i;
//pthread_create(&primes[i],NULL, compPrime, &max_prime);
}
/* join threads */
for(i=0; i< num_threads; i++)
{
pthread_join(primes[i], NULL);
//pthread_join(primes[i], (void*) &prime);
//pthread_join(primes[i],NULL);
//printf("\nThread %d produced: %d primes\n",i, prime);
printf("\nThread %d produced: %d primes\n",i, primeArray[i]);
sleep(1);
}
the error i get is:
myprime.c: In function âmainâ:
myprime.c:123: warning: passing argument 3 of âpthread_createâ from incompatible pointer type
/usr/include/pthread.h:227: note: expected âvoid * (*)(void *)â but argument is of type âvoid * (*)(void *, void *)â
myprime.c:123: error: too many arguments to function âpthread_createâ
It works fine if i take out the second argument.
You can only pass a single argument to the function that you are calling in the new thread. Create a struct to hold both of the values and send the address of the struct.
#include <pthread.h>
#include <stdlib.h>
typedef struct {
//Or whatever information that you need
int *max_prime;
int *ith_prime;
} compute_prime_struct;
void *compute_prime (void *args) {
compute_prime_struct *actual_args = args;
//...
free(actual_args);
return 0;
}
#define num_threads 10
int main() {
int max_prime = 0;
int primeArray[num_threads];
pthread_t primes[num_threads];
for (int i = 0; i < num_threads; ++i) {
compute_prime_struct *args = malloc(sizeof *args);
args->max_prime = &max_prime;
args->ith_prime = &primeArray[i];
if(pthread_create(&primes[i], NULL, compute_prime, args)) {
free(args);
//goto error_handler;
}
}
return 0;
}
In case of std::thread, the user can pass arguments to the thread function in the following method
std::thread(funcName,arg1,arg2);
for instance,
//for a thread function,
void threadFunction(int x,int y){
std::cout << x << y << std::endl;
}
// u can pass x and y values as below
std::thread mTimerThread;
mTimerThread = std::thread(threadFunction,1,12);
This is the code of Manakarse , everything is really good but you need a
pthread_join(thread[i],NULL)
just to be sure all of threads will successfully execute before end of main thread("main will "waiting" while all of threads aren't finished yet)
;
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
int stop_flag;
char name[30];
} _process_data;
typedef struct
{
int meter_no;
int port_no;
} _process_control;
typedef struct
{
_process_data *process_data;
_process_control *process_control;
} compute_prime_struct;
void *compute_prime (void *args)
{
compute_prime_struct *actual_args = args;
printf("actual_args->process_data->stop_flag [%d]\n",actual_args->process_data->stop_flag);
printf("actual_args->process_data->name [%s]\n",actual_args->process_data->name);
printf("actual_args->process_control->meter_no [%d]\n",actual_args->process_control->meter_no);
printf("actual_args->process_control->port_no [%d]\n",actual_args->process_control->port_no);
free(actual_args);
return 0;
}
void fill_data(_process_data *process_data,_process_control *process_control)
{
process_data->stop_flag=1;
process_data->name[0]='P';
process_control->meter_no=6;
process_control->port_no=22;
pthread_t tid;
compute_prime_struct *args = malloc(sizeof (*args));
args->process_data = malloc(sizeof (*args->process_data));
args->process_control = malloc(sizeof (*args->process_control));
memcpy (args->process_data, process_data, sizeof (args->process_data));
memcpy (args->process_control, process_control, sizeof (*args->process_control));
if(pthread_create(&tid, NULL, compute_prime, args))
{
free(args);
printf("Error here");
}
sleep(1);
}
int main()
{
_process_data process_data;
_process_control process_control;
fill_data(&process_data,&process_control);
return 0;
}

Resources