ID: Q94804
The information in this article applies to:
- Microsoft Windows NT versions 3.1, 3.5, 3.51
- Microsoft Windows 95
Thread local storage (TLS) is a method by which each thread in a given process is given a location(s) in which to store thread-specific data.
Four functions exist for TLS: TlsAlloc(), TlsGetValue(), TlsSetValue(), and TlsFree(). These functions manipulate TLS indexes, which refer to storage areas for each thread in a process. A given index is valid only within the process that allocated it.
Note that the Visual C++ compiler supports an alternate syntax:
_declspec( thread )
which can be used in place of directly calling these APIs. Please see the
description of _declspec in the VC++ "Language and Run-time Help" helpfile
for more information.
A call to TlsAlloc() returns a global TLS index. This one TLS index is valid for every thread within the process that allocated it, and should therefore be saved in a global or static variable.
Thread local storage works as follows: when TlsAlloc() is called, every thread within the process has its own private DWORD-sized space reserved for it (in its stack space, but this is implementation-specific). However, only one TLS index is returned. This single TLS index may be used by each and every thread in the process to refer to the unique space that TlsAlloc() reserved for it.
For this reason, TlsAlloc() is often called only once. This is convenient for DLLs, which can distinguish between DLL_PROCESS_ATTACH (where the first process's thread is connecting to the DLL) and DLL_THREAD_ATTACH (subsequent threads of that process are attaching). For example, the first thread calls TlsAlloc() and stores the TLS index in a global or static variable, and every other thread that attaches to the DLL refers to the global variable to access their local storage space.
Although one TLS index is usually sufficient, a process may have up to TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than or equal to 64).
Once a TLS index has been allocated (and stored), the threads within the process may use it to set and retrieve values in their storage spaces. A thread may store any DWORD-sized value in its local storage (for example, a DWORD value, a pointer to some dynamically allocated memory, and so forth). The TlsSetValue() and TlsGetValue() APIs are used for this purpose.
A process should free TLS indexes with TlsFree() when it has finished using them. However, if any threads in the process have stored a pointer to dynamically allocated memory within their local storage spaces, it is important to free the memory or retrieve the pointer to it before freeing the TLS index, or it will be lost.
For more information, please see "Using Thread Local Storage" in the "Processes and Threads" overview in the "Win32 Programmer's Reference".
Thread A within a process calls TlsAlloc(), and stores the index returned in the global variable TlsIndex:
TlsIndex = TlsAlloc();
Thread A then allocates 100 bytes of dynamic memory, and stores it in its
local storage:
TlsSetValue( TlsIndex, malloc(100) );
Thread A creates thread B, which stores a handle to a window in its local
storage space referred to by TlsIndex.
TlsSetValue( TlsIndex, (LPVOID)hSomeWindow );
Note that TlsIndex refers to a different location when thread B uses it,
than when thread A uses it. Each thread has its own location referred to by
the same value in TlsIndex.
Thread B may terminate safely because it does not need to specifically free the value in its local storage.
Before thread A terminates, however, it must first free the dynamically allocated memory in its local storage
free( TlsGetValue( TlsIndex ) );
and then free the TLS index:
if ( !TlsFree( TlsIndex ) )
// TlsFree() failed. Handle error.
Additional query words:
Keywords : kbKernBase kbThread kbGrpKernBase
Last Reviewed: October 3, 1998