Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pthread_join()

6 views
Skip to first unread message

Senthilkumar Cheetancheri

unread,
Jan 22, 2002, 5:49:57 PM1/22/02
to
Hi,
I create several threads in the main() function.

Each thread executes the function T1().

The thread running main() function should wait and receive the
value that each thread returns after executing the function T1().

I used pthread_exit() in T1() and pthread_join() in main(), but
I'm getting nowhere. The program goes into a hang.

Desperate. Thanks in advance.

:(
C.G.Senthilkumar.

David Schwartz

unread,
Jan 22, 2002, 6:19:51 PM1/22/02
to

Post your code.

DS

Senthilkumar Cheetancheri

unread,
Jan 22, 2002, 6:30:23 PM1/22/02
to

Please find the code below. Might look somewhat long-winded due the
numerous mutex and cond_vars. Please run it and you can see the o/p
until some point and then it hangs.

#include <pthread.h>
#include <semaphore.h>

void *pi(void *);

pthread_mutex_t t_done_mutex[10];
int ini = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t t_done_cond = PTHREAD_COND_INITIALIZER;
int exiting_thread = 0;

main()
{
unsigned int value = 0;

int **ret_val;

pthread_t t[10];

int i, j, r = 0;

i = 100;

for(j = 0; j < 10; j++)
{
pthread_mutex_init(&t_done_mutex[j], (pthread_mutexattr_t *)&ini);
pthread_mutex_lock(&t_done_mutex[j]);
pthread_create(&t[j], NULL, (void*)&pi, (void*)&j);
}

for(j = 0; j < 10; j++)
{
pthread_cond_wait(&t_done_cond, &t_done_mutex[j]);
printf("waiting for pthread_join %d\n", (int)exiting_thread);
pthread_join(exiting_thread, (void **)ret_val);
printf("Received %d from thread %d\n", **ret_val, exiting_thread);
exiting_thread = 0;
pthread_mutex_unlock(&t_done_mutex[j]);
}

exit(0);
}

void *
pi(void *got_value)
{
int ret_val;
printf("I'm thread %d and I got: %d\n", (int)pthread_self(), *(int *)got_value);
/* ++ has higher precedence than *. */
ret_val = (*(int *)got_value) + 1;
pthread_mutex_lock(&t_done_mutex[*(int *)got_value]);
exiting_thread = pthread_self();
pthread_cond_signal(&t_done_cond);
pthread_mutex_unlock(&t_done_mutex[*(int *)got_value]);
pthread_exit((void *)&ret_val);
/*
return ((void *)&ret_val);
*/
}

Thanks in advance.

C.G.Senthilkumar.

David Schwartz

unread,
Jan 22, 2002, 6:45:40 PM1/22/02
to
Senthilkumar Cheetancheri wrote:

> Please find the code below. Might look somewhat long-winded due the
> numerous mutex and cond_vars. Please run it and you can see the o/p
> until some point and then it hangs.

Two threads can't hold the same mutex at the same time. The main thread
grabs the mutex and doesn't release it.



> #include <pthread.h>
> #include <semaphore.h>
>
> void *pi(void *);
>
> pthread_mutex_t t_done_mutex[10];
> int ini = PTHREAD_MUTEX_INITIALIZER;
> pthread_cond_t t_done_cond = PTHREAD_COND_INITIALIZER;
> int exiting_thread = 0;
>
> main()
> {
> unsigned int value = 0;
>
> int **ret_val;
>
> pthread_t t[10];
>
> int i, j, r = 0;
>
> i = 100;
>
> for(j = 0; j < 10; j++)
> {
> pthread_mutex_init(&t_done_mutex[j], (pthread_mutexattr_t *)&ini);
> pthread_mutex_lock(&t_done_mutex[j]);

Why are you locking the mutex? What does the mutex protect?

> pthread_create(&t[j], NULL, (void*)&pi, (void*)&j);
> }
>
> for(j = 0; j < 10; j++)
> {
> pthread_cond_wait(&t_done_cond, &t_done_mutex[j]);
> printf("waiting for pthread_join %d\n", (int)exiting_thread);
> pthread_join(exiting_thread, (void **)ret_val);
> printf("Received %d from thread %d\n", **ret_val, exiting_thread);
> exiting_thread = 0;
> pthread_mutex_unlock(&t_done_mutex[j]);
> }
>
> exit(0);
> }
>
> void *
> pi(void *got_value)
> {
> int ret_val;
> printf("I'm thread %d and I got: %d\n", (int)pthread_self(), *(int *)got_value);
> /* ++ has higher precedence than *. */
> ret_val = (*(int *)got_value) + 1;
> pthread_mutex_lock(&t_done_mutex[*(int *)got_value]);
> exiting_thread = pthread_self();
> pthread_cond_signal(&t_done_cond);
> pthread_mutex_unlock(&t_done_mutex[*(int *)got_value]);
> pthread_exit((void *)&ret_val);
> /*
> return ((void *)&ret_val);
> */
> }
>
> Thanks in advance.

You have created a deadlock situation wherein two threads are waiting
for each other. *NEVER* wait for another thread while holding a mutex.

DS

Senthilkumar Cheetancheri

unread,
Jan 22, 2002, 7:03:49 PM1/22/02
to
> Two threads can't hold the same mutex at the same time. The main thread
> grabs the mutex and doesn't release it.
>
>> #include <pthread.h>
>> #include <semaphore.h>
>>
>> void *pi(void *);
>>
>> pthread_mutex_t t_done_mutex[10];
>> int ini = PTHREAD_MUTEX_INITIALIZER;
>> pthread_cond_t t_done_cond = PTHREAD_COND_INITIALIZER;
>> int exiting_thread = 0;
>>
>> main()
>> {
>> unsigned int value = 0;
>> int **ret_val;
>> pthread_t t[10];
>> int i, j, r = 0;
>> i = 100;
>> for(j = 0; j < 10; j++)
>> {
>> pthread_mutex_init(&t_done_mutex[j], ...
>> pthread_mutex_lock(&t_done_mutex[j]);

> Why are you locking the mutex? What does the mutex protect?

I'm locking all the 'mutices' until I'm done with creating all the
threads. And I'm releasing them using the pthread_cond_wait() below.
If I don't do this, the threads fiinish their jobs and exit even before
I could finish creating all the threads. Thus I'm not able to receive
the return values of the threads. I was told that I'm trying to implement
the 'Farmer's model', if it could help you.

>> pthread_create(&t[j], NULL, (void*)&pi, (void*)&j);
>> }
>>
>> for(j = 0; j < 10; j++)
>> {
>> pthread_cond_wait(&t_done_cond, &t_done_mutex[j]);

I'm releasing the lock here.

>> printf("waiting for pthread_join %d\n", (int)exiting_thread);
>> pthread_join(exiting_thread, (void **)ret_val);

>> printf("Received %d from thread %d\n"...


>> exiting_thread = 0;
>> pthread_mutex_unlock(&t_done_mutex[j]);
>> }
>>
>> exit(0);
>> }
>>
>> void *
>> pi(void *got_value)
>> {
>> int ret_val;

>> printf("I'm thread %d and I got: %d\n", (int)pt...


>> /* ++ has higher precedence than *. */
>> ret_val = (*(int *)got_value) + 1;
>> pthread_mutex_lock(&t_done_mutex[*(int *)got_value]);
>> exiting_thread = pthread_self();
>> pthread_cond_signal(&t_done_cond);
>> pthread_mutex_unlock(&t_done_mutex[*(int *)got_value]);
>> pthread_exit((void *)&ret_val);
>> /*
>> return ((void *)&ret_val);
>> */
>> }
>>
>> Thanks in advance.

> You have created a deadlock situation wherein two threads are waiting
> for each other. *NEVER* wait for another thread while holding a mutex.

> DS

Thanks for your quick reply. And thanks in advance.

C.G.Senthilkumar.

crux

unread,
Jan 23, 2002, 7:59:29 AM1/23/02
to

You don't need cond, in POSIX when a thread call exit the returned value
is not deallocaded until another thread performe a join.

You should read documentation on how much this is true for your machine
(how much is POSIX)

However I don't know why your program hangs

Alexander Terekhov

unread,
Jan 23, 2002, 10:29:43 AM1/23/02
to
Senthilkumar Cheetancheri <chee...@pc6.cs.ucdavis.edu> wrote in message news:<a2ksmf$ntb$3...@woodrow.ucdavis.edu>...

> Please find the code below. Might look somewhat long-winded due the
> numerous mutex and cond_vars.

[... 8-0 ...]

Does the following example help?

#include <pthread.h>

void * pi(void *got_value)
{
++(*(int*)got_value);
return got_value;
}

int main()
{
int j;
int value = 0;

void* presult;

pthread_t t[10];
int values[10]; // <- an invitation for word-tearing/false-sharing ;)


for(j = 0; j < 10; ++j)
{
values[j] = j;
pthread_create(&t[j], NULL, &pi, &values[j]);
}

for(j = 0; j < 10; ++j)
{
pthread_join(t[j], &presult);
value += *(int*)presult;
}

return value;
}

BTW, would not it be nice to have a standard C++
threading library which would allow us to write
something along the lines of: (I am just dreaming ;)

#include <thread>

int f1( int value )
{ return value+1; }

int f2( int value )
{ /**/if (0 == value) thread::current()->exit( 100 ); /**/return value+1; }

void thread::main(int argc, char* argv[])
{
joinable_thread_ptr< int > tptr1 = new_thread( f1,1 );
joinable_thread_ptr< thread_traits< f2 >::result > tptr2 = new_thread( f2,2 );

exit( *tptr1->join() + *tptr2->join() );
}

regards,
alexander.

David Schwartz

unread,
Jan 23, 2002, 4:06:45 PM1/23/02
to
Senthilkumar Cheetancheri wrote:

> I'm locking all the 'mutices' until I'm done with creating all the
> threads. And I'm releasing them using the pthread_cond_wait() below.
> If I don't do this, the threads fiinish their jobs and exit even before
> I could finish creating all the threads. Thus I'm not able to receive
> the return values of the threads. I was told that I'm trying to implement
> the 'Farmer's model', if it could help you.

Okay, you can do that if you want, BUT YOU HAVE TO DO IT RIGHT.

for(j = 0; j < 10; j++)
{
pthread_cond_wait(&t_done_cond, &t_done_mutex[j]);

printf("waiting for pthread_join %d\n",
(int)exiting_thread);
pthread_join(exiting_thread, (void **)ret_val);

printf("Received %d from thread %d\n", **ret_val,
exiting_thread);


exiting_thread = 0;
pthread_mutex_unlock(&t_done_mutex[j]);
}

In the call to 'pthread_cond_wait', what are you waiting for? There's
no predicate. You must use a condition variable in association with a
predicate because the condition variable itself is stateless. There must
be something specific you are waiting for, and the code must call
pthread_cond_wait only so long as the thing it's waiting for has not
happened.

DS

Senthilkumar Cheetancheri

unread,
Jan 23, 2002, 3:59:14 PM1/23/02
to
Hi,
I tried your program. I works fine. I'm delighted.

I have a few questions.

1. I tried printing out the address of the presult. I found that it is assigned
a new address for each join. How does that happen? Who assigns it?

2. I found that all the threads finish in the same order in which they were
created. I guess it is just incidental and if there was a lot of work to do
for the threads, they would exit in different order than in which they were
created. Would I get back the proper values in that case too from pjoin()?

3. And I didn't get the real meaning of the term 'word-tearing/false-sharing'.
How is it going to affect my program?

Please reply.
Thanks in advance.

Regards,
C.G.Senthilkumar.

Alexander Terekhov

unread,
Jan 24, 2002, 3:04:08 AM1/24/02
to
Senthilkumar Cheetancheri <chee...@pc6.cs.ucdavis.edu> wrote in message news:<a2n872$nam$1...@woodrow.ucdavis.edu>...

> Hi,
> I tried your program. I works fine. I'm delighted.
>
> I have a few questions.
>
> 1. I tried printing out the address of the presult. I found that it is assigned
> a new address for each join. How does that happen? Who assigns it?

pi's "return got_value;" statement.

> 2. I found that all the threads finish in the same order in which they were
> created. I guess it is just incidental and if there was a lot of work to do
> for the threads, they would exit in different order than in which they were
> created. Would I get back the proper values in that case too from pjoin()?

Yep.

> 3. And I didn't get the real meaning of the term 'word-tearing/false-sharing'.
> How is it going to affect my program?

Well, see the first URL below and... STFW! sorry.

> Please reply.
> Thanks in advance.

You know, here is my free advice for you:

1. Buy and read*** http://www.awl.com/cseng/titles/0-201-63392-2/
2. Register and download POSIX/PTHREADS standard at:
http://www.opengroup.org/austin/
3. Bear in mind this URL: http://sources.redhat.com/pthreads-win32
4. Subscribe to comp.programming.threads
5. Distribute these instructions among your friends,
so they could also do 1,2,3,4,5 and our living
on planet Earth will become better! ;-)

regards,
alexander.

[***] If/when you meet Butenhof, just ask him
whether it is true that the 2nd edition is nearly
done and will go GA this year rather soon! ;-)
Okay, I am just kidding. Sorry.

David Butenhof

unread,
Jan 24, 2002, 7:33:25 AM1/24/02
to
Alexander Terekhov wrote:

Why, thank you. ;-)

> 2. Register and download POSIX/PTHREADS standard at:
> http://www.opengroup.org/austin/

Technically, what you'd have downloaded isn't "POSIX/PTHREADS standard",
it's the Single UNIX Specification, either V2 or V3. If you've gotten the
new V3, then you're dealing with a document SOURCE that's identical to the
source for the POSIX 1003.1-2001 STANDARD but, technically, it still ISN'T
"the standard".

OK, OK, this shouldn't make much difference to most people, but we might as
well keep our terminology straight. Communication may be much more FUN when
everyone invents their own terms, but the information can sometimes get
lost in the mess...

> 3. Bear in mind this URL: http://sources.redhat.com/pthreads-win32

Sure, if you MUST use Windows, this and a lot of aspirin may help. ;-)

