Each thread gets its own storage slot. This makes it useful to store a thread specific value. The classic example is SetLastError(), GetLastError().
Code:
// On process intialization.
// Get an index to an available slot.
g_idxLastError = TlsAlloc();
void SetLastError(DWORD dwErr)
{
TlsSetValue(g_idxLastError, (LPVOID) dwErr);
}
DWORD GetLastError(void)
{
return (DWORD) TlsGetValue(g_idxLastError);
}
Now, consider how you would implement that functionality without some sort of thread local storage. Another example is being able to return a pointer to something in a thread safe manner. See gethostbyname(), etc.