Regarding processes, we know that every process has a unique PID which is not used by any other process while the machine is running. I was wondering whether threads have such a system as well, or their ID is unique to the process they are running in itself and not the entire system.
Thread ids depend on the threading system used. I will describe POSIX and its implementation on Linux here.
First, the POSIX standard asks that each thread is assigned an identifier of type pthread_t
.
That's what's returned by pthread_create()
(as the first OUT argument) and it is used, for instance,
in pthread_join()
and pthread_detach()
. It is also returned by pthread_self()
.
Interestingly, POSIX intentionally keeps pthread_t
opaque, allowing it to be implemented as either
an (integer) identifier or as a struct. For that reason, a comparator pthread_equals()
exist to compare 2 thread ids. It should be noted that POSIX thread ids are guaranteed to be
unique only within one process - the same POSIX thread id could refer to different threads in
different processes.
Applications that are intended to run on all POSIX compliant system should use only
pthread_t
to refer to threads.
Second, in Linux specifically, a kernel-level thread is created for each POSIX thread. This thread is assigned a kernel-level thread id that comes from the same namespace as process ids. In fact, the thread id of the main thread (the thread that's created when a process is started) is equal to its process id.
This thread id can be obtained using the (hidden) system call gettid()
. Shown below is
code that uses the generic system call wrapper syscall(2)
to invoke this system call. Using this system call, it is possible to implement
a (nonportable) function is_lock_held
that determines the owner of a lock, which
can come in helpful during debugging.
#include <sys/types.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
// return current thread id
static pid_t gettid() {
return syscall(SYS_gettid);
}
static bool is_lock_held(pthread_mutex_t * lock) __attribute__((__unused__));
static bool is_lock_held(pthread_mutex_t * lock) {
return lock->__data.__owner == gettid();
}
int
main()
{
printf("%d %d\n", getpid(), gettid());
}
During debugging with gdb, gdb will show both the pthread ID and the task id (as LWP id) in its output.