pthread_self on Linux

2.3k Views Asked by At

I have the following small code snippet:

int main()
{
  pthread_t t = pthread_self();
  std::cout << t << std::endl;
  return 0;
}

When I compile+link on Linux using g++ 4.9.2 without any library, the output is :

0

When I link with pthread as below:

g++ test.c -o test -lpthread; ./test

The output is:

139675118393152

When linked with -lpthreads, can I get a mapping from actual POSIX thread ID to some index unique to the thread? I would like to have a global array having some thread-specific value to use, and need to use the thread id as the array index, can't handle 139675118393152, for example, need to map that to 1, 2, etc

1

There are 1 best solutions below

3
cbuchart On BEST ANSWER

More or less it is as follows: first, as pthread_self() is implemented in the standard C library, it doesn't need to be linked to be linked against -lpthreads.

Now, pthread_self() uses a global variable, a pointer to a TCB (thread control block), to store the thread information, including the ID (unique within the process).

This pointer is initialized to NULL (0), but Pthreads library (when linked) changes it so it now points to current thread header structure.

That's why you get a 0 when not linking with Pthreads and the actual POSIX thread ID when you do.

Custom thread IDs

You can assign a custom ID to each thread on creation and use that value as the index for your array.

void* thread_function(void* data) {
  assert(data);
  const int id = *((int*)data);

  // g_array[id]...
}

int main() {
  // ...
  pthread_t t0;
  int t0id = 0; // this variable must exist when the thread starts
  pthread_create(&t0, NULL, thread_function, &t0id);

  pthread_t t1;
  int t1id = 1; // this variable must exist when the thread starts
  pthread_create(&t1, NULL, thread_function, &t1id);
  // ...

  pthread_join(t0, NULL);
  pthread_join(t1, NULL);
}

Another option may be to use a global std::map<pthread_t, int> g_thread_ids structure and link the thread ID from pthread_self() and the array index passed as argument. You must be careful about race conditions (omitted here for simplicity). You should also care about the case (if possible) of a thread not created in this way, since the pthread_self() value will not exist in the map.

std::map<pthread_t, int> g_thread_ids;

int get_thread_index() { // note: critical section
   if (g_thread_ids.find(pthread_self()) == g_thread_ids.end()) return -1;
   return g_thread_ids[pthread_self()];
}

void* thread_function(void* data) {
  assert(data);
  const int id = *((int*)data); // read the index from caller
  g_thread_ids[pthread_self()] = id; // note: critical section

  // g_array[get_thread_index()]...
}