#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#define N_ASS 4
pthread_t tid[N_ASS];
//mutex
pthread_mutex_t mutex;
//variabili condition
pthread_cond_t c_ass[N_ASS], c_pass[N_PASS];
void * checkDoc ()
{
printf("do stuff\n");
}
int main()
{
int err;
int i = 0;
for(i;i<N_ASS;i++){
err = pthread_create (&tid[i], NULL, checkDoc(), NULL);
pthread_cond_wait(&c_ass[i],&mutex);
}
for(i=0;i<N_ASS;i++)
pthread_cond_signal(&c_ass[i]);
for(i=0;i<N_ASS;i++) {
err = pthread_join(tid[i],NULL);
printf("%d joined\n",i);
}
printf("End\n");
}
I just want to say that I'm a little noob who is just learning and this is my first question, if I have to do something else just tell me and I'll do it!
So this is the code, I got one first problem, it makes segmentation-fault and I don't know why.
The output is:
do stuff //1,2,3 or 4 time
Segmentation fault
Nothing else, i runned at least 20 time.
You should be getting compiler warnings here, as the thread function (or rather what is supposed to be the thread function) doesn't return anything.
This will lead to undefined behavior because you don't pass a pointer to the checkDoc function to pthread_create, you actually call the checkDoc function, and use the returned pointer as the pointer to the thread function. As the checkDoc function doesn't actually return anything you will have undefined behavior, and most likely a crash.
Simple solution? Don't call the checkDoc function:
pthread_create (&tid[i], NULL, checkDoc, NULL)
// ^^^^^^^^
// No longer calling the function
And if you state that a function returns a value, you should actually do it. If the returned value is not used then just return NULL.
Also, in C when you declare a function without any formal arguments, it's the same thing as saying that the function accepts any number of arguments of any type. POSIX thread functions must specifically accept a void * argument. If you do not use the argument in the thread function, then simply don't name the argument:
void * checkDoc (void *) { ... }
This last bit also has implications for the main function, as the C specification explicitly says that the main function should either take two arguments (an int and an char *[]), or be void. If you have a function which doesn't take any arguments you must explicitly say that by using void as argument.
There are also other issues with your code. Like you not initializing the structures you use properly. Or like you waiting for the condition variable right after creating the each thread, and as you don't signal the condition variable until after you start waiting for it then you will wait forever and the code will not continue to the part where you actually call the signalling function.
Related
I think the print result should be 500, but the result was weird - it said 32728, which is meaningless.
#include<stdio.h>
#include<pthread.h>
void* testFunction(void*);
int main(void)
{
void* result;
pthread_t tid;
pthread_create(&tid, NULL, testFunction, NULL);
pthread_join(tid, &result);
printf("%d\n", *((int*)result));
}
void* testFunction(void* args)
{
int time;
time = 500;
pthread_exit((void*)&time);
}
In this code, this is the flow of what I thought
(void*)result has time's address.
(int*)result has time's address. Because of (int*), the program should know result variable is referring to int-type variable.
*((int*)result) means the value of what result variable refers to, so it would be time's value, which is 500.
Can you let me know what I thought wrong?
The problem is that time no longer exists by the time you come to check it. One way around that is to play with the casting. Instead of
pthread_exit((void*)&time);
use
pthread_exit((void*)time);
Then, when you are extracting the result, use
*((int) result)
Another minimal fix is to make time a static. That way, it is not stored in the stack and always exists.
What's wrong is that time is going out of scope when the thread function exits, meaning that dereferencing its address is undefined behaviour. And you are dereferencing after that, since it happens after the pthread_join() call.
There's a chance that something else will be using that memory (probably on the stack but no mandated, since a stack isn't itself mandated), which would explain the strange value.
But, regardless of what's actually happening, it's not something you're allowed to do in C. Or, more correctly, you can do it, just don't expect sane results.
As others already pointed out, the problem is that the pointer received by pthread_join() points nowhere the moment the function returned. As the memory allocate for int time has already been deallocated, as the function has already ended.
There are two possibilities to have pthread_join() return a pointer to valid memory:
Have the thread function allocate it dynamically.
#include <stdlib.h> /* For malloc() and free(). */
#include <stdio.h>
#include <pthread.h>
void* testFunction(void* pv_unused)
{
int * ptime = malloc(sizeof *ptime);
/* Add error checking/handling here! */
*ptime = 500;
pthread_exit(ptime);
}
int main(void)
{
...
pthread_join(tid, &result);
printf("%d\n", *((int*)result));
free(result); /* Free the memory that has been allocated by the thread-function. */
}
Pass a pointer to valid memory to the thread-function.
#include <stdio.h>
#include <pthread.h>
void* testFunction(void* pv_time)
{
int * ptime = pv_time;
*ptime = 500;
pthread_exit(ptime);
}
int main(void)
{
pthread_t tid;
int time;
pthread_create(&tid, NULL, testFunction, &time);
{
void * pv;
pthread_join(tid, &pv);
if (pv != &time)
{
/* Something went wrong! */
}
}
printf("%d\n", time);
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct Array
{
//
};
void* evensum(void* param)
{
//calculated the sum of even elements and returned it
}
void* oddsum(void* param)
{
//did the same thing but for odd elements
}
int main()
{
struct Array* obj=malloc(sizeof(struct Array));
//did all the inputs
int evensum,oddsum;
pthread_t thread1,thread2;
pthread_create(&thread1,0,&evensum,(void*)obj);
int evensum,oddsum;
pthread_join(&thread,(void**)evensum);
pthread_create(&thread2,0,&oddsum,(void*)obj);
pthread_join(&thread2,(void**)oddsum);
//try to print it using %i but I get or %d
// I get the sum as zero
}
So I created two separate threads and these threads were meant to work asynchronously. I followed the advice mentioned here but the join still doesn't work as once the thread1 finishes execution, the other thread is never created despite me following the correct syntax. Any idea how to fix this?
Also, the value printed is zero, despite showing the correct value if I print it in the function.
Here is what I wrote in the return statement of each function:
return (void*)sum;//variable that stores sum
Also, I want to add that I don't want to use semaphores or any other synchronization tool to do this.
The second parameter to pthread_join is a void **, i.e. it expects a pointer to a void * which it dereferences to store the value in. Because you're not passing the address of a variable, this function will attempted to use whatever value you passed in as an address (which would likely be invalid) and dereference it. This invokes undefined behavior.
Also, the first parameter is of type pthread_t but you're passing a pointer to a pthread_t.
You're also declaring local variables with the same names as the functions you're calling. As a result, when you call pthread_create(&thread2,0,&oddsum,(void*)obj); you're actually passing the local int variable called oddsum and not the function called oddsum. That's why it hangs.
Changing the name of the variables to hold the results, changing the pthread_join calls to pass the addresses of these variables and passing the thread IDs directly should work:
int evenresult;
pthread_join(thread,(void**)&evenresult);
...
int oddresult;
pthread_join(thread2,(void**)&oddresult);
The proper way to do retrieve the result however would be to pass the addresses of actual void * variables and converting them:
int evenresult, oddresult;
void *result;
pthread_join(thread, &result);
evensum = (intptr_t)result;
...
pthread_join(thread2, &result);
oddsum = (intptr_t)result;
Create all the thread and then join them like below:-
pthread_create(&thread1,0,&evensum,(void*)obj);
pthread_create(&thread2,0,&oddsum,(void*)obj);
pthread_join(&thread1,(void**)evensum);
pthread_join(&thread2,(void**)oddsum);
In my program, a call to pthread_create looks like:
res = pthread_create(&a_thread, NULL, thread_fn, (void*)n);
My question is, why can't we make it:
res = pthread_create(&a_thread, NULL, thread_fn( (void*)n) );
since this will reduce the number of parameters in pthread_create and also looks logical, as for a function I have learnt only 3 things: declaration, definition and calling.
Passing the function name as a parameter and adding to that passing its argument as a separate parameter is a thing I don't understand.
If there is any logic behind this format, kindly explain.
The most obvious argument would be that you cannot call thread_fn "as an argument" because then it would need to run to completion before pthread_create could be called -- that is, you would run the code destined for the new thread in the current thread.
Another way of looking at things is that creating a thread of execution necessarily taps into OS (kernel) code; the OS needs to set up its internal bookkeeping structures before the new thread becomes effectively usable. A kernel call such as caused by pthread_create needs to know the memory address of the code to be executed in a thread so that it can transfer control to that location after setting everything up, and passing the address of a function (as opposed to its return value) is done with the first syntax.
res = pthread_create(&a_thread, NULL, thread_fn( (void*)n) );
Keep in mind that the part in bold is a function call. The semantics of the C language call for execution of that function call, and then substituting its return value in it's place. So, this syntax, is equivalent to the following sequence of things.
temp = thread_fn( (void*)n) // function call
res = pthread_create(&a_thread, NULL, temp)
This is obviously not what you want. What you want is for the function pthread_create to first create a separate thread of execution, which executes the function call thread_fn with the argument that you specified.
Following is what pthread_create needs to do.
Create a new thread execution context.
Setup the call context for thread_fn i.e. setup stack and arguments etc.
Arrange for thread_fn to be entered.
Because the function thread_fn gets executed in a deferred fashion, the only way to do it is to set aside the function entry point and its arguments, and then arrange for it be executed. Which is why these are passed in as arguments to pthread_create.
When you call a function as a parameter to a function call, what actually happens is that the function is called and the return value is placed on the stack to pass to the function you are calling.
strthings(getStr1(), strlen(getStr1()), getStr2(), strlen(getStr2()));
translates to (the order may vary depending on compiler/cpu)
auto t1 = getStr2(); // probably not exact order
auto t2 = strlen(t1);
auto t3 = getStr1();
auto t4 = strlen(t3);
strthings(t3, t4, t1, t2);
So - your piece of code:
*res = pthread_create (&a_thread , NULL , thread_fn( (void*)n) )
would translate to
// run the thread function and get the return value.
auto t1 = thread_fn((void*n));
*res = pthread_create(&a_thread, NULL, t1);
We'd be running the thread_fn in OUR thread context and then passing it's return value. It sounds like you were expecting functions-as-parameters to be passed to the called function and interpreted inline?
Why does passing the function and the argument work?
--- EDIT: Explanation of why passing a function and parameter separately works.
In C, function names are actually pointer variables. The type of the pointer depends on the 'fingerprint' of the function.
int strncmp(const char* left, const char* right, int maxlen);
is actually
int (*strncmp)(const char*, const char*, int);
that is, strncmp is a pointer to a function returning a void and taking three arguments of the specified types.
This forms a contract, so that when you write
int n = strncmp(a, b, 3);
it knows to do something in [presudo] assembly like:
push a
push b
push 3
call 0x783af83 // strncmp
mov return -> n
pop 12
So - now that you know functions are actually pointers (to code) you can see how it is possible to pass them, so that you can do things like:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int func1() { return 1; }
int func2() { return 22; }
int flip(int useFirst, int (*first)(), int (*second)()) {
return (useFirst) ? first() : second();
}
int main() {
srand(time(NULL));
int useFirst = rand() % 2;
int result = flip(useFirst, func1, func2);
printf("use first is %u. return value was %u.\n", useFirst, result);
}
I have a question about C concurrency programming.
In the pthread library, the prototype of pthread_join is
int pthread_join(pthread_t tid, void **ret);
and the prototype of pthread_exit is:
void pthread_exit(void *ret);
So I am confused that, why pthread_join takes the return value of the process as a pointer to a void pointer from reaped thread, but pthread_exit only takes a void pointer from the exited thread? I mean basically they are all return values from a thread, why there is a difference in type?
In pthread_exit, ret is an input parameter. You are simply passing the address of a variable to the function.
In pthread_join, ret is an output parameter. You get back a value from the function. Such value can, for example, be set to NULL.
Long explanation:
In pthread_join, you get back the address passed to pthread_exit by the finished thread. If you pass just a plain pointer, it is passed by value so you can't change where it is pointing to. To be able to change the value of the pointer passed to pthread_join, it must be passed as a pointer itself, that is, a pointer to a pointer.
It because every time
void pthread_exit(void *ret);
will be called from thread function so which ever you want to return simply its pointer pass with pthread_exit().
Now at
int pthread_join(pthread_t tid, void **ret);
will be always called from where thread is created so here to accept that returned pointer you need double pointer ..
i think this code will help you to understand this
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
void* thread_function(void *ignoredInThisExample)
{
char *a = malloc(10);
strcpy(a,"hello world");
pthread_exit((void*)a);
}
int main()
{
pthread_t thread_id;
char *b;
pthread_create (&thread_id, NULL,&thread_function, NULL);
pthread_join(thread_id,(void**)&b); //here we are reciving one pointer
value so to use that we need double pointer
printf("b is %s\n",b);
free(b); // lets free the memory
}
The typical use is
void* ret = NULL;
pthread_t tid = something; /// change it suitably
if (pthread_join (tid, &ret))
handle_error();
// do something with the return value ret
I want to write a multi threaded program in c language. I use posix thread library.
I write the following code:
#include<stdio.h>
#include<pthread.h>
void *put (int *arg)
{
int i;
//int * p;
// p=(int*)arg;
for(i=0;i<5;i++)
{
printf("\n%d",arg[i]);
}
pthread_exit(NULL);
}
int main()
{
int a[5]={10,20,30,40,50};
pthread_t s;
pthread_create(&s,NULL,put,a);
printf("what is this\n");
return 0;
}
I just want my thread just show the items in the array. The program compiled with following warning:
tm.c:19: 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 * (*)(int *)’
When I run the program I got the out put of main thread but not the value stored in array.
Now can anyone tell me what I'm doing wrong?
How to send the array as an argument in the thread function?
If I just changed the code little bit the compile time warning resolved the changed code is following:
#include<stdio.h>
#include<pthread.h>
void *put (void *arg)
{
int i;
int * p;
p=(int*)arg;
for(i=0;i<5;i++)
{
printf("\n%d",p[i]);
}
pthread_exit(NULL);
}
int main()
{
int a[5]={10,20,30,40,50};
pthread_t s;
pthread_create(&s,NULL,put,a);
printf("what is this\n");
return 0;
}
But the output does not change. Can any one tell me what i did wrong? What is the proper way to send array to a thread function (put in this case)?
Your code creates the thread and then the process exits by reaching the end of main. You have to wait for the thread to have a chance to execute, by calling pthread_join, or sleeping for a bit.
First of all, you need to wait for the thread to finish before returning from main().
Another problem with this code is that the array a is allocated on the stack of the main() routine and is thus potentially invalid in the context of a different thread. You should heap allocate a with a call to malloc().
If you wait for the thread to finish in main() then a is probably valid since the stack frame for main() will still exist. However, any future refactorings are liable to cause you grief so please switch to using malloc().
Try to wait for your thread to execute, add
pthread_join(s, NULL);
before your return 0;