Get thread identifier C

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; 
} 

Solution 1:

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.

Solution 2:

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.

Solution 3:

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()