【问题标题】:No luck compiling __thread using ndk clang 3.4/3.5使用 ndk clang 3.4/3.5 编译 __thread 不走运
【发布时间】:2014-11-28 14:54:02
【问题描述】:

我试图在这个小程序中使用 __thread 没有运气。知道 ndk 10c clang 3.4/3.5 是否支持此 TLS?使用 ndk gcc 4.8/4.9 和本机 clang/gcc 编译器可以很好地编译相同的程序。


这是程序和编译行-

__thread int counter;
int main () { counter=20; return 0; }

[armeabi] Compile++ thumb: test <= test.cpp
/Users/padlar/android/android-ndk-r10c/toolchains/llvm-3.5/prebuilt/darwin-x86/bin/clang++ -MMD -MP -MF ./obj/local/armeabi/objs/test/test.o.d -gcc-toolchain /Users/padlar/android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86 -fpic -ffunction-sections -funwind-tables -fstack-protector -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -fno-integrated-as  -target armv5te-none-linux-androideabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing -I/Users/padlar/android/android-ndk-r10c/sources/cxx-stl/stlport/stlport -I/Users/padlar/android/android-ndk-r10c/sources/cxx-stl//gabi++/include -Ijni -DANDROID  -Wa,--noexecstack -Wformat -Werror=format-security -fPIE  -frtti     -I/Users/padlar/android/android-ndk-r10c/platforms/android-19/arch-arm/usr/include -c  jni/test.cpp -o ./obj/local/armeabi/objs/test/test.o
[armeabi] Executable     : test
/Users/padlar/android/android-ndk-r10c/toolchains/llvm-3.5/prebuilt/darwin-x86/bin/clang++ -Wl,--gc-sections -Wl,-z,nocopyreloc --sysroot=/Users/padlar/android/android-ndk-r10c/platforms/android-19/arch-arm -Wl,-rpath-link=/Users/padlar/android/android-ndk-r10c/platforms/android-19/arch-arm/usr/lib -Wl,-rpath-link=./obj/local/armeabi ./obj/local/armeabi/objs/test/test.o /Users/padlar/android/android-ndk-r10c/sources/cxx-stl/stlport/libs/armeabi/thumb/libstlport_static.a -lgcc  -gcc-toolchain /Users/padlar/android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86 -no-canonical-prefixes -target armv5te-none-linux-androideabi  -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -fPIE -pie  -L/Users/padlar/android/android-ndk-r10c/platforms/android-19/arch-arm/usr/lib -llog -lc -lm -o ./obj/local/armeabi/test
jni/test.cpp:2: error: undefined reference to '__aeabi_read_tp'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [obj/local/armeabi/test] Error 1

ndk-which objdump -S obj/local/armeabi/objs/test/test.o

obj/local/armeabi/objs/test/test.o:     file format elf32-littlearm
Disassembly of section .text.main:

00000000 <main>:
__thread int counter;
int main () { counter=20; return 0; }
   0:   b580        push    {r7, lr}
   2:   4904        ldr r1, [pc, #16]   ; (14 <main+0x14>)
   4:   f7ff fffe   bl  0 <__aeabi_read_tp>
   8:   1840        adds    r0, r0, r1
   a:   2114        movs    r1, #20
   c:   6001        str r1, [r0, #0]
   e:   2000        movs    r0, #0
  10:   bd80        pop {r7, pc}
  12:   46c0        nop         ; (mov r8, r8)
  14:   00000000    .word   0x00000000

gcc4.6对同一个程序的disass

ndk-which objdump -S obj/local/armeabi/objs/test/test.o

obj/local/armeabi/objs/test/test.o:     file format elf32-littlearm
Disassembly of section .text.startup.main:

00000000 <main>:
__thread int counter;
int main () { counter=20; return 0; }
   0:   b508        push    {r3, lr}
   2:   4804        ldr r0, [pc, #16]   ; (14 <main+0x14>)
   4:   4478        add r0, pc
   6:   f7ff fffe   bl  0 <__emutls_get_address>
   a:   2314        movs    r3, #20
   c:   6003        str r3, [r0, #0]
   e:   2000        movs    r0, #0
  10:   bd08        pop {r3, pc}
  12:   46c0        nop         ; (mov r8, r8)
  14:   0000000c    .word   0x0000000c

【问题讨论】:

    标签: android c++ android-ndk clang++ thread-local-storage


    【解决方案1】:

    __thread 样式 TLS(类似 C++11 样式 thread_local)目前不受 Android 链接器支持(不过我们正在努力)。现在你必须使用pthread_getspecificpthread_setspecific

    编辑:从 NDK r12 开始,Clang 支持模拟 TLS。虽然上述内容在技术上仍然正确(设备上的链接器不支持这一点),但编译器可以代表您将内置 TLS 支持替换为 pthread 调用。

    注意:在 r14 之前,Android 仍然只支持 thread_local 用于具有微不足道的析构函数的对象。请参阅https://github.com/android-ndk/ndk/issues/156#issuecomment-231878690https://github.com/android-ndk/ndk/issues/216 上的讨论。

    【讨论】:

    • 我的代码可以追溯到 2004 年使用的 __thread/thread_local,但在 2016 年仍未在 Android 上构建。我没有屏住呼吸......
    • 它将在 NDK 的下一个版本中(或者可能是N+1)。 Clang 现在支持通过 pthread 线程特定数据进行 TLS 仿真(GCC 已经有一段时间了),这将允许您使用 __thread
    • 谢谢 Dan,您能否更具体地了解一下 NDK 版本?
    • 我希望在接下来的几个月内,但事情总是在最后一刻需要改变。将尽快发布候选版本(这可能意味着几周?)
    • 自从回答这个问题后情况有变化吗?
    【解决方案2】:

    首先,您应该避免使用 __thread,因为它可能不可移植。

    这里是 gnu gcc https://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/Thread-Local.html 所说的:

    GCC 用来实现这一点的运行时模型起源于 IA-64 处理器特定的 ABI,但后来也被迁移到其他处理器。它需要链接器 (ld)、动态链接器 (ld.so) 和系统库(libc.so 和 libpthread.so)的大力支持,因此并非随处可用。

    来自维基百科http://en.wikipedia.org/wiki/Thread-local_storage#C.2B.2B

    C++0x 引入了 thread_local 关键字。除此之外,各种 C++ 编译器实现都提供了声明线程局部变量的特定方法:

    Sun Studio C/C++, IBM XL C/C++, GNU C and Intel C/C++ (Linux systems) use the syntax:
    
        __thread int number;
    Visual C++, Intel C/C++ (Windows systems), Borland C++ Builder and Digital Mars C++ use the syntax:
    
        __declspec(thread) int number;
     Borland C++ Builder also supports the syntax:
    
        int __thread number;
    

    所以它可能适用于thread_local 关键字

    【讨论】:

      猜你喜欢
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-26
      • 1970-01-01
      • 2019-05-31
      • 2015-05-16
      相关资源
      最近更新 更多