Saturday, February 12, 2011

Thread Local Storage

Thread Local Storage (TLS) is another area of memory management that defines memory on a per-thread basis. All threads of a process share its virtual address space, where the static and global variables are shared by all threads in the process, and the local variables of a function are unique to each thread that runs the function. With TLS, you can provide unique data for each thread that the process accesses by using a global index. One thread allocates the index, which can be used by the other threads to retrieve the unique data associated with the index.

The typical scenario in which TLS is used in Windows is within a dynamic-linked library (DLL), but this is not its only possible use. In the case of the DLL scenario, the use of TLS includes the following details:

  • When a DLL attaches to a process, the DLL uses TlsAlloc to allocate a TLS index. The DLL then allocates some dynamic storage to be used exclusively by the initial thread of the process. It uses the TLS index in a call to the TlsSetValue function to store the address in the TLS slot. This concludes the per-thread initialization for the initial thread of the process. The TLS index is stored in a global or static variable of the DLL.

  • Each time the DLL attaches to a new thread of the process, the DLL allocates some dynamic storage for the new thread and uses the TLS index in a call to TlsSetValue to store the address in the TLS slot. This concludes the per-thread initialization for the new thread.

  • Each time an initialized thread makes a DLL call requiring the data in its dynamic storage, the DLL uses the TLS index in a call to TlsGetValue to retrieve the address of the dynamic storage for that thread.

The following functions are used to manage TLS in UNIX and Windows:

  • Allocating memory. In the Windows environment, the TlsAlloc function allocates a TLS index. A TLS index is used by a thread to store and retrieve values that are local to the thread. The minimum number of indexes available to each process is defined by TLS_MINIMUM_AVAILABLE. TLS indexes are not valid across process boundaries. The prototype of the function is as follows:

    DWORD TlsAlloc(void);

    In the UNIX environment, pthread_key_create creates a thread-specific data key visible to all the threads in the process. Upon key creation, the value NULL is associated with the new key in all active threads. An optional destructor function may be associated with each key value. The prototype of the function is as follows:

    Note: The line has been split into multiple lines for readability.However, while trying it out on a system you must enter it as one line without breaks.

    int pthread_key_create(pthread_key_t *key,
  •                        void   (*destructor, void*));
  • Deleting memory. In the Windows environment, TlsFree releases a TLS index. This, however, does not release the data allocated and set in the TLS index slot. The prototype of the function is as follows:

    BOOL TlsFree(DWORD dwTlsIndex);

    In the UNIX environment, the pthread_key_delete function deletes the thread-specific data key.

    int pthread_key_delete(pthread_key_t key);
  • Storing a value. In the Windows environment, the TlsSetValue function stores memory in a TLS index. The prototype of the function is as follows:

    BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue);

    In the UNIX environment, the pthread_setspecific function associates a thread-specific value with the key. The prototype of the function is as follows:

    int pthread_setspecific(pthread_key_t key, const void *value);

  • Retrieving a value. In the Windows environment, the TlsGetValue function returns a memory element stored in a specified TLS index. The prototype of the function is as follows:

    LPVOID TlsGetValue(DWORD dwTlsIndex);

    In the UNIX environment, the pthread_getspecific function returns the values currently bound to the specific key. The prototype of the function is as follows:

    void *pthread_getspecific(pthread_key_t key);

Note Additional information is available at
http://msdn.microsoft.com/library/en-us/winprog/winprog/windows_api_reference.asp.

Thread Local Storage (TLS) Example

The following section shows a portion of an example application. It illustrates allocation and access to a memory space on a per-thread basis. First, the main thread of the process allocates a memory slot. The memory slot is then accessed and modified by a child thread. If several instances of the thread are active, each thread procedure will have a unique TLS index value to ensure the separation and isolation of data and state.

UNIX example: Using TLS with pthread library

#include  #include  #include  int main(void) 
{
pthread_key_t k1;
int ret;
int val = 100;
int *pval = NULL;
ret = pthread_key_create(&k1, NULL);
if (ret)
{
printf("pthread_key_create: %s\n", strerror(ret));
return -1;
}
ret = pthread_setspecific(k1, (void *) &val);
if (ret)
{
printf("pthread_setspecific: %s\n",
strerror(ret));
return -2;
}
pval = (int*)pthread_getspecific(k1);
if(pval == NULL)
{
printf("pthred_getspecific: NULL returned");
return -3;
}
printf("pthread_getspecific value: %d\n",*pval);
ret = pthread_key_delete(k1);
if (ret)
{
printf("pthread_key_delete: %s\n", strerror(ret));
return -4;
}
return 0;
}

No comments:

Post a Comment