From owner-freebsd-threads@FreeBSD.ORG Fri Jun 20 11:36:00 2003 Return-Path: Delivered-To: freebsd-threads@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2E97037B401 for ; Fri, 20 Jun 2003 11:36:00 -0700 (PDT) Received: from ns1.xcllnt.net (209-128-86-226.bayarea.net [209.128.86.226]) by mx1.FreeBSD.org (Postfix) with ESMTP id 19E0543FA3 for ; Fri, 20 Jun 2003 11:35:59 -0700 (PDT) (envelope-from marcel@xcllnt.net) Received: from dhcp01.pn.xcllnt.net (dhcp01.pn.xcllnt.net [192.168.4.201]) by ns1.xcllnt.net (8.12.9/8.12.9) with ESMTP id h5KIZQDZ077394; Fri, 20 Jun 2003 11:35:26 -0700 (PDT) (envelope-from marcel@piii.pn.xcllnt.net) Received: from dhcp01.pn.xcllnt.net (localhost [127.0.0.1]) by dhcp01.pn.xcllnt.net (8.12.9/8.12.9) with ESMTP id h5KIZQR8018730; Fri, 20 Jun 2003 11:35:26 -0700 (PDT) (envelope-from marcel@dhcp01.pn.xcllnt.net) Received: (from marcel@localhost) by dhcp01.pn.xcllnt.net (8.12.9/8.12.9/Submit) id h5KIZPJd018729; Fri, 20 Jun 2003 11:35:25 -0700 (PDT) (envelope-from marcel) Date: Fri, 20 Jun 2003 11:35:25 -0700 From: Marcel Moolenaar To: Terry Lambert Message-ID: <20030620183525.GA18628@dhcp01.pn.xcllnt.net> References: <20030619202013.GA833@dhcp01.pn.xcllnt.net> <20030619223608.GB1273@dhcp01.pn.xcllnt.net> <3EF2AA23.89CCD315@mindspring.com> <20030620071729.GA16066@dhcp01.pn.xcllnt.net> <3EF2D3DE.8C7CA97D@mindspring.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <3EF2D3DE.8C7CA97D@mindspring.com> User-Agent: Mutt/1.5.4i cc: threads@freebsd.org cc: Julian Elischer Subject: Re: Implementing TLS: step 1 X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 Jun 2003 18:36:00 -0000 On Fri, Jun 20, 2003 at 02:29:02AM -0700, Terry Lambert wrote: > > > Note(1): I have no idea how this applies to things like function > > > pointers with this attribute pointed to functions without it; > > > > There's no problem. It's no different than having a function pointer > > on the stack or anywhere else in memory. > > I was worried that the compiler might not generate the correct > code for a function pointer dereference for a function pointer > that was __thread. E.g.: > > __thread int (*funcp)(int i); I don't think this is meaninful, unless you'd actually put the code of the function in the TLS. The __thread keyword cannot be applied to code. If you put a buffer in TLS, fill it with machine code and write an assembly stub that jumps to the buffer in TLS you have it, but the compiler doesn't know about it. > > > Note(2): For external global references, one would assume that > > > there are scoping issues, i.e. that the external declaration with > > > the "__thread" qualifier language extension *MUST* be in scope at > > > the time, or, at bes, the symbol decorations will not match, or, > > > at worst, everyone who references an out of scope variable like > > > this, or, if forced to have a reference in scope, the reference > > > fails to also have the "__thread" qualifier, they would get the > > > first thread's instance... or even worse, the template instance. > > > > All thread local variables must have TLS specific relocations > > attached to them. It the linkers job and also the rtlds job to > > validate this. A program is invalid is there's an inconsistency. > > OK, this could be a problem with the GNU toolchain, secifically > with linking shared. You would expect that the relocations would > be trated as RTLD_NOW at link time and RTLD_LAZY at runtime; that > is, at link time, you would not be permitted to have symbols that > referenced a library function that referenced symbols which did not > resolve in the set of objects and binaries you were linking. This > is not the case. It's also not meaningful. There are no guarantees that the library you load at runtime is in fact the library that was given to the linker at link time. The only thing the linker has to do is to make sure all TLS symbols have TLS relocations. This guatantees that all ELF objects are consistent. The rtld then should not bind a TLS symbol to a non-TLS symbol. > The way you are *supposed* to ensure against this, according to the > linker's assumptions, is that all ELF binaries are linked shared, > and all shared libraries that depend on other shared libraries are > linked against them explicitly. Yes. > This is not the case on FreeBSD, which supports static linking, > and as you probably already know, static ELF libraries can't be > linked against other ELF libraries that way, so that they get > drug in automatically. But a static library is just another way of listing object files on the link line. They are part of the object your're linking. >From a dynamic linking poin of view they're not even libraries. Thus, if there's a dependency on some library L from within an object file in the archive library, you're supposed to put that library L on the link line as well. If L is a static library, this will be recursive. > > > This is where I personally have a problem with lazy intialization > > > of per thread TLS. Specifically, when a thread exits, you have to > > > know what you have and have not instanced, on a per dynamic object, > > > per thread basis, as a minimum granularity, in order to be able to > > > clean it up, without trying to clean up things you have not yet > > > instanced in that particular thread. > > > > This is where the DTV comes in. It's basicly a vector of TLS block > > pointers and each pointer/index corresponds to the TLS block of > > a shared library. At cleanup you iterate over the vector and clean > > all the non-NULL pointers. This is specific to the dynamic TLS > > model, BTW. > > This is the 256 entry pointer table from the spec., right? Yes. > I still don't think a program can know apriori what kind of a > reference to generate in its code: how does it know, at the > time an individual object is compiled, that you are going to > link it static or dynamic, so it should generate static vs. > dynamic references? A compiler generally won't know. So, one solution is to always generate dynamic TLS sequences. This however requires that the static binaries also contain __tls_get_addr(). GCC has tied this to -fpic. If you compile without -fpic, the code is unsuitable for shared libraries and static TLS sequences are generated. Thus, if you compile a staticly linked binary containing TLS with -fpic, you need __tls_get_addr() in your startup code or libc or where-ever. Note that the use of the __thread keyword does not mean you'll actually link against the thread library. > Or are you saying this only applies to dlopen, and not to linking > against a dynamic library... and that ld.so will need to know > which kind of thing it's link-loading, and act differently? ELF objects containing TLS will have a flag that is set when the ELF object contains static TLS access sequences. The rtld should reject loading such ELF objects. > Thanks for your incredible patience with us, No problem. The consequences of having the _thread keyword are tricky. We need to make sure we grasp it, that includes me. I may have been close to the fire, but that does not mean I actually know it all. Talking about it is one way to make sure that we don't rush things and consequently end up having it wrong. -- Marcel Moolenaar USPA: A-39004 marcel@xcllnt.net