I'm trying to figure out the usage of pthread_exit using this example code:
void* PrintVar(void* arg)
{
int * a = (int *) arg; // we can access memory of a!!!
printf( "%d\n", *a);
}
int main(int argc, char*argv[])
{
int a, rc;
a = 10;
pthread_t thr;
pthread_create( &thr, NULL, PrintVar, &a );
//why do I need it here?//
pthread_exit(&rc); /* process continues until last
threads termintates */
there are two things I'm not quite sure about :
when we are using pthread_create - I'm passing 'a' parameter's address,
but is this paramter being "saved" under "arg" of the PrintVar function?
for example if I was using : PrintVar(void *blabla) , and wanted to pass 2 parameters from main function : int a = 10, int b= 20 .. how can I do that?
Why the pthread_exit needed? it means - wait for proccess to end - but what scenario can I get if I won't use that line?
thanks alot!
when we are using pthread_create - I'm passing 'a' parameter's address, but is this paramter being "saved" under "arg" of the PrintVar function?
The "original" a (the one defined in main) is not being copied, you are only passing around a pointer to it.
for example if I was using : PrintVar(void *blabla) , and wanted to pass 2 parameters from main function : int a = 10, int b= 20 .. how can I do that?
Put those two values in a struct and pass a pointer to such struct as argument to pthread_create (PrintVar, thus, will receive such a pointer and will be able to retrieve the two values).
and my second question is why the pthread_exit needed? it means - wait for proccess to end - but what scenario can I get if I won't use that line?
pthread_exit terminates the current thread without terminating the process if other threads are still running; returning from main, instead, is equivalent to calling exit which, as far as the standard is concerned, should "terminate the program" (thus implicitly killing all the threads).
Now, being the C standard thread-agnostic (until C11) and support for threading in the various Unixes a relatively recent addition, depending from libc/kernel/whatever version exit may or may not kill just the current thread or all the threads.
Still, in current versions of libc, exit (and thus return from main) should terminate the process (and thus all its threads), actually using the syscall exit_group on Linux.
Notice that a similar discussion applies for the Windows CRT.
The detached attribute merely determines the behavior of the system when the thread terminates; it does not
prevent the thread from being terminated if the process terminates using exit(3) (or equivalently, if the
main thread returns).
Related
I am trying to get the identifier of a thread, but it always returns some random numbers.
What isn't good here ?
// C program to demonstrate working of pthread_self()
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* calls(void* ptr)
{
// using pthread_self() get current thread id
printf("In function \nthread id = %d\n", pthread_self());
pthread_exit(NULL);
return NULL;
}
int main()
{
pthread_t thread; // declare thread
pthread_create(&thread, NULL, calls, NULL);
printf("In main \nthread id = %d\n", thread);
pthread_join(thread, NULL);
return 0;
}
Maybe it would be good time to read the documentation. For Linux, it is said that
NOTES
POSIX.1 allows an implementation wide freedom in choosing the type used to represent a thread ID; for example, representation using either an arithmetic type or a structure is permitted. Therefore, variables of
type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3) instead.
Thread identifiers should be considered opaque: any attempt to use a thread ID other than in pthreads calls is nonportable and can lead to unspecified results.
Thread IDs are guaranteed to be unique only within a process. A thread ID may be reused after a terminated thread has been joined, or a detached thread has terminated.
Which means that for example printing the value returned by pthread_self is not sensible.
In Linux/GLIBC the pthread_t type is actually the address of the "Thread Control Block" (TCB) of the thread (located at the bottom of its stack). This is unique. But as pointed out in a previous answer from #AnttiHaapala, no supposition can be done as the type should be considered opaque. So, printing it with a "%d" specifier is definitely not portable.
In Linux/GLIBC environment, you also have another unique identifier for a thread. This is its task identifier in the kernel obtained with a call to gettid(). It returns a pid_t typed value (signed integer suitable for "%d" format specifier) as discussed in this post.
You can use gettid(). Under Linux, it's available with glibc 2.30 or higher. If you have an older version, you can write your own trivial syscall wrapper.
#include <syscall.h>
static pid_t my_gettid(void)
{
return syscall(SYS_gettid);
}
#define gettid() my_gettid()
I've seen a few questions on user thread libraries, but none that seem to answer my question. I am able to create threads, run them, cancel them, and exit from them. What I cannot do for some reason is get a thread to return data.
When I initialize my thread library, I set my exit thread context as follows:
getcontext(&threadEnd);
threadEnd.uc_stack.ss_sp = (char *)malloc(SIGSTKSZ);
threadEnd.uc_stack.ss_size = SIGSTKSZ;
makecontext(&threadEnd, (void *) thread_exit, 1, &ReturnValue);
I create a thread and assign it as follows:
thread->myContext.uc_stack.ss_sp = (char *) malloc(SIGSTKSZ);
thread->myContext.uc_stack.ss_size = SIGSTKSZ;
thread->myContext.uc_link = &threadEnd;
When the function returns and thread_exit() is called:
void thread_exit(void* retval){
int* test;
if (retval != NULL)
{
test = (int*) retval;
printf("Returned value: %i\n", *test);
fflush(stdout);
}
The printout is always "Returned value: 0"
The called function is returning a pointer to an integer.
What am I doing wrong?
If you step through your program in GBD makecontext dose not save the return for the function used to make the context.
Example from my experiments: (observe the rax register):
at return statement:
thread1 (arg=0x1) at test_create_join.c:14
14 return (void *)11;
Value returned is $1 = 19
(gdb) info registers
rax 0x13 19
---
after return:
(gdb) step
15 }
(gdb) info registers
rax 0xb 11
inside context switch:
__start_context () at ../sysdeps/unix/sysv/linux/x86_64/__start_context.S:32
32 ../sysdeps/unix/sysv/linux/x86_64/__start_context.S: No such file or directory.
(gdb) info registers
rax 0xb 11
you can see for few instructions the return value is preserved but after few steps it becomes 0. Obviously its specific to x86_64 arch but I presume it might be same to most arch (ie the behavior of makecontext)
Now if you need the return value to your thread function you can go another way about it. Just create a thread handler for running your threads and use the handler for making new contexts. Here you can get the return for the functions you want to run as threads and save it in your thread control block structure for later use.
typedef struct {
thread_start_routine start;
void *arg;
} entry_point;
static void thread_runner(void *args) {
exit_critical_section();
entry_point *entry = (entry_point *) args;
// run the thread and get the exit code
current->retcode = entry->start(entry->arg);
}
You need some simple synchronization for waiting on one thread. The worker thread sets the variable test and signals.
// Pseudo code
// worker thread
retval = &VALUE; // retval is pointer?
SignalEvent( hEvent );
And the main thread:
// Pseudo code
// main thread
int* test;
hEvent = CreateEvent();
WaitOnEvent( hEvent );
if (retval != NULL)
{
test = (int*) retval;
printf("Returned value: %i\n", *test);
fflush(stdout);
}
And with many threads you need to decide whether you wait to simply on any of them or to any but until they all signaled or you want to wait until all signaled and then check on value. Also we usually consider whether or not the thread that waits on events does some idle looping while waiting and possibly doing some other job (a bit more complicated case).
Should you use C++ I could've provided an example with C++ 11 condition variable but with C it is usually either POSIX or Win32 API but we can use pseudocode. Win32 SetEvent and WaitForSingleObject. This POSIX topic pretty much covers condition variables for you.
Mind that with threads finishing one thread is also triggering the signal so in Win32 you can wait directly on thread handle but this approach is maybe not portable. Also threads and their synchronization are not part of C language standard so it only makes sense to apply to certain OS that provides both.
First of all, when supplying arguments to makecontext, last one should always be NULL:
makecontext(&threadEnd, (void *) thread_exit, 1, &ReturnValue, NULL);
I had the same problem, I tackled it a bit differently, namely instead of using uc_link I stored start_routine, i.e. func and arg inside of thread structure and used a wrapper function: a thread_runner that actually call a thread's function and stored the return value:
makecontext(&thread->ctx, (void *) thread_runner, 1, thread, NULL);
where thread runner is:
void thread_runner(thread_t *thread){
void **retval = thread->func(thread->arg);
if(retval != NULL){
thread_exit(*retval);
} else {
thread_exit(NULL);
}
}
We are not supposed to pass pointers in the parameter list of makecontext(). They must be integers as specified in the manual:
the function func is called, and passed the series
of integer (int) arguments that follow argc; the caller must
specify the number of these arguments in argc.
On some architectures, integers have the same size as pointers (e.g. 32 bits) but on others the pointer is 64 bits whereas the integer is 32 bits long. On recent GLIBC/Linux x86_64 architectures, the parameters are stored as "long long" integers in the context. And so, this may work as this makes the parameters stored as 64 bits values (compatible with the size of pointers) but this is not portable. So, this may explain why you don't get a correct value passing the "&ReturnValue" pointer.
I have a question about pthreads whith this little C source:
int calc = 0;
void func(void* data){
calc = 2 * 2;
return NULL;
}
int main(){
pthread_t t;
if(0==pthread_create(&t,NULL,func,NULL)){
if(0==pthread_join(t,NULL)){
printf("Result: %d\n",calc); // 4 ?
}
}
}
If pthread_join return success, is "func" always executed entirely ? (calc always equal 4 on printf ?).
The function pthread_join returns zero on success.
The documentation says that pthread_join blocks until the thread ends, so, with some applied logic one can easily conclude that the thread has ended.
On the other side, pthread_join fails in different ways:
When the handle is invalid: EINVAL
When a deadlock has been detected: EDEADLK
There is another possible error (recommended by the open group, but depending on the implementation): ESRCH, when it detects that the thread handle is being used past the end of the thread.
If you want to know more you may want to take a look at the documentation.
I'm trying to write some code using posix threads but I'm stuck from the first step and to be honest I can't realise why. I know that my problem has probably to do with some sort of synchronisation but I can't figure it out.
What I have in main is the following:
while(1){
int x = getX();
pthread_t t;
printf("Main: %d\n",x);
pthread_create(&t, NULL, process_x, &x);
}
When I try to print the x value from the main and also the process_x function what I get is something like this:
Main: 1
Main: 2
Main: 3
Main: 4
Main: 5
Process_x: 5
What do I miss here?
---- EDIT -----
OK, maybe I need to provide some more info. The getX function receives data from a socket and returns an identifier while for our needs now the process_x just prints the argument it receives.
You need to consider that you pass the address of x to a thread, and then without waiting for the thread to finish printing, you modify it's value. Obviously, this will mean that if a few iterations are over before the thread gets to print it's value, the value would have changed.
Two Ways around this:
1) Use a pthread_join and wait for the thread to finish. This is esseentially useless. Because then what is the point of spawning the new thread?
OR
2) Allocate a new address for each thread, and let the thread free it after it finishes printing.
i.e. malloc a new integer, assign x to that integer, pass the new mallocd integer to the thread, let the thread free it when done.
A thread will not be executed as soon as you create it using a call to pthread_create. The scheduler can decide to keep it in queue. During that time your while loop has run 5 times and value of x might also have changed to 5. Now when your thread(s) is(are) eventually scheduled, it(they) only sees the latest value of your x and hence print(s) only 5.
I strongly suspect that Process_x was printed only once?
There is no default way to get pthreads executed in any specific order. You need to use some synchrnization techniques like semaphores. Also if you want to see Process_x print all your values, convert x into an array and pass x[i] as argument to pthread_create
Apparently using malloc doesn't work because it sets x to 0 so the process always reads 0. But thanks to everyones ideas I finally made it work using a condition variable and now everything is ok. Here is the code.
int main{
pthread_t t;
int x;
while(1){
pthread_mutex_lock(&receive);
x = getX();
printf("Main: %d\n",x);
pthread_create(&t, NULL, process_x, &x);
pthread_cond_wait(&goOn, &receive);
pthread_mutex_unlock(&receive);
}
}
void *process_x(void* arg){
pthread_mutex_lock(&receive);
int x = *(int *) arg;
pthread_cond_signal(&goOn);
pthread_mutex_unlock(&receive);
}
I would like to know the difference between a thread entry function:
void* thread_function (void* parameter)
{
struct parameter * thread_data = (struct parameter *)parameter;
char buffer[20];
int temp;
printf_buffer(buffer);
}
and a normal function:
void printf_buffer(char *buffer)
{
printf("buffer is %s",buffer);
return;
}
I know a thread entry is called when a thread is created, and how normal functions are used.
Are there any other differences between thread entry functions and a normal functions in terms of execution , behavior, or creating instances?
There is no difference in the language between what you call a "thread function" (although Justin has edited to call it a "thread entry function") and what you call a "normal function".
With pthreads, the so-called "start routine" of a thread is a function that takes a single void* parameter and returns void*, but there's nothing to stop you calling the same function "normally".
When the start routine of a thread returns, the thread finishes execution, but that's just because the threading implementation calls it, and then finishes the thread. It's not because of anything special to do with the start routine itself.
A thread function is just the entry/exit point of a thread. The execution of that function is no different from what you refer to as a normal function.
man pthread_create defines it quite well:
http://linux.die.net/man/3/pthread_create
one major difference that has not been mentioned yet is that the thread entry should expect to operate on a stack other than the caller's. for this reason, you will often want to pass heap copies of resources as your argument when your thread is detached, then free it in the entry:
// the caller must pass a heap copy of struct parameter* arg
void* detached_entry(void* arg) {
struct parameter* parameter = (struct parameter*)arg;
...
free(parameter);
}