Discussion:
Thread Local Storage - a contradiction in the available MS docs.
(too old to reply)
R.Wieser
2011-04-06 12:25:44 UTC
Permalink
Hello All,

I've been wanting to use some thread-local storage, and found the TLS
related commands on MS-es website, in specific these ones :

TlsAlloc : http://msdn.microsoft.com/en-us/library/ms686801(v=vs.85).aspx
TlsSetValue : http://msdn.microsoft.com/en-us/library/ms686818(v=vs.85).aspx

The problem is that they seem to contradict one another. :-(

What I mean ? See the first paragraph of the remark section of the
TlsAlloc function, and compare it with the second paragraph of the remark
section of the TlsSetValue function : As far as I can tell the first tells
me *not* to regard the TLS as a Zero-based indexed array, while the second
seems to be saying its exactly that (with upto TLS_MINIMUM_AVAILABLE
guaranteed available slots).

Currently I get the feeling that I can just use TlsSetValue and TlsGetValue
without bothering to use TlsAlloc as long as I keep the slot-index lower
than TLS_MINIMUM_AVAILABLE, and that the "not opaque" remark to the TlsAlloc
function might (is it ?) only be valid when TlsFree is used.

Can anyone confirm it ? Is there perhaps any more/other info available ?

Regards,
Rudy Wieser
David Lowndes
2011-04-06 12:47:28 UTC
Permalink
... As far as I can tell the first tells
me *not* to regard the TLS as a Zero-based indexed array, while the second
seems to be saying its exactly that (with upto TLS_MINIMUM_AVAILABLE
guaranteed available slots).
I don't read it as a contradiction, more so a warning of the current
implementation and that TlsSetValue/TlsGetValue will succeed with any
value in that range even if you've not obtained it via TlsAlloc.
Currently I get the feeling that I can just use TlsSetValue and TlsGetValue
without bothering to use TlsAlloc as long as I keep the slot-index lower
than TLS_MINIMUM_AVAILABLE, and that the "not opaque" remark to the TlsAlloc
function might (is it ?) only be valid when TlsFree is used.
I'd agree with that interpretation.

... though since the documentation says to use TlsAlloc, a future
implementation might be more rigorous!

Dave
R.Wieser
2011-04-06 20:36:12 UTC
Permalink
Hello David,
... more so a warning of the current implementation
The *current* implementation ? It is valid on a W98se as well as an XP
machine (I tested), and it looks to be still valid on a Win7 machine
(according to those docs). Nothing "current" about that.
TlsSetValue/TlsGetValue will succeed with any value in
that range even if you've not obtained it via TlsAlloc.
Agreed. But that range is explicitily defined as Zero-based in in one
function, when the other seems to tell me thats not to be depended upon.
Without any kind of explanation mind you :-(
... though since the documentation says to use TlsAlloc,
a future implementation might be more rigorous!
It also says there allways a certain minimum available, which negates the
need of having to use TlsAlloc. It simply does not match. I can read it
one way, but as easily as another. Not funny.

But as I just need a few thread-local values (at least one, to point to some
allocated data-space) I will stay far below that "minimum available" number
and probably do not have to worry about it.

... but I would liked to have something more definitive. Oh well. :-)

Regards,
Rudy Wieser
... As far as I can tell the first tells
me *not* to regard the TLS as a Zero-based indexed array, while the second
seems to be saying its exactly that (with upto TLS_MINIMUM_AVAILABLE
guaranteed available slots).
I don't read it as a contradiction, more so a warning of the current
implementation and that TlsSetValue/TlsGetValue will succeed with any
value in that range even if you've not obtained it via TlsAlloc.
Currently I get the feeling that I can just use TlsSetValue and TlsGetValue
without bothering to use TlsAlloc as long as I keep the slot-index lower
than TLS_MINIMUM_AVAILABLE, and that the "not opaque" remark to the TlsAlloc
function might (is it ?) only be valid when TlsFree is used.
I'd agree with that interpretation.
... though since the documentation says to use TlsAlloc, a future
implementation might be more rigorous!
Dave
David Schwartz
2011-04-13 11:10:57 UTC
Permalink
The *current* implementation ?  It is valid on a W98se as well as an XP
machine (I tested), and it looks to be still valid on a Win7 machine
(according to those docs).  Nothing "current" about that.
Those are all current implementations, that is, they are all
implementations that it is currently possible for your code to be
running on. It's very important to distinguish between what are the
defined, guaranteed properties of the functions you are calling and
what are things that the current implementations 'just happen to do'.
If you rely on something that the current implementation just happens
to do, the next implementation might just happen to do something else,
and your code might break on Windows 8 or Windows 7 SP2 or whatever.

If you rely on the defined, guaranteed properties and a new version of
Windows breaks your code, that's Microsoft's fault. If you rely on
things current implementations just happen to do and a new version of
Windows breaks your code, that's your fault.

DS

Leo Davidson
2011-04-06 14:28:05 UTC
Permalink
Post by R.Wieser
Currently I get the feeling that I can just use TlsSetValue and TlsGetValue
without bothering to use TlsAlloc as long as I keep the slot-index lower
than TLS_MINIMUM_AVAILABLE, and that the "not opaque" remark to the TlsAlloc
function might (is it ?) only be valid when TlsFree is used.
That seems like a bad idea. How do you know some other DLL is not
already using the TLS index you choose for its own data?

The purpose of TlsAlloc is to obtain an index that nobody else is
using (assuming that everyone is well-behaved and uses TlsAlloc, of
course).

(You may not be loading other DLLs explicitly but they can be loaded
into your process implicitly anyway, and they may be using TLS to
store data.)

(And if it is your own process, do you need to use TLS at all? There
are usually better, easier, safer ways to associate data with a
thread. You usually only need to resort to TLS if your DLL is being
loaded into 3rd party processes that give you no other choice.)
R.Wieser
2011-04-06 21:03:34 UTC
Permalink
Hello Leo,
Post by Leo Davidson
That seems like a bad idea. How do you know some other
DLL is not already using the TLS index you choose for its
own data?
Hmm ... You've got a point there. A DLL is loaded (and its
initialisation-code executed) before the programs own code is run. If such
a DLL uses any kind of TLS than that program will, by use of a TlsAlloc, get
a later TLS index.

