Intel® C++ Compiler
Support and discussions for creating C++ code that runs on platforms based on Intel® processors.
7690 Discussions

thread-local storage linking problems

jdonald313
Beginner
306 Views
I am having trouble linking with __thread variables. Thread-local storage works fine for most things, but something goes wrong if I try linking with extern declarations. gcc does not have this problem. Here's what happens:

[jdonald@wallaby ~/ssppc]$ cat foo.c
#include
extern __thread int i;

int main() {
printf("%d ", i);
return 0;
}

[jdonald@wallaby ~/ssppc]$ cat bar.c
__thread int i = 5;

[jdonald@wallaby ~/ssppc]$ gcc foo.c bar.c
[jdonald@wallaby ~/ssppc]$ ./a.out
5
[jdonald@wallaby ~/ssppc]$ icc foo.c bar.c
ld: i: TLS definition in /tmp/iccyb9dRf.o section .tdata mismatches non-TLS reference in /tmp/icc9DxY1O.o
/tmp/iccyb9dRf.o: could not read symbols: Bad value
[jdonald@wallaby ~/ssppc]$ icc -c foo.c
[jdonald@wallaby ~/ssppc]$ icc -c bar.c
[jdonald@wallaby ~/ssppc]$ icc foo.o bar.o
ld: i: TLS definition in bar.o section .tdata mismatches non-TLS reference in foo.o
bar.o: could not read symbols: Bad value
[jdonald@wallaby ~/ssppc]$ objdump -t foo.o

foo.o: file format elf32-i386

SYMBOL TABLE:
00000000 l df *ABS* 00000000 foo.c
00000000 l d *ABS* 00000000 .strtab
00000000 l d *ABS* 00000000 .symtab
00000000 l d .text 00000000 .text
00000000 l d .rodata 00000000 .rodata
00000000 l O .rodata 00000004 __STRING.0
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 l d *ABS* 00000000 .rel.text
00000000 *UND* 00000000 i
00000000 g F .text 00000036 main
00000000 *UND* 00000000 __intel_new_proc_init
00000000 *UND* 00000000 printf


[jdonald@wallaby ~/ssppc]$ gcc -c foo.c
[jdonald@wallaby ~/ssppc]$ icc foo.o bar.o
[jdonald@wallaby ~/ssppc]$ ./a.out
5
[jdonald@wallaby ~/ssppc]$ objdump -t foo.o

foo.o: file format elf32-i386

SYMBOL TABLE:
00000000 l df *ABS* 00000000 foo.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .rodata 00000000 .rodata
00000000 l d .note.GNU-stack 00000000 .note.GNU-stack
00000000 l d .comment 00000000 .comment
00000000 g F .text 0000003c main
00000000 *UND* 00000000 _GLOBAL_OFFSET_TABLE_
00000000 *UND* 00000000 i
00000000 *UND* 00000000 printf


[jdonald@wallaby ~/ssppc]$

As you can see, the entry for the variable i in both the gcc-created and icc-created object files appears identical. What's going on? I am using icc (ICC) 9.0 20051201 and gcc (GCC) 4.0.0 20050519 (Red Hat 4.0.0-8) under Fedora Core 4. Any help would be greatly appreciated.

Message Edited by jdonald313 on 04-21-200610:28 AM

0 Kudos
3 Replies
Rick_Paulson
Beginner
306 Views
Try adding -gcc-version=400 to your command-line options.
-Rick
jdonald313
Beginner
306 Views
Still doesn't work. Earlier I was trying -gcc-version=330, since I read that in some document as gcc 3.3 is when thread-local storage was first supported. However, I get the same result with -gcc-version=330, -gcc-version=400, -gcc-version=402, or no options.

When I use -gcc-version=320, it gives parse errors on the __thread, which at least is exactly what's supposed to happen for gcc 3.2.
Raffenetti__Ken
Beginner
306 Views

This bug is still present in icc version 19.0.4.233. The issue appears to be that if the __thread variable is not referenced in the compilation unit in which it is defined, the compiler treats it as a regular variable.

mac1:tmp raffenet$ cat foo.c
__thread int i = 5;
mac1:tmp raffenet$ icc -c foo.c
mac1:tmp raffenet$ nm foo.o
0000000000000000 S _i

mac1:tmp raffenet$ cat bar.c
__thread int i = 5;

void bar() {
  i = 1;
}
mac1:tmp raffenet$ icc -c bar.c
mac1:tmp raffenet$ nm bar.o
000000000000006c s EH_frame0
0000000000000030 S __tls___i
                 U __tlv_bootstrap
0000000000000000 T _bar
0000000000000084 S _bar.eh
0000000000000068 s _i

Reply