How can a thread function access variables of the parent thread - multithreading

I read that threads share the memory address space of it's parent thread.
If that is true , why can't a thread function access a local variable belonging to it's parent thread ?
void* PrintVar(void* arg){
printf( "%d\n", a);
}
int main(int argc, char*argv[]) {
int a;
a = 10;
pthread_t thr;
pthread_create( &thr, NULL, PrintVar, NULL );
}
If the thread shares the address space , then the function PrintVar should have been able to print the value of variable a , right ?
I read this piece of info on http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
Threads in the same process share:
Process instructions
Most data
open files (descriptors)
signals and signal handlers
current working directory
User and group id
If that is true, then why does int a not qualify as a shared variable ?
I'd like to see an example code where the file descriptors are shared

The child thread can access the variable in the stack of the parent thread, it just needs to know the variable's address. For example, you could do it like this:
void* PrintVar(void* arg){
int * a = (int *) arg;
printf( "%d\n", *a);
}
int main(int argc, char*argv[]) {
int a;
a = 10;
pthread_t thr;
pthread_create( &thr, NULL, PrintVar, &a );
}
Note that this sort of thing can be tricky, since you have to (one way or another) guarantee that (a) won't get destroyed while the child thread is still accessing it. (In this case you'd probably want to call pthread_join() at the end of main(), so that the main thread will block there and not return from main() until after the child thread has exited)

you couldn't do that even if this were not a thread, because a is out of scope.
put a in the global scope, like so:
int a;
void* PrintVar(void* arg){
printf( "%d\n", a);
}
int main(int argc, char*argv[]) {
a = 10;
pthread_t thr;
pthread_create( &thr, NULL, PrintVar, NULL );
}
This is actually not an issue of threads. consider the following code:
void PrintVar(){
printf( "%d\n", a);
}
int main(int argc, char*argv[]) {
int a;
a = 10;
PrintVar();
}
This obviously won't work, because the variable name a declared in main is not visible in PrintVar, because it's in the local scope of another block. This is a compile-time problem, the compiler just doesn't know what you mean by a when you mention it in PrintVar.
But there is also another threading issue. when the main thread of a process exit, all other threads are terminated (specifically, when any thread calls _exit, then all threads are terminated, and _start calls _exit after main returns). but your main returns immediately after invoking the other thread. To prevent this, you should call pthread_join which will wait for a thread to exit before returning. that'll look like this
int a;
void* PrintVar(void* arg){
printf( "%d\n", a);
}
int main(int argc, char*argv[]) {
void *dummy;
a = 10;
pthread_t thr;
pthread_create( &thr, NULL, PrintVar, NULL );
pthread_join( thr, &dummy);
}

Related

Trigger multiple pthreads by pthread_cond_broadcast

