Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jun 2003 02:29:02 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Marcel Moolenaar <marcel@xcllnt.net>
Cc:        Julian Elischer <julian@elischer.org>
Subject:   Re: Implementing TLS: step 1
Message-ID:  <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>

next in thread | previous in thread | raw e-mail | index | archive | help
Marcel Moolenaar wrote:
> > Implementation defined access mechanisms are outside the scope
> > of this discussions, since they have not yet been selected.
> 
> In fact, they are already architected as part of the psABI (which is
> an extention to the psABI in most cases). It's our job to implement
> our threading models within the psABI.

Right.  There's a menu from which we can select, but it we can't
decide on something not on the menu.  That's what  I meant by it
being "outside the scope"... we're not allowed to reinvent some
new crazy thing.


> > 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);

...
{
	...
	x = (*funcp)( 3);
	...
	x = funcp( 7);
	...

You'd *hope* it would do the right thing, but mixing code and
data references didn't seem to be covered...


> > 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.

Specifically, the linker doesn't enforce the reference counting in
the "referenced/references" case, and you can end up with a runtime
unresolved symbol, if it's referenced by a library you are linked
against that expects you to link against a second party library.

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.

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.

Archie Cobbs ran into this with a second order dependency on a
database library when writing a JNI shared object that linked
against a third party library in Kaffe, bck in the Whistle days.
I tried to fix this back then, but it required tunneling state
across two functions calls deep.  Possible, but too much work;
we just linked the main program against the library required
by the modeule as a workaround.  8-(.

My relatively recent dive into the idea of a static libdl told
me that things haven't changes in there.


> > 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?

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?

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?

Thanks for your incredible patience with us,
-- Terry



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3EF2D3DE.8C7CA97D>