Threads, Processes, IPC, and Synchronization |
Thread Local Storage (TLS) is the memory area that is available to every thread and is not accessible to other threads. Each thread can use it for storing its thread-specific information in it. The size of the TLS and the way it is accessed is operating system-dependent. Some times the scope of the TLS also differs from OS to OS. The POSIX standard has defined the way to access TLS and the size of TLS. Symbian OS is not POSIX-compliant and has defined TLS in a different way.
Thread local storage is a single machine word (4 bytes) of static writable memory. The scope of this machine word is the thread, which means that there is one word per thread. The word is accessible only to code running in a DLL. Generally, this word is almost always used to hold a pointer to the allocated memory; this makes the allocated memory available to all DLL code running on behalf of the same thread. The following summarizes the main points of TLS:
TLS or thread-specific data is the memory area that is specific to that thread. Any DLL or executable can use this. As the name indicates, it is data that is specific to the respective thread. TLS is provided in chunks of 4 bytes. Each such 4 bytes of chunk (memory space) is called a key. If a program needs TLS, then it has to create a key. Once a key is created, an ID (handle) is returned. Subsequently this ID should be used to read and write to the key.
Creating a key
The pthread_key_create() API creates a new key and returns the ID (handle). If one thread calls pthread_key_create(), then a key (4 bytes) is created in all the threads. The ID (handle) to access that key in all threads is the same (which is returned by this API). Hence, one thread can create a key and store the handle (ID) in a global variable and all the other threads can use the same handle to access their respective key. When the key is created, it is assigned to NULL in all the threads.
In addition to this, POSIX also defines an associating destructor routine to each key. The associated destructor routine is called when the thread is terminating and the key value is not NULL. Most of the time the key holds a pointer to an allocated memory. This needs to be freed when the thread is terminating. This freeing can be done from the destructor routine. A program can create a maximum of 128 or 256 keys in a process. This value is defined as PTHREAD_KEY_MAX in the pthread.h header file.
Reading from a key
The pthread_getspecific() API can be used to get the value of the key. It takes the handle (ID) of the key as an argument.
Writing to a key
pthread_setspecific() API can be used to set the value to a key. It takes the handle (ID) of the key as argument.
Freeing the key
The pthread_key_delete() API deletes the key in all the threads. Once the key is deleted, no thread should use the old handle to set and get the key value. All the above APIs are part of the libpthread library.
The following summarizes the main points of POSIX TLS :
It is important to know if the DLL is written on top of the Open C platform, so that both POSIX TLS as well as Symbian TLS techniques can be used. Both of these techniques work without failure.
#inlcude <pthread.h> #inlcude <stdio.h> #inlcude <stdlib.h> #inlcude <unistd.h> static pthread_key_t key; void *thread_func_1(void*) { void* rc2; pthread_setspecific(key, (void *)(200)); printf("Setting Thread_1 key value to %d\n", 200); sleep(5); rc2 = pthread_getspecific(key); printf("Getting Thread_1 key value %d\n", rc2); pthread_exit(0); return NULL; } void *thread_func_2(void*) { void* rc2; sleep(1); pthread_setspecific(key, (void *)(400)); printf("Setting Thread_2 key value to %d\n", 400); sleep(1); rc2 = pthread_getspecific(key); printf("Getting Thread_2 key value %d\n", rc2); pthread_exit(0); return NULL; } int main() { pthread_t new_th_1; pthread_t new_th_2; void* rc1; /* Create the key */ pthread_key_create(&key, NULL); /* Set the value for the main thread key */ pthread_setspecific(key, (void *)(100)); printf("Setting Main thread key value to %d\n", 100); /* Create 2 threads */ pthread_create(&new_th1_1, NULL, thread_func_1, NULL); pthread_create(&new_th1_2, NULL, thread_func_2, NULL); /* Wait for thread to end execution */ pthread_join(new_th_1, NULL); pthread_join(new_th_2, NULL); /* Get the value associated for the key in the main thread */ rc1 = pthread_getspecific(key); printf("Getting Main thread key value %d\n", rc1); sleep(10); return 0; }
The output is:
Setting Main thread key value to 100 Setting Thread_1 key value to 200 Setting Thread_2 key value to 400 Getting Thread_2 key value 400 Getting Thread_1 key value 200 Getting Main thread key value 100
©Nokia 2007 |