禁用__thread支持 [英] Disable __thread support

查看:58
本文介绍了禁用__thread支持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm implementing a pthread replacement library which is extremely lightweight. There are several reasons why I want to disable __thread completely.

  1. 这是浪费内存.如果我要创建一千个与__thread声明变量的上下文无关的线程它们仍将分配 程序仍将分配 1000 *大小的数据字节,并且永远不要使用它.它根本不是与大容量并发模型兼容的内存.如果我们需要只有8K堆栈的极轻量级的光纤,那么仅4K的TLS块将占用每个线程所用内存的50%.在某些情况下,TLS开销会很大.
  2. TLS是一个复杂的标准,我只是没有时间/资源来支持它.太贵了.我个人认为该标准设计得很差.它应该定义了链接程序必须提供的标准功能,以便线程库可以控制TLS分配的位置,并插入相关的偏移量和所需的地址.同样,标准ELF实现也感染了pthread,希望pthread大小的结构能够计算偏移量,从而使其很难适应其他东西.
  3. 这只是一个错误的模式.它鼓励使用全局变量并创建具有静态功能/副作用的功能.如果我们要创建易于分析的正确程序,那么这不是我们想要的领域.
  4. 如果我们确实需要用于跟踪幕后线程状态的某种魔术的线程上下文"(例如分配或取消跟踪),为什么不仅仅公开TLS用于首先了解该上下文的魔术呢?就个人而言,我将直接使用 %fs 寄存器.由于明显的原因,这在库中是不可能的,但是为什么它们从一开始就应该具有线程意识?为什么不正确地设计它们,以便它们在参数列表中首先获得所需的上下文相关数据?
  1. It's a waste of memory. If I'm creating a thousand threads which has nothing to do with the context that declares a variable with __thread they will still allocate the program will still have allocated 1000*the size of that data bytes and never use it. It's simply not memory compatible with the mass-concurrency model. If we need extremely lightweight fibers with only 8K of stack, a TLS block of just 4K would be an overhead of 50% of the memory used by each thread. In some scenarios the TLS overhead would be enormous.
  2. TLS is a complex standard and I simply don't have the time/resources to support it. It's to expensive. Personally I think the standard is poorly designed. It should have defined standard functions that had to be provided by the linker so thread libraries can take control over where TLS allocation takes place and insert relevant offsets and addresses it requires. Also the standard ELF implementation has been infected with pthread, expecting pthread sized structs to calculate offsets making it really hard to adapt to something else.
  3. It's just a bad pattern. It encourages using globals and creating functions with static functions/side effects. This is not a territory we want to be in if we're creating correct programs that are easy to analyze.
  4. If we really need "thread context" for some magic that tracks thread state behind the scenes (like for allocation or cancellation tracking) why not just expose the magic that TLS uses to understand that context in the first place? Personally I'm just going to use the %fs register directly. This would not be possible in libraries for obvious reasons but why should they be thread aware to begin with? Why not just design them correctly so they get the context related data they need in the first place right in the argument list?

我的问题很简单:如果不小心使用了__thread支持,并且使clang发出错误,最简单的方法是什么?如果加载刚需要TLS的动态库,怎么会出错?

My question is simply: What is the simplest way to disable __thread support and make clang emit errors if you accidentally used it? How can I get errors if I load a dynamic library which happens to require TLS?

推荐答案

我相信最简单的方法是无条件地向您的CFLAGS中添加这样的内容(如果您希望clang成为系统全局的,则可能来自clang的gcc specfile):

I believe the simplest way is adding something like this unconditionally to your CFLAGS (perhaps from clang's equivalent of the gcc specfile if you want it to be system-global):

-D__thread='^-^'

在C程序的任何位置,右侧可以是语法上无效的任何东西(违反约束).

where the righthand side can be anything that's syntactically invalid (a constraint violation) at any point in a C program.

为防止使用TLS加载库,您必须修补链接程序和/或动态链接程序以拒绝它们.如果您只是在谈论 dlopen ,则程序可以先读取文件并解析TLS重定位的ELF标头,然后拒绝该库(而不将其传递给 dlopen )如果有的话.甚至可以使用 LD_PRELOAD 包装器.

As for preventing loading of libraries with TLS, you'd have to patch the linker and/or dynamic linker to reject them. If you're just talking about dlopen, your program could first read the file and parse the ELF headers for TLS relocations, then reject the library (without passing it to dlopen) if it has any. This might even be possible with an LD_PRELOAD wrapper.

我同意您的意见,特别是在当前实施中,TLS是应该避免使用的一种方式,但是请问您是否已衡量成本?我认为在一个旨在使用它的系统上完全将其消除将相当困难,并且有很多可以减少膨胀的结果.您正在使用哪个libc?如果是glibc,我可以肯定的是,这些天glibc本身在内部使用了很多TLS ...当然,如果您正在编写自己的线程实现,则将需要与标准库的其余部分进行大量交互,所以也许您已经在修补它了??

I agree with you that, especially in its current implementation, TLS is something whose use should generally be avoided, but may I ask if you've measured the costs? I think stamping it out completely will be fairly difficult on a system that's designed to use it, and there's much lower-hanging fruit for cutting bloat. Which libc are you using? If it's glibc, I'm pretty sure glibc has lots of TLS it uses internally itself these days... Of course if you're writing your own threads implementation, that's going to entail a lot of interaction with the rest of the standard library, so perhaps you're already patching it out...?

顺便说一下(后面是无耻的插件),我们非常轻当前没有TLS的 musl libc 中的轻量级线程实现.我认为与另一个libc集成并不容易(而且我敢肯定,如果您正在编写自己的libc,您将发现与glibc集成非常困难,尤其是glibc的动态链接器,它希望支持TLS),但是如果您可以按原样使用整个库,则它可能满足您对特定项目的需求,或者可以借用有用的代码(许可证为MIT).

By the way (shameless plug follows), we have an extremely light-weight threads implementation in musl libc which presently does not have TLS. I don't think it would be easy to integrate with another libc (and I'm sure if you're writing your own you will find it difficult to integrate with glibc, especially glibc's dynamic linker, which expects TLS to be supported) but if you can use the whole library as-is, it may meet your needs for specific projects, or have useful code you can borrow (license is MIT).

这篇关于禁用__thread支持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