禁用__thread支持

时间:2012-09-22 11:13:46

标签: c linux pthreads

我正在实现一个非常轻量级的pthread替换库。我想完全禁用__thread有几个原因。

  1. 这是浪费记忆。如果我创建了一千个与声明带有__thread 变量的上下文无关的线程,它们仍然会分配 程序仍将分配 1000 *的大小那些数据字节,从不使用它。它与大规模并发模型没有内存兼容性。如果我们需要非常轻量级的光纤,只有8K的堆栈,那么仅4K的TLS块将是每个线程使用的内存的50%的开销。在某些情况下,TLS开销会很大。
  2. TLS是一个复杂的标准,我根本没有时间/资源来支持它。这很贵。我个人认为标准设计不合理。它应该定义必须由链接器提供的标准函数,以便线程库可以控制TLS分配发生的位置并插入它需要的相关偏移量和地址。此外,标准的ELF实现已被pthread感染,期望使用pthread大小的结构来计算偏移量,这使得它很难适应其他东西。
  3. 这只是一个糟糕的模式。它鼓励使用全局变量并使用静态函数/副作用创建函数。如果我们要创建易于分析的正确程序,这不是我们想要的领域。
  4. 如果我们真的需要“线程上下文”来追踪幕后线程状态的某些魔法(比如分配或取消跟踪),为什么不公开TLS用来理解该上下文的魔力呢?就个人而言,我只是直接使用%fs寄存器。由于显而易见的原因,这在图书馆中是不可能的,但为什么它们应该是线程感知的呢?为什么不正确地设计它们,以便它们首先在参数列表中获得所需的上下文相关数据?
  5. 我的问题很简单:如果您不小心使用它,禁用__thread支持并使clang发出错误的最简单方法是什么?如果加载一个恰好需要TLS的动态库,我怎么会出错?

1 个答案:

答案 0 :(得分:3)

我认为最简单的方法是无条件地向你的CFLAGS添加这样的东西(如果你希望它是系统全局的,可能来自clang相当于gcc规范文件):

-D__thread='^-^'

其中右侧可以是C程序中任何时候语法无效(违反约束)的任何内容。

至于使用TLS阻止加载库,您必须修补链接器和/或动态链接器以拒绝它们。如果您只是在讨论dlopen,那么您的程序可以首先读取该文件并解析ELF标头以进行TLS重定位,然后拒绝该库(不将其传递给dlopen)(如果有的话)。使用LD_PRELOAD包装器甚至可以实现这一点。

我同意你的看法,特别是在目前的实施中,TLS是一般应该避免使用的东西,但是我可以问你是否测量了成本?我认为在设计使用它的系统上将完全标记出来将是相当困难的,并且在减少膨胀方面有很多悬而未决的成果。您使用的是哪个libc?如果它是glibc,我很确定glibc现在有很多内部使用的TLS ......当然如果你正在编写自己的线程实现,这将需要与标准库的其余部分进行大量的交互,所以也许你已经把它修补了......?


顺便说一下(无耻插件),an extremely light-weight threads implementationmusl libc目前没有TLS。我认为与其他libc集成并不容易(我敢肯定,如果你自己编写,你会发现很难与glibc集成,尤其是glibc的动态链接器,它希望支持TLS)但是如果您可以按原样使用整个库,它可能满足您对特定项目的需求,或者您可以借用有用的代码(许可证是麻省理工学院)。