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

Reply via email to