美文网首页
Bionic TLS介绍

Bionic TLS介绍

作者: Little熊猫 | 来源:发表于2019-02-27 14:40 被阅读0次

一 什么是TLS

TLS英文全称Thread local Storage,准确的定义是 a computer programming method that uses static or global memory local to a thread。在线程中使用的全局或者static变量,在线程中本地复制一份。最常见的使用场景是errno。每个线程有一份本地的errno,线程间彼此不影响。在bionic中errno的定义:

 int* __errno(void) __attribute_const__;
 #define errno (*__errno())

attribute_const const 告诉编译器某个函数是无状态的(也就是说,它使用传递给它的参数生成要返回的结果)。The const function attribute specifies that a function examines only its arguments, and has no effect except for the return value. That is, the function does not read or modify any global memory.// attribute((const)) functions do not read or modify any global memory。
// attribute((const)) functions do not read or modify any global memory
还有就是使用

__thread int number;
thread_local int tls_var;

二 TLS的位置

在elf中,tls变量存储在elf的tbss和tdata段


TLS1.png

像其他变量一样,TLS也可以动态链接,如果这样的话,TLS变量将会出现在符号表,相关的type类型为STT_TLS,存储位置:


tls_1_1.png

在ARM运行时相关的tls的加载地址为:


tls_2.png

DTV为dynmic thread vector,向量保存着tls的存储位置。

三 bionic中的TLS处理

目前bionic不支持ELF TLS,因此在编译时使用了-emulated-tls,相关的soong代码如下:

            // Work around bug in Clang that doesn't pass correct emulated
            // TLS option to target. See b/72706604 or
            // https://github.com/android-ndk/ndk/issues/498.
            flags.LdFlags = append(flags.LdFlags, "-Wl,-plugin-opt,-emulated-tls")

libc中相关的处理,对于tls的

        if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
          DL_ERR("unsupported ELF TLS symbol \"%s\" referenced by \"%s\"",
                 sym_name, get_realpath());
          return false;
        }
        if (!relocating_linker) {
          if (d->d_tag == DT_TLSDESC_GOT || d->d_tag == DT_TLSDESC_PLT) {
           DL_ERR("unsupported ELF TLS DT entry in \"%s\"", get_realpath());
            return false;
         }

对于errno处理比较特殊,专门放到了tcb中,相关的代码如下:

// Well-known TLS slots. What data goes in which slot is arbitrary unless otherwise noted.
enum {
  TLS_SLOT_SELF = 0, // The kernel requires this specific slot for x86.
  TLS_SLOT_THREAD_ID,
  TLS_SLOT_ERRNO,

  // These two aren't used by bionic itself, but allow the graphics code to
  // access TLS directly rather than using the pthread API.
  TLS_SLOT_OPENGL_API = 3,
  TLS_SLOT_OPENGL = 4,

  // This slot is only used to pass information from the dynamic linker to
  // libc.so when the C library is loaded in to memory. The C runtime init
  // function will then clear it. Since its use is extremely temporary,
  // we reuse an existing location that isn't needed during libc startup.
  TLS_SLOT_BIONIC_PREINIT = TLS_SLOT_OPENGL_API,

  TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86.
  TLS_SLOT_DLERROR,

  // Fast storage for Thread::Current() in ART.
  TLS_SLOT_ART_THREAD_SELF,

  // Lets TSAN avoid using pthread_getspecific for finding the current thread
  // state.
  TLS_SLOT_TSAN,

  BIONIC_TLS_SLOTS // Must come last!
};

int*  __errno() {
  return reinterpret_cast<int*>(&(__get_tls()[TLS_SLOT_ERRNO]));
}

但是从android 10.0的最新代码看,ELF TLS支持已经添加进去。

相关文章

网友评论

      本文标题:Bionic TLS介绍

      本文链接:https://www.haomeiwen.com/subject/dwcfuqtx.html