hel hel - 5 months ago 13
Linux Question

Why doesn't the newly created thread obtain its tid through pthread_create() return argument but pthread_self()

This is the sample code for thread creation from “Advanced Programming in the Unix Environment”. As for thread creation,

err = pthread_create(&ntid, NULL, thr_fn, NULL);
can the newly created thread just use ntid to print its own threadID, rather than calling pthread_self()?

#include "apue.h"
#include <pthread.h>

pthread_t ntid;

void
printids(const char *s)
{
pid_t pid;
pthread_t tid;

pid = getpid();
tid = pthread_self();
printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid,
(unsigned int)tid, (unsigned int)tid);
}

void *
thr_fn(void *arg)
{
printids("new thread: "); /* for the newly created thread,can it
* print its own threadID just using ntid,
* instead of calling pthread_self()
*/
return((void *)0);
}

int
main(void)
{
int err;

err = pthread_create(&ntid, NULL, thr_fn, NULL);
if (err != 0)
err_quit("can't create thread: %s\n", strerror(err));
printids("main thread:");
sleep(1);
exit(0);
}

Answer

Let's check spec:

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_create.html

pthread_create(pthread_t *restrict thread,

Upon successful completion, pthread_create() shall store the ID of the created thread in the location referenced by thread.

The calling thread can obtain the ID of the created thread through the return value of the pthread_create() function, and the newly created thread can obtain its ID by a call to pthread_self().

The problem is: ntid is variable of calling function; even if it is global, the reading of this global variable from thread doesn't scale to two created threads or more.

Other problem is timing and order of execution. pthread_create writes thread id to ntid after new thread is created:

Upon successful completion, pthread_create() shall store the ID of the created thread in the location referenced by thread.

So, it is unsafe to read ntid from created thread without synchronization, new thread may do read before actual value will be written to global.

So, you should use pthread_self: http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_self.html

The pthread_self() function shall return the thread ID of the calling thread.

The pthread_self() function provides a capability similar to the getpid() function for processes and the rationale is the same: the creation call does not provide the thread ID to the created thread.