> 4. Subscribe to comp.programming.threads

Definitely. Absolutely the best place to be if you're a thread.

> 5. Distribute these instructions among your friends,
> so they could also do 1,2,3,4,5 and our living
> on planet Earth will become better! ;-)

Hmm. OK, "no comment". ;-)

> [***] If/when you meet Butenhof, just ask him
> whether it is true that the 2nd edition is nearly
> done and will go GA this year rather soon! ;-)
> Okay, I am just kidding. Sorry.

Ha ha. If you don't stop bothering me about this, I'm going to have to go
off and write the bloody thing just to keep you quiet. ;-)

(Yeah, if only it were that easy. I STILL have not received any free time
in my INBOX, by the way... perhaps nobody's downloaded the FreeTime(tm)
media plugin? [NOTE: I hope I made that up. If there is such a thing, I
have no doubt radically misrepresented its intent and purpose, and I
suppose I ought to apologize to someone. Nah...]

/------------------[ David.B...@compaq.com ]------------------\
| Compaq Computer Corporation POSIX Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\-----[ http://home.earthlink.net/~anneart/family/dave.html ]-----/

Senthilkumar Cheetancheri

unread,
Jan 25, 2002, 1:33:49 AM1/25/02
to
Alexander Terekhov <tere...@web.de> wrote:

> void * pi(void *got_value)
> {
> ++(*(int*)got_value);
> return got_value;
> }

One more newbie question please.

If I call some other function f1() here in the pi(), will there
be separate copies of fi() created or will it be just one and all
the threads keep stomping on each others data?

Thanks in advance.

C.G.Senthilkumar.

David Butenhof

unread,
Jan 25, 2002, 7:34:02 AM1/25/02
to
Senthilkumar Cheetancheri wrote:

That's an ambiguous question, and the fact that you wrote "f1" one time and
"fi" the other doesn't help. I'll presume you meant to write "f1" both
times...

Your program text generally contains one copy of the "f1" function.
(Although, if the compiler inlines, that may not be quite true; in any
case, the duplication has nothing to do with threads, but with the various
static call sites.)

However, if f1() contains any local (auto or register) declarations, then
each invocation of the routine will have its own private copy of those
variables. This isn't really related to threads, either -- it's what makes
it possible to write recursive functions in C. It does, however, mean that
functions using only auto/register local variables can run simultaneously
in multiple threads without interference. (This also presupposes, by the
way, that those local variables aren't used to POINT to shared data!)

If f1() declares a 'static' variable, or references an extern or file-level
static variable, then those variables will be shared by all threads, and in
particular by all "instances" of f1() running in any thread. They'll
certainly "stomp on each other" unless you apply some formal
synchronization protocol to serialize their access.

Alexander Terekhov

unread,
Jan 25, 2002, 11:49:39 AM1/25/02
to

Senthilkumar Cheetancheri wrote:
>
> Alexander Terekhov <tere...@web.de> wrote:
>
> > void * pi(void *got_value)
> > {
> > ++(*(int*)got_value);
> > return got_value;
> > }
> One more newbie question please.
>
> If I call some other function f1() here in the pi(), will there
> be separate copies of fi() created

What do you mean?

> or will it be just one and all
> the threads keep stomping on each others data?

I guess that it depends on the level of skill
of fi()'s author(s) and/or fi()'s user(s). ;-)

regards,
alexander.

Alexander Terekhov

unread,
Jan 25, 2002, 12:28:09 PM1/25/02
to

David Butenhof wrote:
[...]

> > [***] If/when you meet Butenhof, just ask him
> > whether it is true that the 2nd edition is nearly
> > done and will go GA this year rather soon! ;-)
> > Okay, I am just kidding. Sorry.
>
> Ha ha. If you don't stop bothering me about this, I'm going to have to go
> off and write the bloody thing just to keep you quiet. ;-)