Yep, you (and a quick test I just did) have convinced me: I really need to
use TlsAlloc and store the returned indices.

d*mn, I thought I found a nice shortcut ...


A related question: can I be certain that the "Arbitrary data slot" at
[FS:00000014h] in the Thread Information Block (TIB) is always free for the
creating process to use ? If so I can use that one instead of a TLS slot.

Regards,
Rudy Wieser
Post by Leo Davidson
Currently I get the feeling that I can just use TlsSetValue and TlsGetValue
without bothering to use TlsAlloc as long as I keep the slot-index lower
than TLS_MINIMUM_AVAILABLE, and that the "not opaque" remark to the TlsAlloc
function might (is it ?) only be valid when TlsFree is used.
That seems like a bad idea. How do you know some other DLL is not
already using the TLS index you choose for its own data?

The purpose of TlsAlloc is to obtain an index that nobody else is
using (assuming that everyone is well-behaved and uses TlsAlloc, of
course).

(You may not be loading other DLLs explicitly but they can be loaded
into your process implicitly anyway, and they may be using TLS to
store data.)

(And if it is your own process, do you need to use TLS at all? There
are usually better, easier, safer ways to associate data with a
thread. You usually only need to resort to TLS if your DLL is being
loaded into 3rd party processes that give you no other choice.)
Jeroen Mostert
2011-04-07 04:00:36 UTC
Permalink
Post by R.Wieser
A related question: can I be certain that the "Arbitrary data slot" at
[FS:00000014h] in the Thread Information Block (TIB) is always free for the
creating process to use ? If so I can use that one instead of a TLS slot.
No. The same reasoning applies as to using TLS indexes without marking them.
DLLs loaded into a process are part of the process. Any DLL can do anything
the main process code or any other DLL can do. There are no shortcuts where
you can safely squirrel away data in unconventional locations, without
running the risk of someone else having the same clever idea. In fact, with
something as enticingly named as an "arbitrary data slot", this is
practically a guarantee.

What's your big issue with avoiding the proper channels anyway? If you are
the creating process, you are at perfect liberty to communicate data to your
thread in any number of safe, easy ways.
--
J.
R.Wieser
2011-04-07 08:04:46 UTC
Permalink
Hell Jeroen,
There are no shortcuts where you can safely squirrel away
data in unconventional locations, without running the risk
of someone else having the same clever idea
Does it not, by your reasoning, mean that *noone* can use that space
(without a chance that some (other) DLL has the same idea) ? If so, why
than is it there at all ?
If you are the creating process, you are at perfect liberty to
communicate data to your thread in any number of safe,
easy ways.
I think you misunderstood the problem. I need to store thread-global
variables, to be retrieved in any function called by such a thread (like,
but not only, the handle of that threads main window).

Communication from the parent-process to those threads or between threads
is, as far as I can see, something quite different.

Currently I would do for the storage of a single dataword, as it can be used
to point to whatever thread-local data I need (on stack or alloc'ed) ...

Regards,
Rudy Wieser
Post by R.Wieser
A related question: can I be certain that the "Arbitrary data slot" at
[FS:00000014h] in the Thread Information Block (TIB) is always free for the
creating process to use ? If so I can use that one instead of a TLS slot.
No. The same reasoning applies as to using TLS indexes without marking them.
DLLs loaded into a process are part of the process. Any DLL can do anything
the main process code or any other DLL can do. There are no shortcuts where
you can safely squirrel away data in unconventional locations, without
running the risk of someone else having the same clever idea. In fact, with
something as enticingly named as an "arbitrary data slot", this is
practically a guarantee.
What's your big issue with avoiding the proper channels anyway? If you are
the creating process, you are at perfect liberty to communicate data to your
thread in any number of safe, easy ways.
--
J.
Loading...