Passing data to Pthread using structure in C - c

I want to run Pthreads in c. i am comfortable with sending integer values to Pthread in c. But when I am passing the data structure to the thread, it is printing garbage values.
My code is as follows:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_THREADS 3
typedef struct MyStructure
{
int id;
char *myName;
}myst;
void *PrintHello(void *threadArgs)
{
myst *myPersonalSt;
myPersonalSt = (myst *) threadArgs;
printf("Thread %d and Name : %s \n", myPersonalSt->id ,
myPersonalSt->myName);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUMBER_OF_THREADS];
long taskids[NUMBER_OF_THREADS];
int rc, t;
char myNameArray[NUMBER_OF_THREADS][100] = {"kp" , "kkp" , "ap"};
myst **mystArray;
mystArray = (myst **)malloc(NUMBER_OF_THREADS*sizeof(myst));
for(t=0;t<NUMBER_OF_THREADS;t++)
{
mystArray[t] = (myst *)calloc(1,sizeof(myst));
mystArray[t]->id = t+1;
mystArray[t]->myName = myNameArray[t];
}
for(t=0;t<NUMBER_OF_THREADS;t++) {
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) mystArray);
if (rc) {
printf("ERROR; return code from
pthread_create() is %d\n", rc);
exit(-1);
}
}
for(t=0;t<NUMBER_OF_THREADS;t++) {
pthread_join(threads[t],NULL);
}
pthread_exit(NULL); // this takes an input parameter !
}
I was thinking that it was a problem with MALLOC (because it doesn't initialize memory allocated). So I used CALLOC , but the same problem occured.

rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) mystArray);
You're missing the array index here, you mean mystArray + t.
On a side note: remove all these casts, they make the code hard to read. void * is generic and implicitly convertible in c.

This line is wrong:
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) mystArray);
Given how you're written the rest of the code, it should be:
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) ( mystArray[t] ) );
But the use of malloc()/calloc() is unnecessary:
myst mystArray[ NUMBER_OF_THREADS ];
memset( mystArray, 0, sizeof( mystArray ) );
...
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) &( mystArray[t] ) );
That will work without the malloc()/calloc().

Related

How to get one correct value from a function which is parallelized by multi-threads

For faster calculation, trying to make my method parallelized by 4 threads. Where threads are making 4 separate calculation whether I was expecting concurrent operation and on single variable.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static int x, j=5;
void *print_count (void *dummy)
{
for(int i=0;i<1000;i++){
x+=j;
}
}
int main ()
{
pthread_t p1, p2, p3, p4;
pthread_create (&p1, NULL, print_count, NULL);
pthread_create (&p2, NULL, print_count, NULL);
pthread_create (&p3, NULL, print_count, NULL);
pthread_create (&p4, NULL, print_count, NULL);
pthread_join (p1, NULL);
pthread_join (p2, NULL);
pthread_join (p3, NULL);
pthread_join (p4, NULL);
printf("Actual output: %d \nExpected output: 5000\n", x);
return 0;
}
I expect the output 5000 as the increment is 5 and loop for 1000 times.
But the actual output first of all not static, it always change and it is near 4 times of 5000 because threads are calculating the print_count separately.
Thank you
If you are under C11 you can use _Atomic
Of course each thread needs to work over a range of values (not with the complete set), pass a struct:
#include <stdio.h>
#include <stdatomic.h>
#include <pthread.h>
_Atomic int x;
static int j = 5;
struct range {
int from, to;
};
void *print_count(void *data)
{
struct range *range = data;
for (int i = range->from; i < range->to; i++) {
x += j;
}
return NULL;
}
int main(void)
{
pthread_t p1, p2, p3, p4;
struct range ranges[] = {
{0, 250},
{250, 500},
{500, 750},
{750, 1000}
};
pthread_create(&p1, NULL, print_count, &ranges[0]);
pthread_create(&p2, NULL, print_count, &ranges[1]);
pthread_create(&p3, NULL, print_count, &ranges[2]);
pthread_create(&p4, NULL, print_count, &ranges[3]);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
pthread_join(p3, NULL);
pthread_join(p4, NULL);
printf("Actual output: %d \nExpected output: 5000\n", x);
return 0;
}
Or a compound literal:
pthread_create(&p1, NULL, print_count, (int []){ 0, 250});
pthread_create(&p2, NULL, print_count, (int []){250, 500});
pthread_create(&p3, NULL, print_count, (int []){500, 750});
pthread_create(&p4, NULL, print_count, (int []){750, 1000});
...
void *print_count(void *data)
{
int *range = data;
for (int i = range[0]; i < range[1]; i++) {
x += j;
}
return NULL;
}
in order to divide the task.
Output:
Actual output: 5000
Expected output: 5000

Synchronize N-processes in strict order with Semaphores

