Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jun 2003 11:35:25 -0700
From:      Marcel Moolenaar <marcel@xcllnt.net>
To:        Terry Lambert <tlambert2@mindspring.com>
Cc:        Julian Elischer <julian@elischer.org>
Subject:   Re: Implementing TLS: step 1
Message-ID:  <20030620183525.GA18628@dhcp01.pn.xcllnt.net>
In-Reply-To: <3EF2D3DE.8C7CA97D@mindspring.com>
References:  <20030619202013.GA833@dhcp01.pn.xcllnt.net> <Pine.BSF.4.21.0306191323250.41210-100000@InterJet.elischer.org> <20030619223608.GB1273@dhcp01.pn.xcllnt.net> <3EF2AA23.89CCD315@mindspring.com> <20030620071729.GA16066@dhcp01.pn.xcllnt.net> <3EF2D3DE.8C7CA97D@mindspring.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030620183525.GA18628>