在 Linux 中实现快速的“GetCurrentThreadId”

Myr*_*ria 2 linux multithreading posix pthreads

Windows NT 有一个很好的函数GetCurrentThreadId,它的名字暗示了它的作用。它的实现非常快,因为它只是从线程本地存储中读取一个变量,该变量在 NT 内核创建线程期间写入那里。我想在 Linux 中实现它,但我遇到了一个障碍。

我最初的实现是这样的:

typedef pid_t ThreadID;

ThreadID GetCurrentThreadId(void)
{
    static __thread ThreadID t_cachedID = (ThreadID) -1;

    if (__builtin_expect(t_cachedID == (ThreadID) -1, 0))
    {
        t_cachedID = (ThreadID) syscall(__NR_gettid);
    }

    return t_cachedID;
}
Run Code Online (Sandbox Code Playgroud)

问题是fork。在程序,使用forkt_cachedID变得陈旧-新的子进程的主线程有线程的线程本地存储的副本叫fork,那t_cachedID就是不再正确。

解决方案应该是pthread_atfork,以便t_cachedID将新子进程中的值更改为 -1,但作为 Pthreads API 的规范,它的设计很差。如果你是被使用卸载一个DLL dlclosepthread_atfork不知道这一点,仍然会尽力呼吁一个你的函数fork,并KABOOM。糟糕的设计决策#1。也没有 API 可以删除您的回调函数。糟糕的设计决策#2。

有一个模糊记录的 glibc 函数__register_atfork似乎旨在处理这个问题,但它需要一个 DLL 句柄,而不是提供一种删除*_atfork处理程序的方法。glibc 在尝试解决 POSIX 糟糕的设计决策时做出的糟糕的设计决策 #1。

如何获得我自己的 DLL 句柄?在 Linux 中,似乎每次有人调用DLL/.so 文件时都会dlopen返回不同的void *句柄dlopen,而不仅仅是维护引用计数......?它不像 Windows 中的 DLL 句柄等于节映射的基地址。除非有一些简单的方法可以在 Linux 中获得自己的 DLL 句柄,否则这会导致糟糕的设计决策 #2。

有没有更好,正确的方法来做到这一点?

Dew*_*wfy 5

嗯,实际上 posix 已经包含返回线程 id 的函数

 pthread_self() //thanks to alk 
Run Code Online (Sandbox Code Playgroud)

旧答案:

int thr_self()
Run Code Online (Sandbox Code Playgroud)