Is there a way to link a linux's thread TID and a pthread_t "thread ID"

2.6k Views Asked by At

On linux a thread is identified by a pthread_t or a TID. I'm looking for bridges between these two kinds of thread ids:

  • given a pthread_t can I get it's TID ? apparently not without hacking in pthread's internals :( but i'm still asking in case someone has a clean way to do it.
  • given a TID (or PID), can I get a pthread_t handle to it ?

Because the term "thread id" is ambiguous in this context (and in the documentation), a bit of background:

  • The POSIX pthread API defines a pthread_t type, all functions that query/act on a thread use a pthread_t argument, and we can get such a handle e.g. with pthread_self(). The documentation calls these "thread ids", but here I call them handles to disambiguate, because multiple different pthread_t values may represent the same thread, hence the need for pthread_equal(pthread_t, pthread_t).

  • On the other hand, on linux at least, there is a concept of TIDs or thread ids. One can get the current TID with a system call: syscall(SYS_gettid). The TID has a few interesting properties such as being unique to a thread, and comparable to PIDs, which allows to easily identify the main thread, etc.

1

There are 1 best solutions below

2
On

Unfortunately, there is no portable way to do so because there is no requirement for pthread_t to map to tid:

Implementations may choose to define a thread ID as a structure. This allows additional flexibility and robustness over using an int. For example, a thread ID could include a sequence number that allows detection of "dangling IDs" (copies of a thread ID that has been detached). Since the C language does not support comparison on structure types, the pthread_equal() function is provided to compare thread IDs.

Historically, prior to NPTL, pthread_t did not map 1-to-1 to tid.

You would need to use pthreads library implementation details to peek at tid. I would not recommend doing that because such code would not be portable.

For the sake of curiosity only, with glibc, pthread_t is a struct pthread *:

27 int
28 __pthread_kill (pthread_t threadid, int signo)
29 {
30   struct pthread *pd = (struct pthread *) threadid;
...
40   pid_t tid = atomic_forced_read (pd->tid);

And pthread is:

122 /* Thread descriptor data structure.  */
123 struct pthread
124 {
...
166   /* Thread ID - which is also a 'is this thread descriptor (and
167      therefore stack) used' flag.  */
168   pid_t tid;