Since the examples for pthreads with pthread_cond_broadcast wakeup are sparse i wrote one, but are unsure if this is correctly synchronized and the way to do it:
do all threads share the same c and mtx variable?
is it necessary upon pthread_cond_wait return to test if some condition is actually met? in my case every call to broadcast should wake up every thread exactly once, but no-one else should do so. (do i prevent spurious wakeups?)
the program currently does not exit despite async cancel type. also no success with deferred cancellation tried in example code despite pthread_cond_wait being a cancellation point so.
overall does it work like i expect it to.
#include <pthread.h>
#include <iostream>
#include <unistd.h>
struct p_args{
int who;
};
pthread_cond_t c; //share between compilation units
pthread_mutex_t mtx;
void *threadFunc(void *vargs){
//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
struct p_args * args = (struct p_args *) vargs;
while(true){
//wait for trigger one loop
pthread_mutex_lock(&mtx);
pthread_cond_wait(&c, &mtx);
pthread_mutex_unlock(&mtx);
//should be entangled output showing concurrent execution
std::cout << "t " << args->who << std::endl;
/* expensive work */
}
delete args;
}
int main(int argc, char* argv[])
{
pthread_cond_init(&c, NULL);
pthread_mutex_init(&mtx, NULL);
pthread_t thread_id[2];
struct p_args *args0 = new p_args();
struct p_args *args1 = new p_args();
args0->who = 0;
args1->who = 1;
pthread_create(&thread_id[0], NULL, threadFunc, args0);
pthread_create(&thread_id[1], NULL, threadFunc, args1);
sleep(3);
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&c);
pthread_mutex_unlock(&mtx);
sleep(3);//test if thread waits
pthread_cancel(thread_id[0]);
pthread_cancel(thread_id[1]);
pthread_join (thread_id[0], NULL);
pthread_join (thread_id[1], NULL);
//could perform cleanup here
return 0;
}
Regarding exiting deferred:
thread_id[0] exits fine and i am stuck in line `pthread_join (thread_id[1], NULL);`, it says (Exiting) but seems stuck on a lock, with debugger:
<br>
[![enter image description here][2]][2]
<br>
EDIT final solution i came up with:
#include <pthread.h>
#include <iostream>
#include <unistd.h>
struct p_args{
int who;
};
pthread_cond_t c;
pthread_mutex_t mtx;
bool doSome[2];
bool exitFlag;
void *threadFunc(void *vargs){
struct p_args * args = (struct p_args *) vargs;
while(true){
//wait for trigger one loop
pthread_mutex_lock(&mtx);
do {
pthread_cond_wait(&c, &mtx);
if(exitFlag) {
std::cout << "return " << args->who << std::endl;
delete args;
pthread_mutex_unlock(&mtx);
return NULL;
}
} while(doSome == false);
doSome[args->who] = false;
pthread_mutex_unlock(&mtx);
std::cout << "t " << args->who << std::endl;
}
}
int main(int argc, char* argv[])
{
pthread_cond_init(&c, NULL);
pthread_mutex_init(&mtx, NULL);
pthread_t thread_id[2];
struct p_args *args0 = new p_args();
struct p_args *args1 = new p_args();
args0->who = 0;
args1->who = 1;
doSome[0] = doSome[1] = true;
exitFlag = false;
pthread_create(&thread_id[0], NULL, threadFunc, args0);
pthread_create(&thread_id[1], NULL, threadFunc, args1);
doSome[0] = doSome[1] = true;
pthread_cond_broadcast(&c);
sleep(3);
doSome[0] = doSome[1] = true;
pthread_cond_broadcast(&c);
sleep(3);
exitFlag = true;
pthread_cond_broadcast(&c);
pthread_join (thread_id[0], NULL);
pthread_join (thread_id[1], NULL);
return 0;
}
do all threads share the same c and mtx variable?
Yes, just like any other global variable. You could print their addresses from each thread to confirm it.
is it necessary upon pthread_cond_wait return to test if some condition is actually met?
Yes, all wait interfaces are subject to spurious wakeups, and you're always responsible for checking your own predicate. See the documentation or a good book.
the program currently does not exit ...
pthread_cancel is uniformly horrible and should never be used. It's really hard to get right. If you want to tell your thread to exit, write a notification mechanism - build it into the existing predicate loop - and signal/broadcast to make sure all threads wake up and realize it's time to die.
Regarding exiting deferred: thread_id[0] exits fine and i am stuck in line pthread_join (thread_id[1], NULL);, it says (Exiting) but seems stuck on a lock
One of the hard things about pthread_cancel is cleanup. If cancellation occurs while you're holding a lock, you need to have used pthread_cleanup_push to emulate cancel-compatible RAII semantics. Otherwise the first thread may (and in this case, did) die with the mutex still locked.
In this case the second thread is trying to exit from pthread_const_wait due to cancellation, but it needs to regain the lock and can't.
The usual form of a condition variable loop is this (and a good reference book should show something similar):
void *thread(void *data)
{
struct Args *args = (struct Args *)data;
/* this lock protects both the exit and work predicates.
* It should probably be part of your argument struct,
* globals are not recommended.
* Error handling omitted for brevity,
* but you should really check the return values.
*/
pthread_mutex_lock(&args->mutex);
while (!exit_predicate(args)) {
while (!work_predicate(args)) {
/* check the return value here too */
pthread_cond_wait(&args->condition, &args->mutex);
}
/* work_predicate() is true and we have the lock */
do_work(args);
}
/* unlock (explicitly) only once.
* If you need to cope with cancellation, you do need
* pthread_cleanup_push/pop instead.
*/
pthread_mutex_unlock(&args->mutex);
return data;
}
where your custom code can just go in bool exit_predicate(struct Args*), bool work_predicate(struct Args*) and void do_work(struct Args*). The loop structure itself rarely needs much alteration.

Dead lock in the mutex, condition variable code?

