Hello all, I was looking for previous correspondence on the subject of obtaining an OS thread ID from a `pthread_t`, but have been unable to find any. As such, I would like to ask if there may be interest in new API to allow this:
/* sys/types.h */ typedef /* platform-dependent integer */ tid_t; /* pthread.h */ int pthread_gettid(pthread_t thread, tid_t *thread_id); Background ---------- A `pthread_t` cannot be used to identify a thread because it is opaque, and its address is not meaningful since it is passed by value. Typically there is an association with an OS ID, but there is no POSIX-specified way to obtain it. Many systems already have a way to obtain a current OS identifier: * AIX: `pthread_id_np_t pthread_getthreadid_np(void);` [aix] * Linux, Android: `pid_t gettid(void);` [linux] * FreeBSD: `int pthread_getthreadid_np(void);` [freebsd] * NetBSD: `lwpid_t _lwp_self(void);` [netbsd] * OpenBSD: `pid_t getthrid(void);` [openbsd] Additionally, some platforms have a way to obtain the identifier from a `pthread_t`: * Apple: `int pthread_threadid_np(pthread_t thread, uint64_t *thread_id);` [apple] * Android: `pid_t pthread_gettid_np(pthread_t t)` [android] * Glibc 2.42: `pid_t pthread_gettid_np(pthread_t)` [glibc] * Windows: `DWORD GetThreadId(HANDLE Thread);` [windows] The wide variety of names and signatures seems to indicate value in a new cross-platform method with more uniform behavior. Proposed Behavior ----------------- Required behavior: 1. `pthread_gettid` stores an integer thread identifier (TID) for `thread` in `*thread_id` 2. If `thread` is NULL, a TID for the current thread is stored. 3. A return value of zero indicates success. 4. A return value of ESRCH indicates the thread ID could not be found. 5. If a thread is not running, it is unspecified whether ESRCH or zero is returned. If zero is returned, `*thread_id` will have been written (i.e. it is not uninitialized), but its value may be invalid. 6. The TID is process-unique at any given time; however, reuse is allowed after a thread exits. 7. A TID need not be globally (cross-process) unique. `id_t` is now required to also fit a `tid_t` (in addition to pid_t, uid_t, and gid_t). Recommended behavior: 1. In a single-thread process, the TID is the same as the process ID. 2. If the return value is nonzero, `*thread_id` has not been written (or read). 3. The TID should be an OS thread identifier if the concept exists. This should match what is available via process inspection (e.g. `/proc`). 4. `pthread_gettid` should return the same TID when querying the same thread at any time (i.e., the TID for a thread should not change once it is spawned). Usage guidelines: 1. The TID is intended to be user-facing. Example uses are for cross referencing TIDs in logs, debuggers, and process inspectors (`ps`). 2. `pthread_gettid` provides a "friendly" identifier but should not be relied upon for correctness; the OS is allowed to change the TID during a thread's lifetime (though this is strongly preferred against). This means that `pthread_gettid` must not be used to replace API like `pthread_equal`, and must not be used to query thread liveliness. Rationale --------- The function I suggest here keeps the Apple interface of returning the tid_d indirectly with an error direct return. This is relevant because some BSDs use an unsigned thread ID, so a `tid_t f(pthread_t)` signature would have no straightforward way of indicating the error condition. The name is selected to match the `_np` versions in Android and Glibc, which also matches POSIX `getpid`. A new type `tid_t` is introduced because many platforms have a 32-bit `pid_t`, but some platforms may choose to implement thread IDs as pointers. --- Thanks all, and best regards, Trevor Gross [aix]: https://www.ibm.com/docs/en/i/7.4.0?topic=ssw_ibm_i_74/apis/users_22.html [linux]: https://man7.org/linux/man-pages/man2/gettid.2.html [freebsd]: https://man.freebsd.org/cgi/man.cgi?query=pthread_getthreadid_np&sektion=3&format=html [netbsd]: https://man.netbsd.org/_lwp_self.2 [openbsd]: https://man.openbsd.org/getthrid.2 [apple]: https://www.manpagez.com/man/3/pthread_threadid_np/ [android]: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/pthread_gettid_np.cpp [windows]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadid [glibc]: https://sourceware.org/bugzilla/show_bug.cgi?id=27880