How to get thread id of a pthread in linux c program?
Asked Answered
V

12

131

In a Linux C program, how do I print the thread id of a thread created by the pthread library? For example like how we can get pid of a process by getpid().

Varix answered 13/1, 2014 at 12:12 Comment(1)
A
113

pthread_self() function will give the thread id of current thread.

pthread_t pthread_self(void);

The pthread_self() function returns the Pthread handle of the calling thread. The pthread_self() function does NOT return the integral thread of the calling thread. You must use pthread_getthreadid_np() to return an integral identifier for the thread.

NOTE:

pthread_id_np_t   tid;
tid = pthread_getthreadid_np();

is significantly faster than these calls, but provides the same behavior.

pthread_id_np_t   tid;
pthread_t         self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
Alejoa answered 18/1, 2014 at 15:54 Comment(6)
The original question was about Linux. Linux does not include the _np functions. (It doesn't include their man pages, I didn't check any further than that.)Zaccaria
pthread_threadid_np is available on OS X >= 10.6 and iOS >= 3.2.Ravish
@Bleater Can you please provide the official documentation for pthread_threadid_np. Am in need to use for a project, so need to check on the reliability of that API in iOS and OSX platforms. Referred the link at opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h but not sure if they are the right one.Shinny
@Vivek I don't have any link to official docs, just the header you link and the source at opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.cRavish
@Trade-IdeasPhilip - To clarify, _np means non-portable. Linux has its own _np stuff, but it doesn't include Apple's pthread_getthreadid_np.Viewer
Some important note: A pthread_t is a kind of pointer in Linux. So if you run the same program multiple times, you may see the same pthread_t, while the actual threads are different. Thus printing the pthread_t does not help very much.Polliwog
C
134

What? The person asked for Linux specific, and the equivalent of getpid(). Not BSD or Apple. The answer is gettid() and returns an integral type. You will have to call it using syscall(), like this:

#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>

 ....

 pid_t x = syscall(__NR_gettid);

While this may not be portable to non-linux systems, the threadid is directly comparable and very fast to acquire. It can be printed (such as for LOGs) like a normal integer.

