美文网首页
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