From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23696 invoked by alias); 19 Jan 2015 14:42:28 -0000 Mailing-List: contact cygwin-help@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner@cygwin.com Mail-Followup-To: cygwin@cygwin.com Received: (qmail 23683 invoked by uid 89); 19 Jan 2015 14:42:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-la0-f53.google.com Received: from mail-la0-f53.google.com (HELO mail-la0-f53.google.com) (209.85.215.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 19 Jan 2015 14:42:23 +0000 Received: by mail-la0-f53.google.com with SMTP id gq15so4773309lab.12 for ; Mon, 19 Jan 2015 06:42:17 -0800 (PST) MIME-Version: 1.0 X-Received: by 10.112.129.195 with SMTP id ny3mr32160146lbb.10.1421678537358; Mon, 19 Jan 2015 06:42:17 -0800 (PST) Received: by 10.114.185.65 with HTTP; Mon, 19 Jan 2015 06:42:17 -0800 (PST) Date: Mon, 19 Jan 2015 15:28:00 -0000 Message-ID: Subject: C++11 thread_local implementation issue on Cygwin/AMD64 From: =?UTF-8?Q?V=C3=A1clav_Zeman?= To: cygwin@cygwin.com Content-Type: multipart/mixed; boundary=047d7b3441c634984f050d025464 X-IsSubscribed: yes X-SW-Source: 2015-01/txt/msg00265.txt.bz2 --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=UTF-8 Content-length: 3693 Hi. I have hit an issue with thread-local storage variables on Cygwin/AMD64, I do not see it with Cygwin/i686. I am having linking issues when using `thread_local` keyword in Cygwin with its GCC 4.8.3 and GCC 4.9.2. This is derived from log4cplus. The test case is split into three files: File def.hxx: ~~~~ #include namespace N { struct S { std::string str; }; // extern declaration in a header extern thread_local S * ptd; // accessing the extern declared ptd here inline S * get_ptd () { if (! ptd) ptd = new S; return ptd; } } // namespace N ~~~~ File def.cxx: ~~~~ #include "def.hxx" namespace N { // definition of ptd thread_local S * ptd = nullptr; } // namespace N ~~~ File use.cxx: ~~~~ #include "def.hxx" namespace N { __declspec(dllexport) void * foo () { // invoking inline get_ptd() function to get the value in ptd return get_ptd (); } } ~~~~ Now, when I compile each .cxx with `g++ -std=gnu++11 -fvisibility=hidden -c use.cxx def.cxx` and then try to link with `g++ -shared -o cygtest.dll use.o def.o`, I get the following error from linker: ~~~~ use.o:use.cxx:(.text$_ZTWN1N3ptdE[_ZTWN1N3ptdE]+0x15): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `TLS init function for N::ptd' collect2: error: ld returned 1 exit status ~~~~ The nm -C ./def.o output confirms that: ~~~~ `--> nm -C ./def.o 0000000000000000 b .bss 0000000000000000 d .data 0000000000000000 r .rdata 0000000000000000 r .rdata$zzz 0000000000000000 t .text 0000000000000008 r __emutls_t._ZN1N3ptdE 0000000000000000 D __emutls_v._ZN1N3ptdE 0000000000000000 r std::piecewise_construct ~~~~ As you can see, the ptd thread-local variable initialization function is not defined anywhere. The use.o references this initialization function (see bottom of the listing): ~~~~ `--> nm -C ./use.o 0000000000000000 b .bss 0000000000000000 d .data 0000000000000000 i .drectve 0000000000000000 p .pdata 0000000000000000 p .pdata$_ZN1N1SC1Ev 0000000000000000 p .pdata$_ZN1N7get_ptdEv 0000000000000000 p .pdata$_ZTWN1N3ptdE 0000000000000000 r .rdata 0000000000000000 r .rdata$.refptr.__emutls_v._ZN1N3ptdE 0000000000000000 r .rdata$.refptr._ZTHN1N3ptdE 0000000000000000 r .rdata$zzz 0000000000000000 R .refptr.__emutls_v._ZN1N3ptdE 0000000000000000 R .refptr._ZTHN1N3ptdE 0000000000000000 t .text 0000000000000000 t .text$_ZN1N1SC1Ev 0000000000000000 t .text$_ZN1N7get_ptdEv 0000000000000000 t .text$_ZTWN1N3ptdE 0000000000000000 A .weak._ZTHN1N3ptdE._ZN1N1SC1Ev 0000000000000000 r .xdata 0000000000000000 r .xdata$_ZN1N1SC1Ev 0000000000000000 r .xdata$_ZN1N7get_ptdEv 0000000000000000 r .xdata$_ZTWN1N3ptdE U __emutls_get_address U __emutls_v._ZN1N3ptdE U __gxx_personality_seh0 U __real__ZdlPv U __real__Znwm U _Unwind_Resume U operator delete(void*) 0000000000000000 T N::S::S() 0000000000000000 T N::foo() 0000000000000000 T N::get_ptd() U std::basic_string, std::allocator >::basic_string() U operator new(unsigned long) 0000000000000000 r std::piecewise_construct w TLS init function for N::ptd 0000000000000000 T TLS wrapper function for N::ptd ~~~~ Now, this code seems to work well on Linux with both GCC and Clang. Is this a GCC problem on Cygwin? Am I using extern thread_local wrong? My experiments show that not using the extern keyword seems to fix the issue. But I am not sure if that does not introduce two ptd thread-local variables in two TUs. See also http://stackoverflow.com/q/28023728/341065 -- VZ --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=US-ASCII; name="def.cxx" Content-Disposition: attachment; filename="def.cxx" Content-Transfer-Encoding: base64 X-Attachment-Id: f_i53yols10 Content-length: 118 I2luY2x1ZGUgImRlZi5oeHgiCgpuYW1lc3BhY2UgTgp7CiAgdGhyZWFkX2xv Y2FsIFMgKiBwdGQgPSBudWxscHRyOwp9IC8vIG5hbWVzcGFjZSBOCg== --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=US-ASCII; name="def.hxx" Content-Disposition: attachment; filename="def.hxx" Content-Transfer-Encoding: base64 X-Attachment-Id: f_i53yolug1 Content-length: 273 I2luY2x1ZGUgPHN0cmluZz4KCm5hbWVzcGFjZSBOCnsKICBzdHJ1Y3QgUyB7 IHN0ZDo6c3RyaW5nIHN0cjsgfTsKICBleHRlcm4gdGhyZWFkX2xvY2FsIFMg KiBwdGQ7CgogIGlubGluZQogIFMgKiBnZXRfcHRkICgpCiAgewogICAgaWYg KCEgcHRkKQogICAgICBwdGQgPSBuZXcgUzsKICAgIHJldHVybiBwdGQ7CiAg fQp9IC8vIG5hbWVzcGFjZSBOCg== --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=US-ASCII; name="use.cxx" Content-Disposition: attachment; filename="use.cxx" Content-Transfer-Encoding: base64 X-Attachment-Id: f_i53yolul2 Content-length: 147 I2luY2x1ZGUgImRlZi5oeHgiCgpuYW1lc3BhY2UgTgp7CgogIF9fZGVjbHNw ZWMoZGxsZXhwb3J0KQogIHZvaWQgKiBmb28gKCkKICB7CiAgICByZXR1cm4g Z2V0X3B0ZCAoKTsKICB9Cn0K --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=us-ascii Content-length: 218 -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple --047d7b3441c634984f050d025464--