I'm facing simple issue with Semaphore's task.
I am having N-processes (P1, P2, P3, P4...Pn). No matter in what order I create threads, I need them to execute in exact order (P1, P2, P3, P4...Pn). I need to come with solution, where I use minimum semaphores required.
It would be quite simple using Mutex, but the task says "use only semaphores".
I'm using only one semaphore. In while, within the condition, if order number is NOT equals your ID number, just unlock semaphore and cycle in while, till order number is equals to your ID number.
I think that problem might be with "Spurious wakeups".
Here is my code:
sem_t semvar;
int order = 0;
void *sayHello(void *thread_id){
int *my_id = (int *) thread_id;
while(1)
{
// take semaphore and close critical zone to read order variable to recognize who's on turn!
sem_wait(&semvar);
if(*my_id == order)
{
// if I'm on turn, then I shout my number and set order variable to someone behind me
printf("I'm thread no.: %d\n", *my_id);
order++;
break;
}
// release semaphore if I'm not on turn!
sem_post(&semvar);
}
// release semaphore if it was my turn, I shout my number and gonna end (die)!
sem_post(&semvar);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
int numbOfThreads = 13;
int *thread_id[numbOfThreads];
int new_thread, i;
pthread_t threads[numbOfThreads];
// generating thread numbers --> NOTE: you need this, if you use random thread generating!!!
for(i = 0; i < numbOfThreads; i++)
{
thread_id[i] = (int *) malloc(sizeof(int));
*thread_id[i] = i;
}
// random thread generating for testing to make sure it works
pthread_create(&threads[10], NULL, sayHello, (void *) thread_id[10]);
pthread_create(&threads[12], NULL, sayHello, (void *) thread_id[12]);
pthread_create(&threads[8], NULL, sayHello, (void *) thread_id[8]);
pthread_create(&threads[3], NULL, sayHello, (void *) thread_id[3]);
pthread_create(&threads[5], NULL, sayHello, (void *) thread_id[5]);
pthread_create(&threads[1], NULL, sayHello, (void *) thread_id[1]);
pthread_create(&threads[0], NULL, sayHello, (void *) thread_id[0]);
pthread_create(&threads[4], NULL, sayHello, (void *) thread_id[4]);
pthread_create(&threads[7], NULL, sayHello, (void *) thread_id[7]);
pthread_create(&threads[6], NULL, sayHello, (void *) thread_id[6]);
pthread_create(&threads[2], NULL, sayHello, (void *) thread_id[2]);
pthread_create(&threads[9], NULL, sayHello, (void *) thread_id[9]);
pthread_create(&threads[11], NULL, sayHello, (void *) thread_id[11]);
/*
// automatic thread generating
for(i = 0; i < numbOfThreads; i++)
{
thread_id[i] = (int *) malloc(sizeof(int));
*thread_id[i] = i;
new_thread = pthread_create(&threads[i], NULL, sayHello, (void *) thread_id[i]);
if(new_thread)
{
printf("Error has occured");
exit(-1);
}
}
*/
// do not end main function before all the threads are done with work!
for(i = 0; i < numbOfThreads; i++)
{
pthread_join( threads[i], NULL);
}
printf("All the threads are gone!");
return 1;
}

implementing and testing thread_create function

I'm very new in C and Linux and English is not my mother language. Sorry in advance.
I'm working on a school project which is implementing thread api and I made the thread_create() function using clone().
The problem is that when I call thread_create(&tid1, NULL, (void *)Testcase1, 0); ,
it creates a new thread but TestCase1 also includes thread_create and it doesn't seem create another thread. Let me explain with my code below:
int foo(void* arg){
printf("Hii");
return 0;
}
int thread_create(thread_t *thread, thread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
void* stack;
stack= malloc( STACK_SIZE );
pid_t pid;
if( stack==0)
{
perror( "malloc : could not allocate stack" );
exit( 1 );
}
pid = clone( &foo ,( char* )stack+STACK_SIZE,SIGCHLD|CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES,0 );
if(pid == -1)
{
perror("clone");
exit(2);
}
kill(pid, SIGSTOP);
Thread* newTCB = (Thread*)malloc(sizeof(Thread));
newTCB->stackSize = malloc(STACK_SIZE);
newTCB->pid = pid;
newTCB->status = THREAD_STATUS_READY;
rEnqueue(newTCB);
rPrintqueue();
free(stack);
printf("Child thread returned and stack freed.\n");
return 0;
}
And this is my test code below:
thread_create(&tid1, NULL, (void*)TestCase1, 0);
TestCase1() below:
int Tc1ThreadProc(int param)
{
int tid = 0;
int count = 0;
tid = thread_self();
count = 3;
while (count > 0)
{
/* sleep for 1 seconds */
sleep(2);
printf("Tc1ThreadProc: my thread id (%d), arg is (%d)\n", tid, param);
count--;
}
}
void TestCase1(void)
{
thread_t tid[TOTAL_THREAD_NUM];
thread_create(&tid[0], NULL, (void*)Tc1ThreadProc, (int*)1);
thread_create(&tid[1], NULL, (void*)Tc1ThreadProc, (int*)2);
thread_create(&tid[2], NULL, (void*)Tc1ThreadProc, (int*)3);
while(1){}
return ;
}
it's supposed to print "Tc1ThreadProc: my thread id (%d), arg is (%d)\n" 3 times but it prints only "Hii" which is because of the call to foo().
How do I fix this?
You pass pointer to function "TestCase1" as argument to "thread_create", but inside "thread_create" you don't use it at all:
thread_create(&tid1, NULL, (void*)TestCase1, 0);
You're calling "clone" syscall only with pointer to "foo" function.
From inside "thread_create" your "TestCase1" pointer is named "start_routine", so you need to call similar "clone" syscall, but instead pointer to "foo" you should pass pointer to "TestCase1". Something like that:
pid = clone( start_routine, (char*) stack + STACK_SIZE, SIGCHLD | CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES, 0);

