16

I was playing with std::thread and I was wondering how is it possible to get the thread id of a new std::thread(), I am not talking about std::thread::id but rather the OS Id given to the thread ( you can view it using pstree). This is only for my knowledge, and it's targeted only to Linux platforms (no need to be portable).

I can get the Linux Thread Id within the thread like this :

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

void SayHello()
{
    std::cout << "Hello ! my id is " << (long int)syscall(SYS_gettid) << std::endl;
}

int main (int argc, char *argv[])
{
    std::thread t1(&SayHello);
    t1.join();
    return 0;
}

But how can I retrieve the same id within the main loop ? I did not find a way using std::thread::native_handle. I believed it was possible to get it trough pid_t gettid(void); since the c++11 implementation relies on pthreads, but i must be wrong.

Any advices ? Thank you.

Char Aznable
  • 165
  • 1
  • 1
  • 5
  • 3
    What is wrong with `std::thread::native_handle()`? – Andy Prowl Mar 29 '13 at 18:16
  • 1
    @AndyProwl - `native_handle()` and `native_handle_type` are not required to exist, and if they do exist, what you can do with the resulting object is implementation-defined. There are **no** portable semantics. Maybe a particular implementation supports doing this, but that's a matter between the user and the library documentation. – Pete Becker Mar 29 '13 at 18:23
  • 1
    @AndyProwl it returns me the same value as `std::thread::id`. – Char Aznable Mar 29 '13 at 18:26
  • 2
    @PeteBecker: I understand that, but I was assuming the OP is OK with doing something non-portable (as he is specifically targeting one platform), and I expected the implementation to provide such a basic information. I understand it is not required to provide it, but I would find it weird if it didn't. – Andy Prowl Mar 29 '13 at 18:27

3 Answers3

15

Assuming you're using GCC standard library, std::thread::native_handle() returns the pthread_t thread ID returned by pthread_self(), not the OS thread ID returned by gettid(). std::thread::id() is a wrapper around that same pthread_t, and GCC's std::thread doesn't provide any way to get the OS thread ID, but you could create your own mapping:

std::mutex m;
std::map<std::thread::id, pid_t> threads;
void add_tid_mapping()
{
  std::lock_guard<std::mutex> l(m);
  threads[std::this_thread::get_id()] = syscall(SYS_gettid);
}
void wrap(void (*f)())
{
  add_tid_mapping();
  f();
}

Then create your thread with:

std::thread t1(&wrap, &SayHello);

then get the ID with something like:

pid_t tid = 0;
while (tid == 0)
{
  std::lock_guard<std::mutex> l(m);
  if (threads.count(t1.get_id()))
    tid = threads[t1.get_id()];
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Oh getting the id this way is smart, that's great , thanks you ! – Char Aznable Jul 01 '13 at 13:29
  • Why would you build a std::map? Is the `syscall()` expected to be so expensive? Also, you never seem to remove threads from the map, which could be viewed as a memory leak (e.g. in a webserver setting where many threads are spawned over time and the process typically runs for months without restarting). – the swine Jul 24 '14 at 09:36
  • @theswine, the syscall gives you the ID of the current thread, the map lets you find the ID of _any_ thread, given its `thread::id`. That's more flexible. It's not strictly a leak, since the memory is still reachable, but to keep the memory usage bounded (and to cope with thread IDs being reused) you could use a `thread_local` object that adds to the map in its constructor and removes from the map in its destructor. The answer was a sketch demonstrating a solution, if you want something more robust then make it more robust. – Jonathan Wakely Jul 24 '14 at 09:46
  • @JonathanWakely You are right, I did not realize that you might want to get thread id *outside* of the thread. Thanks for the explanation. – the swine Jul 24 '14 at 10:01
  • 1
    I just wanted to emphasize that the `while(tid ==0)` is very important because the parent thread might reach the get thread id statement earlier than the mapping happens. – rph Jun 17 '18 at 08:20
1

Some pthread implementations, e.g. Android 21+, provide

pid_t pthread_gettid_np(pthread_t);

The implementation may use the internal structure of struct pthread_t to retrieve the native thread id, same as the one returned by gettid() or syscall(SYS_gettid) when called in the context of that thread.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
0

How about this:

pid_t gettid (void)
{
    return syscall(__NR_gettid);
}

http://yusufonlinux.blogspot.com/2010/11/get-thread-id-from-linux.html

Looks like __NR_gettid is defined in unistd.h

spartacus
  • 613
  • 6
  • 12
  • 1
    I think this is useful if you have a wrapper around `std:thread` or `pthreads`, but I can't call it from outside the thread. (correct me if I'm wrong). Thanks. – Char Aznable Mar 29 '13 at 18:38