Hello Daniel,

2013/12/21 Daniel Villeneuve <[email protected]>:
> Hi,
>
> I have a DLL library which declares an "extern __thread int iTlsExtern"
> variable, which I can access from the library and from a program.
>
> However, modifications made from the library to iTlsExtern are not
> seen from the program.
>
> This seems to come from the fact that the address of the variable
> from the library is different from the address from the program.
>
> I'm using gcc 4.8.2, binutils 2.24, mingw-w64-v3.0.0,
> pthreads-w32-2-9-1-release.  The program is compiled in 64-bit mode.
>
> My test program is given below (files lib.h, lib.c, prog.c and Makefile).
> Running prog displays two different values for &iTlsExtern depending
> on the address being taken from main or the library.  After doing
> iTlsExtern=2 in the library, the output from the library is correct but
> the output from main is not.
>
> Is there something wrong with the code, the feature macros (from lib.h)
> or the compilation flags in the Makefile)?
>
> Is there something else I can provide to investigate the problem?
> --
> Daniel Villeneuve
>
>
> ----- lib.h
> #ifndef LIB_H
> #define LIB_H
>
> #ifndef _POSIX_C_SOURCE
> #define _POSIX_C_SOURCE         200809L
> #endif
>
> #ifndef _MT
> #define _MT                     1
> #endif
>
> #include <stdio.h>
>
> #define EXPORT __declspec(dllexport)
> #define IMPORT __declspec(dllimport)
> #define thread_local __thread
>
> extern thread_local LIB_DLLPORT int iTlsExtern;
>
> extern LIB_DLLPORT void LibDebug(void);
> extern LIB_DLLPORT void LibInit(int);
>
> #endif
>
> ----- lib.c
> #include "lib.h"
>
> thread_local int iTlsExtern;
>
> void LibDebug(void)
> {
>    fprintf(stderr, "&iTlsExtern (from LibDebug) = %p\n", (void
> *)&iTlsExtern);
>    fprintf(stderr, " iTlsExtern (from LibDebug) = %d\n", iTlsExtern);
> }
>
> void LibInit(int i)
> {
>    fprintf(stderr, " setting iTlsExtern to %d (from LibDebug)\n", i);
>    iTlsExtern = i;
> }
>
> ----- prog.c
> #include <stdio.h>
> #include "lib.h"
>
> static void MainDebug(void)
> {
>    fprintf(stderr, "&iTlsExtern (from MainDebug) = %p\n", (void
> *)&iTlsExtern);
>    fprintf(stderr, " iTlsExtern (from MainDebug) = %d\n", iTlsExtern);
> }
>
> int main(void)
> {
>    MainDebug();
>    LibDebug();
>
>    LibInit(2);
>
>    MainDebug();
>    LibDebug();
>
>    return 0;
> }
>
> ----- Makefile
> CROSS=x86_64-w64-mingw32-
>
> .PHONY: all clean
> all: prog.exe
> clean:
>      rm -f prog.exe prog.o liblib.dll.a lib.dll lib.o
>
> prog.exe: prog.o lib.dll
>      $(CROSS)gcc -std=gnu11 -o prog.exe prog.o \
> -Wl,--add-stdcall-alias -Wl,--export-all-symbols -L. -llib -lpthread
>
> prog.o: prog.c lib.h
>      $(CROSS)gcc -std=gnu11 -DLIB_DLLPORT=IMPORT -o prog.o -c prog.c
>
> lib.dll: lib.o
>      $(CROSS)gcc -Wl,--out-implib=liblib.dll.a -o lib.dll lib.o \
> -shared -Wl,-hliblib.dll.a -Wl,--add-stdcall-alias
> -Wl,--export-all-symbols -lpthread
>
> lib.o: lib.c lib.h
>      $(CROSS)gcc -std=gnu11 -DLIB_DLLPORT=EXPORT -o lib.o -c lib.c

The issue here is that you try to mix two concepts here.  A
thread-local variable can't be exported by dll-export, due its address
is mutable for each thread.  So it is invalid trying to dllexport such
a variable.

A valid way of exporting a TLS-variable would be by using a
helper-function, which returns the address of the TLS-variable for the
calling thread.

Regards,
Kai

------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to