Caerleon answered 25/8, 2015 at 18:19 Comment(11)
This should be true answerDecemvir
The person asked about something that worked on Linux. Doing so in a portable way seems to me like the preferable way to do it. If portability doesn't count for anything then I guess Linux is really becoming the new Windows...Credible
@Jasper Siepkes You are missing the point. He asked for a LINUX call that was the equivalent of getpid() for threads. That is gettid(). The question didn't ask about portability or POSIX. Too many people want to show off and try and teach rather than asking the question as asked. pthread_self() does not return the kernel thread id and it not manipulatable in a way that makes for easy printing. Also, pthread_self is likely a pointer and should not be manipulated, only compared with pthread_equal(). The question asked for an ID you can print, and that's gettid().Caerleon
@EvanLanglois He's working with the pthread library, literally the POSIX thread library. Making a POSIX compatible answer not that weird. "He asked for a LINUX call that was the equivalent of getpid() for threads." No, getpid() was given as an example. It didn't say the semantics were a hard specification. Making people aware of doing things in a POSIX compatible way so other communities besides Linux (like FreeBSD, Illumos, OS X, etc.) can benefit from them is not "showing off". Like I said I guess Linux has really become the next Windows.Credible
Can you explain and add to your answer how and when one must use syscall(), and what the __NR_ part comes from and means, and where we can see a list of possible values to pass into syscall()?Slotter
Also, I see a different answer with syscall(SYS_gettid). How is that the same or different from syscall(__NR_gettid)?Slotter
See also: Difference between __NR_gettid and SYS_gettid and getting error in c program "undefined reference to gettid".Slotter
Those are constants defined in header files, defined by the linux kernel. As to NR vs SYS, I would have to Google that. Maybe it has to do with process groups? I dont knowCaerleon
On Linux Ubuntu 18.04 with gcc --version gcc (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0 I had to also add #define _GNU_SOURCE above all of the includes in order for syscall() to be defined. I learned that from the example at the bottom of this documentation here: man7.org/linux/man-pages/man2/syscall.2.html.Slotter
The value returned by gettid() is not the same as the value returned by pthread_self(), If you want a thread id that pthread functions can use, you want to call pthread_self().Levin
@RobinDavies Is this an April Fool's joke? The question asks for a printable id like you would get with getpid(). Good luck printing or comparing pthread_self()'s return value.Caerleon
A
113

pthread_self() function will give the thread id of current thread.

pthread_t pthread_self(void);

The pthread_self() function returns the Pthread handle of the calling thread. The pthread_self() function does NOT return the integral thread of the calling thread. You must use pthread_getthreadid_np() to return an integral identifier for the thread.

NOTE:

pthread_id_np_t   tid;
tid = pthread_getthreadid_np();

is significantly faster than these calls, but provides the same behavior.

pthread_id_np_t   tid;
pthread_t         self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
Alejoa answered 18/1, 2014 at 15:54 Comment(6)
The original question was about Linux. Linux does not include the _np functions. (It doesn't include their man pages, I didn't check any further than that.)Zaccaria
pthread_threadid_np is available on OS X >= 10.6 and iOS >= 3.2.Ravish
@Bleater Can you please provide the official documentation for pthread_threadid_np. Am in need to use for a project, so need to check on the reliability of that API in iOS and OSX platforms. Referred the link at opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h but not sure if they are the right one.Shinny
@Vivek I don't have any link to official docs, just the header you link and the source at opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.cRavish
@Trade-IdeasPhilip - To clarify, _np means non-portable. Linux has its own _np stuff, but it doesn't include Apple's pthread_getthreadid_np.Viewer
Some important note: A pthread_t is a kind of pointer in Linux. So if you run the same program multiple times, you may see the same pthread_t, while the actual threads are different. Thus printing the pthread_t does not help very much.Polliwog
R
28

As noted in other answers, pthreads does not define a platform-independent way to retrieve an integral thread ID.

On Linux systems, you can get thread ID thus:

#include <sys/types.h>
pid_t tid = gettid();

On many BSD-based platforms, this answer https://mcmap.net/q/172890/-how-to-get-thread-id-of-a-pthread-in-linux-c-program gives a non-portable way.

However, if the reason you think you need a thread ID is to know whether you're running on the same or different thread to another thread you control, you might find some utility in this approach

static pthread_t threadA;

// On thread A...
threadA = pthread_self();

// On thread B...
pthread_t threadB = pthread_self();
if (pthread_equal(threadA, threadB)) printf("Thread B is same as thread A.\n");
else printf("Thread B is NOT same as thread A.\n");

If you just need to know if you're on the main thread, there are additional ways, documented in answers to this question how can I tell if pthread_self is the main (first) thread in the process?.

Ravish answered 1/12, 2014 at 21:58 Comment(0)
H
18
pid_t tid = syscall(SYS_gettid);

Linux provides such system call to allow you get id of a thread.

Hormonal answered 9/4, 2017 at 20:22 Comment(1)
As per this answer, you need #include <unistd.h> and #include <sys/syscall.h> for this.Lalita
R
10

You can use pthread_self()

The parent gets to know the thread id after the pthread_create() is executed sucessfully, but while executing the thread if we want to access the thread id we have to use the function pthread_self().

Regretful answered 13/1, 2014 at 12:15 Comment(0)
O
9

This single line gives you pid , each threadid and spid.

 printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",getpid(), pthread_self(), syscall(SYS_gettid));
Observant answered 18/9, 2015 at 10:8 Comment(0)
I
7

I think not only is the question not clear but most people also are not cognizant of the difference. Examine the following saying,

POSIX thread IDs are not the same as the thread IDs returned by the Linux specific gettid() system call. POSIX thread IDs are assigned and maintained by the threading implementation. The thread ID returned by gettid() is a number (similar to a process ID) that is assigned by the kernel. Although each POSIX thread has a unique kernel thread ID in the Linux NPTL threading implementation, an application generally doesn’t need to know about the kernel IDs (and won’t be portable if it depends on knowing them).

Excerpted from: The Linux Programming Interface: A Linux and UNIX System Programming Handbook, Michael Kerrisk

IMHO, there is only one portable way that pass a structure in which define a variable holding numbers in an ascending manner e.g. 1,2,3... to per thread. By doing this, threads' id can be kept track. Nonetheless, int pthread_equal(tid1, tid2) function should be used.

if (pthread_equal(tid1, tid2)) printf("Thread 2 is same as thread 1.\n");
else printf("Thread 2 is NOT same as thread 1.\n");
Inborn answered 26/1, 2019 at 9:20 Comment(1)
The gettid() is actually a good suggestion, thank you! However, I needed to follow the answer by Sergey L. here: https://mcmap.net/q/175081/-getting-error-in-c-program-quot-undefined-reference-to-gettid-quotCutworm
K
3

pthread_getthreadid_np wasn't on my Mac os x. pthread_t is an opaque type. Don't beat your head over it. Just assign it to void* and call it good. If you need to printf use %p.

Koval answered 28/2, 2016 at 15:13 Comment(1)
Yes, this works. All I need is to print it for debugging so 0x23423423423abcdef is as helpful as tid=1234. Thank you!Folder
H
3

For different OS there is different answer. I find a helper here.

You can try this:

#include <unistd.h>
#include <sys/syscall.h>

int get_thread_id() {
#if defined(__linux__)
    return syscall(SYS_gettid);
#elif defined(__FreeBSD__)
    long tid;
    thr_self(&tid);
    return (int)tid;
#elif defined(__NetBSD__)
    return _lwp_self();
#elif defined(__OpenBSD__)
    return getthrid();
#else
    return getpid();
#endif
}
Hartung answered 5/5, 2022 at 14:15 Comment(0)
C
1

There is also another way of getting thread id. While creating threads with

int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg);