That won't help you much either. I have long-term plans...
Great programming books usually have *3* editions followed
by The Special Edition! ;-)

regards,
alexander.

Senthilkumar Cheetancheri

unread,
Jan 25, 2002, 12:42:40 PM1/25/02
to
> If I call some other function f1() here in the pi(), will there
> be separate copies of fi() created or will it be just one and all

I'm SORRY, I meant to say f1() and fi() was a typo. I'm SORRY.

C.G.Senthilkumar.

David Schwartz

unread,
Jan 25, 2002, 2:19:05 PM1/25/02
to
Senthilkumar Cheetancheri wrote:

> If I call some other function f1() here in the pi(), will there
> be separate copies of fi() created or will it be just one and all
> the threads keep stomping on each others data?

You seem to be confusing copies of a functino and copies of the data it
works on.

DS

Senthilkumar Cheetancheri

unread,
Jan 25, 2002, 9:46:49 PM1/25/02
to
David Schwartz <dav...@webmaster.com> wrote:
> You seem to be confusing copies of a functino and copies of the data it
> works on.
Yes, my message was somewhat confused. But that was a reflection of my
thoughts. Now I'm clear. Thank you.

C.G.Senthilkumar.

David Schwartz

unread,
Jan 25, 2002, 9:49:58 PM1/25/02
to

See that? Once you found the right question, you already knew the
answer. ;)

DS

Senthilkumar Cheetancheri

unread,
Jan 25, 2002, 1:05:38 PM1/25/02
to
David Butenhof <David.B...@compaq.com> wrote:
> That's an ambiguous question, and the fact that you wrote "f1" one time and
> "fi" the other doesn't help. I'll presume you meant to write "f1" both
> times...
I'm sorry, I'meant to say f1() both times. fi() was a typo.

C.G.Senthilkumar.

0 new messages