thread-local storage, especially on x86
thread-local storage, especially on x86
- Subject: thread-local storage, especially on x86
- From: Gary Byers <email@hidden>
- Date: Sun, 11 Sep 2005 11:35:27 -0600 (MDT)
OSX/Darwin's the only relatively mainstream platform that I can think
of that doesn't yet offer thread local storage (beyond the support
offered by pthread_getspecific()/pthread_setspecific()). It's possible
that some people believe that that mechanism is entirely adequate for
all programs present and future; I'm personally skeptical of that, and
I would have to assume that other people may share that skepticism.
The concerns that I have aren't based on the belief that the pthread
library functions are somehow grossly inefficient (there doesn't seem
to be a lot of wasted motion in their x86 Darwin implementation; in
fact, the actual access performed by pthread_getspecific() is a single
MOV instruction.) In order to execute that MOV instruction, a
function call has to be executed, and I don't think that it's
unreasonable to believe that that function call overhead can be
significant and undesirable for some - perhaps many - applications.
Functions like pthread_getspecific() would ordinarily be good
candidates for inlining, and "real" TLS schemes generally involve
codifying the ways in which compilers (with help from other toolchain
components) can inline access to thread-specific data.
The Darwin implementations of pthread_getspecific() and
pthread_setspecific() are opaque, so - tempting though it may be -
it'd be risky to effectively inline that MOV instruction. I can
understand Apple's motivation for wanting to maintain that opacity,
but ... I think that it's possible to expose a "codified" TLS interface
without making pthread internals public. (The Linux TLS implementation
certainly does this, and does it well.)
On the PowerPC, it may be possible for some applications to circument
these limitations by keeping a pointer to important thread-specific
data in a registers. That strategy has -some- obvious drawbacks (burning
a register), but that may be an acceptable tradeoff. On 32-bit x86,
that strategy would be significantly more costly, for obvious reasons
(though it's hard to avoid noticing that the %fs segment register is -
for most x86 Darwin applications - totally unused.)
The Darwin kernel offers a function - thread_set_user_ldt() - which
allows user-level code to set up a segment selector which can be
loaded into %fs and used to address a specified address range. (The
name of this function may be a little misleading, since it seems that
that segment descriptor is shared by all threads in the calling
process.) Comments prefacing that function suggest the possibility
(if I understand correctly) of allocating and maintaing this selector
on a per-thread basis; it's much easier for me to imagine that
behavior being useful than it is for me to imagine a use for the
current behavior.
A "real" TLS scheme would likely require support from the compiler and
toolchain and quite likely from the dynamic linker and runtime system
as well. Making the implementation of pthread_getspecific() and
pthread_setspecific() more transparent might enable some applications
to exploit that transparency, but might also restrict Apple's ability
to enhance and extend its pthreads impementation (though I imagine
that there's some middle ground between those extremes.) Extending
thread_set_user_ldt() (and providing related kernel support for
thread-specific selectors in the %fs register) seems like it might be
the simplest way of providing lower-cost thread-local storage to
applications in the short term.
I hope that I haven't mischaracterized anything and hope that this is
of general interest; I hope especially that it's of interest to someone
within Apple who's in a position to do something about it.
Gary Byers
email@hidden
www.clozure.com
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden