X-Recipient: archive-cygwin AT delorie DOT com DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:date:message-id:subject:from:to :content-type; q=dns; s=default; b=Iv4ay2nVT9dgNqqQmW3dmdXVsceoI 1eJKqKK4meblVO55Pw04P1DKsnwVgBCyvPG6LY4JDKR/dYm8wjqel7t2HY6SylNm X1j5/uXQ+/EhgDULE4ead8o9dK1zK6/0QwGX/rCC6e/o/iN3dTT+ag7pSVFLhvVM Ycrz9FwLG75MCA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:date:message-id:subject:from:to :content-type; s=default; bh=eB1t3ZbvbcTYGx3tJhjGEyQ+MGo=; b=G2f sspoGSCr1mKAAunQYN2J995w7Z5tRVvy3jglFhI+9OAfwfcGEFTNbiXioDJz94Dk dzOCx0nRBGgcFQMiIC2jPdT/2REGhpBalzviCOVC62ewOzMF6j4wzXCJ8xyr4ZUG HvanA565Qo+5XsS612ugS+o0Brrv5H91vSzIgr28= Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com 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 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) Date: Mon, 19 Jan 2015 15:42:17 +0100 Message-ID: Subject: C++11 thread_local implementation issue on Cygwin/AMD64 From: =?UTF-8?Q?V=C3=A1clav_Zeman?= To: cygwin AT cygwin DOT com Content-Type: multipart/mixed; boundary=047d7b3441c634984f050d025464 X-IsSubscribed: yes --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=UTF-8 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 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 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 I2luY2x1ZGUgImRlZi5oeHgiCgpuYW1lc3BhY2UgTgp7CgogIF9fZGVjbHNw ZWMoZGxsZXhwb3J0KQogIHZvaWQgKiBmb28gKCkKICB7CiAgICByZXR1cm4g Z2V0X3B0ZCAoKTsKICB9Cn0K --047d7b3441c634984f050d025464 Content-Type: text/plain; charset=us-ascii -- 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--