I'm reading the book, Modern Operation Systems by AS TANENBAUM and it gives an example explaining condition variable as below. It looks to me there is a deadlock and not sure what I miss.
Lets assume consumer thread starts first. Right after the_mutex is locked, consumer thread is blocked waiting for the condition variable, condc.
If producer is running at this time, the_mutex will still be locked, because consumer never releases it. So producer will also be blocked.
This looks to me a textbook deadlock issue. Did I miss something here? Thx
#include <stdio.h>
#include <pthread.h>
#define MAX 10000000000 /* Numbers to produce */
pthread_mutex_t the_mutex;
pthread_cond_t condc, condp;
int buffer = 0;
void* consumer(void *ptr) {
int i;
for (i = 1; i <= MAX; i++) {
pthread_mutex_lock(&the_mutex); /* lock mutex */
/*thread is blocked waiting for condc */
while (buffer == 0) pthread_cond_wait(&condc, &the_mutex);
buffer = 0;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
void* producer(void *ptr) {
int i;
for (i = 1; i <= MAX; i++) {
pthread_mutex_lock(&the_mutex); /* Lock mutex */
while (buffer != 0) pthread_cond_wait(&condp, &the_mutex);
buffer = i;
pthread_cond_signal(&condc);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
int main(int argc, char **argv) {
pthread_t pro, con;
//Simplified main function, ignores init and destroy for simplicity
// Create the threads
pthread_create(&con, NULL, consumer, NULL);
pthread_create(&pro, NULL, producer, NULL);
}
When you wait on a condition variable, the associated mutex is released for the duration of the wait (that's why you pass the mutex to pthread_cond_wait).
When pthread_cond_wait returns, the mutex is always locked again.
Keeping this in mind, you can follow the logic of the example.

Windows Thread Synchronization with create semaphore

I am trying on a problem with writer and reader. I am trying with windows semaphore functionality.
It is very simple as follows
char n[200];
volatile HANDLE hSem=NULL; // handle to semaphore
The write function for console. Which release the semaphore for the read process.
void * write_message_function ( void *ptr )
{
/* do the work */
while(1){
printf("Enter a string");
scanf("%s",n);
ReleaseSemaphore(hSem,1,NULL); // unblock all the threads
}
pthread_exit(0); /* exit */
}
The print message wait for the release from the write message to print the message.
void * print_message_function ( void *ptr )
{
while(1){
WaitForSingleObject(hSem,INFINITE);
printf("The string entered is :");
printf("==== %s\n",n);
}
pthread_exit(0); /* exit */
}
The main function launch the application.
int main(int argc, char *argv[])
{
hSem=CreateSemaphore(NULL,0,1,NULL);
pthread_t thread1, thread2; /* thread variables */
/* create threads 1 and 2 */
pthread_create (&thread1, NULL, print_message_function, NULL);
pthread_create (&thread2, NULL, write_message_function, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
/* exit */
CloseHandle(hSem);
}
The program executes but does not show the string input console.
ReleaseSemaphore in write_message_function will force the following:
The print_message_function will start the output and
The write_message_function will output and scan for input.
These two things occur at the same time. Using the semaphore to trigger the output is
fine. However, using MaximumCount=1 is a waste of capabilities, you may have mutiple inputs before an output occurs.
But the main problem here is that the I/O resources and the use of char n[200]; are not
implemented thread-safe. See What is meant by “thread-safe” code? for details. You'd still have to protect these resources by for example a mutex or a critical section.

How can I pass variable in pthread_cond_signal function?

I am new to pthread programming. I am writing one sample code in which I want to transfer variable in pthread_cond_signal() as shown below
pthread_t th1,th2;
pthread_cond_t con1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t con2 = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* fun(void *gh)
{
pthread_mutex_lock(&mutex);
flag=1;
pthread_cond_wait(&con1,&mutex);
printf("This is test\n");
pthread_mutex_unlock(&mutex);
}
int main()
{
char *s;
int a;
s=malloc(sizeof(char)*4);
printf("Enter thread Number \n");
scanf("%d",&a);
sprintf(s,"con%d",a);
pthread_create(&th1,NULL,fun,NULL);
sleep(1);
while(flag==0) //wait until pthread_cond_wait is called
{}
pthread_mutex_lock(&mutex);
pthread_cond_signal((pthread_cond_t *)s);
pthread_mutex_unlock(&mutex);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
return 0;
}
You are using threads. All threads of a program share memory with each other. The problem isn't reading variables from other threads. The problem is reading them in the correct order: not half-updated, out of date, or from the future.
Solving that problem is the entire reason for mutexes and semaphores and conditions.
What you want to do is NOT pass a value through pthread_cond_signal. What you do is set the value into some memory both threads can read and then send the signal.
I have to wonder why you considered that pthread_cond_signal((pthread_cond_t *)s) would work? s is not, and never was, a condition. A pthread_cond_t is not a value that you pass around. It is the structure that the POSIX Thread library uses to track condition states.

The calling sequence of pthread_init pthread_lock, pthread_destroy and so on?

Normally, the correct sequence is something like this:
pthread_mutex_init(&mutex,NULL);
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
mutex should be initialized first, and then pthread_mutex_lock and pthread_mutex_unlock can be called in respective thread to protect the critical section, finally pthread_mutex_destroy is called to destroy the mutex after the completion of all threads. But if the order is mixed, What would happend?
I disrupt the sequence of the functions in order to find out the error, but everything seems normal when the sequence is messed in different way. Here is an example.
pthread_mutex_t mutex;
static int count = 0;
void* func(void* arg)
{
pthread_mutex_lock(&mutex);
*(int*)arg = *(int*)(arg) + 1;
printf("thread %d\n", *(int*)arg);
pthread_mutex_unlock(&mutex);
}
int main(int argc, char* argv[])
{
int i;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_destroy(&mutex);
for(i = 0; i < 3; i++)
{
pthread_t tid;
pthread_create(&tid, NULL, func, (void*)(&count));
sleep(5);
}
printf("the main thread exit normally.\n");
}
I want to ask whether the sequence matters to the program. Is there something inside the function to assure the calling sequence, or something else? If these functions can be used without order, why should pthread_mutex_init() and pthread_mutex_destroy() be defined?
What happens is undefined behavior. The implementation may, or may not, print an error, abort the program, or start WW III. Or it may appear to work just fine, but there are no guarantees.

Resources