function call; the first parameter pthread_t * thread is actually a thread id (that is an unsigned long int defined in bits/pthreadtypes.h). Also, the last argument void *arg is the argument that is passed to void * (*start_routine) function to be threaded.

You can create a structure to pass multiple arguments and send a pointer to a structure.

typedef struct thread_info {
    pthread_t thread;
    //...
} thread_info;
//...
tinfo = malloc(sizeof(thread_info) * NUMBER_OF_THREADS);
//...
pthread_create (&tinfo[i].thread, NULL, handler, (void*)&tinfo[i]);
//...
void *handler(void *targs) {
    thread_info *tinfo = targs;
    // here you get the thread id with tinfo->thread
}
Calcareous answered 15/2, 2018 at 7:20 Comment(0)
E
-3

Platform-independent way (starting from c++11) is:

#include <thread>

std::this_thread::get_id();
Everest answered 9/9, 2018 at 12:41 Comment(2)
this probably isnt as "platform independent" as you think. on my implementation it resolves to a pthread_t. On a mac that will be a pointer and on Linux an integer. It also doesn't reflect the "native" id you might see in top for example. Something to be aware of, but maybe its fine for some uses.Rosaline
In C11 (the question was about C) you would use thrd_current() from threads.hSikko
E
-6

You can also write in this manner and it does the same. For eg:

for(int i=0;i < total; i++)
{
    pthread_join(pth[i],NULL);
    cout << "SUM of thread id " << pth[i] << " is " << args[i].sum << endl;
}

This program sets up an array of pthread_t and calculate sum on each. So it is printing the sum of each thread with thread id.

Everybody answered 12/5, 2020 at 6:13 Comment(1)
It does not answer the question, and even the description for the code is wrong!Polliwog

© 2022 - 2024 — McMap. All rights reserved.