Accessing the return value using pthread_exit()

I have done the following code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
struct foo
{
int a;
int b;
};
void* thread_func1(void *arg)
{
struct foo *temp = (struct foo*)malloc(sizeof(struct foo));
temp->a = 10;
temp->b = 20;
pthread_exit(temp);
}
void* thread_func2(void *arg)
{
pthread_exit((void*)100);
}
int main()
{
pthread_t tid1, tid2;
int err;
struct foo *f;
void *ret;
err = pthread_create(&tid1, NULL, thread_func1, NULL);
err = err | pthread_create(&tid2, NULL, thread_func2, NULL);
if(err != 0)
{
perror("pthread_create()");
exit(-1);
}
err = pthread_join(tid1, (void**)&f);
if(err != 0 )
{
perror("pthread_join1");
exit(-1);
}
printf("a = %d, b = %d\n", f->a, f->b); //Line1
err = pthread_join(tid2, &ret);
if(err != 0 )
{
perror("pthread_join2");
exit(-1);
}
printf("ret = %d\n", *(int*)ret); //Line2
return 0;
}
I get segmentation fault on Line2. What is wrong with Line2
If i modify Line2 to
printf("ret = %d\n", (int)ret);
there is no segmentation fault and it prints the correct value(ie, 100). I do not understand why the modification works. I believe i have the wrong concept regarding the usage of double pointers. I would like to get it corrected.
What is the reason for the Segmentation fault and why the modification works?
That's because you are returning the actual integer, not a pointer, but you access it as a pointer.
You return one number from the thread. In the first thread, that number is a struct foo *. Therefore, if you say
pthread_join(tid1, &ret);
then ret will contain that pointer (which is not a double pointer).
Similarly in the second case, you are returning 100 even though you are looking at it as if it's a void *. Nevertheless, the value is still 100!
Therefore when you write
pthread_join(tid2, &ret);
ret will contain 100, which is not a pointer, but a mere integer. That is why you should also cast it to int.
The reason you got a segmentation fault is that you look at 100 as an int * and then try to dereference it.
pthread_exit((void*)100); causes integer 100 to become exit status of your thread. It just abuses type cast so that void* is its type.
If you want to retrieve this value, you will have to use same type cast abuse in main thread as well:
int ret;
err = pthread_join(tid2, (void**) &ret);
// here you can work with ret as with any other integer
I also suggest you to use return instead of pthread_exit. Also note that memory dynamically allocated by using malloc should be freed by calling free. And type cast of return value of malloc is redundant here, it can be omitted.
This question could also help you: Close a thread when done with it
Its because you're trying to dereferencce a pointer whose address is 100.
Instead of looking at the return value, why dont you pass in a pointer to what you want to assign in the thread_funcs? That is, use the "void *arg" arguments of thread_func1() and thread_func2()
Like this:
void* thread_func1(void *arg)
{
struct foo **fooPtrPtr = (struct foo**) arg;
*fooPtrPtr = (struct foo*)malloc(sizeof(struct foo));
...
}
void* thread_func2(void *arg)
{
int *intPtr = arg;
*intPtr = 100;
...
}
int main()
{
pthread_t tid1, tid2;
int err;
struct foo *f;
int ret;
err = pthread_create(&tid1, NULL, thread_func1, &f);
err = err | pthread_create(&tid2, NULL, thread_func2, &ret);
...
printf("a = %d, b = %d\n", f->a, f->b); //Line1
...
printf("ret = %d\n", ret); //Line2
...
}

First time using pthreads in C, why is nothing returned from these ones?

In the following code:
int main (int argc, const char * argv[]) {
// insert code here...
pthread_t t1, t2;
int sp1, sp2;
sp1 = pthread_create( &t1, NULL, getScalarProduct, NULL);
sp2 = pthread_create( &t2, NULL, getScalarProduct, NULL);
pthread_join( t1, NULL);
pthread_join( t2, NULL);
printf("Seperate scalars: %d %d\n", sp1, sp2);
finalScalarProd = sp1 + sp2;
printf("Result: %d\n", finalScalarProd);
return 0;
}
I've been unable to get anything back other than zero for the finalScalarProduct, and both sp1 and sp2 are zero also. I believe it's something to do with the NULL argument being passed in pthread_join. I don't really understand what this argument is for.
Any help appreciated!
That's because pthread_create returns zero upon success.
The value is not the result of the main thread function, but the result of the thread creation (that might fail in some cases).
void * threadMainFunc(void * arg) {
// modify arg like this
int * ip = (int *)arg;
*ip = 3; // this is the "return value"
return NULL;
}
pthread_create( &t1, NULL, threadMainFunc, &sp1);

Resources