Не удалось скомпилировать __thread с помощью ndk clang 3.4/3.5.

Я безуспешно пытаюсь использовать __thread в этой небольшой программе. Есть идеи, поддерживается ли этот TLS в ndk 10c clang 3.4/3.5? Эта же программа прекрасно компилируется с 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 дизасс той же программы

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

person padlar    schedule 28.11.2014    source источник


Ответы (2)


TLS в стиле __thread (аналогично thread_local в стиле C++11) в настоящее время не поддерживается компоновщиком Android (хотя мы работаем над этим). Пока вам придется использовать pthread_getspecific и pthread_setspecific.

РЕДАКТИРОВАТЬ: Начиная с NDK r12, Clang поддерживает эмулируемый TLS. Хотя вышеприведенное по-прежнему технически верно (компоновщик на устройстве этого не поддерживает), компилятор может заменить встроенную поддержку TLS вызовами pthread от вашего имени.

NB: Android по-прежнему поддерживает только thread_local для объектов с тривиальными деструкторами до версии r14. См. обсуждения на https://github.com/android-ndk/ndk/issues/156#issuecomment-231878690 и https://github.com/android-ndk/ndk/issues/216.

person Dan Albert    schedule 28.11.2014
comment
У меня есть код, восходящий к 2004 году с использованием __thread/thread_local, который до сих пор не собирается на Android в 2016 году. Я не задерживаю дыхание... - person Glenn Maynard; 17.01.2016
comment
Это будет в следующем выпуске NDK (или, возможно, N+1). Clang теперь поддерживает эмуляцию TLS с помощью данных, специфичных для потока pthread (GCC некоторое время поддерживает), что позволит вам использовать __thread. - person Dan Albert; 18.01.2016
comment
Спасибо, Дэн, не могли бы вы поподробнее рассказать о выпуске NDK? - person Slagh; 21.01.2016
comment
Я надеюсь, что в ближайшие пару месяцев, но в последнюю минуту все требует изменений. Будет выпущен релиз-кандидат как можно скорее (что, вероятно, означает пару недель?) - person Dan Albert; 23.01.2016
comment
Изменилась ли ситуация с момента ответа на этот вопрос? - person wilx; 12.07.2016
comment
@wilx: Да, я обновил свой ответ, чтобы отразить текущее состояние мира. Спасибо за напоминание! - person Dan Albert; 13.07.2016
comment
И снова изменился (на самом деле еще в марте), потому что мы можем поддерживать нетривиальные глобальные деструкторы, начиная с r14. - person Dan Albert; 21.08.2017

Во-первых, вам следует избегать использования __thread, поскольку он может быть непереносимым.

Вот что говорит gnu gcc здесь https://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/Thread-Local.html :

Модель времени выполнения, которую GCC использует для реализации этого, происходит из ABI для процессора IA-64, но с тех пор была перенесена и на другие процессоры. Он требует значительной поддержки со стороны компоновщика (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

person Bipi    schedule 28.11.2014