API

TLS (Thread Local Storage) 란 무엇인가?

디버그정 2008. 7. 30. 18:50
TLS (Thread Local Storage) 란 무엇인가? 프로그래밍(삽질)

2006/01/09 09:12

복사 http://blog.naver.com/process3/20020554547

 오늘은 앞으로 Dual(MultiCore) Core 프로그램이 더욱 중요해 질 것이다.  그래서 Thread 프로그램 중에서 기본적인 개념이 TLS(Thread Local Storage)에 대해서 알아 보자^^



Thread Local Storage

All threads of a process share its virtual address space. The local variables of a function are unique to each thread that runs the function. However, the static and global variables are shared by all threads in the process. With thread local storage (TLS), you can provide unique data for each thread that the process can access 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.

(의역:모든 프로세스 내의 스레드는 가상메모리를 공유한다. 당연히 모든 스레드는 static, global variable을 공유한다 즉,TLS는 각각 스레드만의 Index를 이용해서 메모리를 가진다.)


The constant TLS_MINIMUM_AVAILABLE defines the minimum number of TLS indexes available in each process. This minimum is guaranteed to be at least 64 for all systems. The limits are as follows:

System Limit
Windows Server 2003, Windows XP, and Windows 2000 1088 indexes per process
Windows Me/98 80 indexes per process
Windows NT and Windows 95 64 indexes per process


When the threads are created, the system allocates an array of LPVOID values for TLS, which are initialized to NULL. Before an index can be used, it must be allocated by one of the threads. Each thread stores its data for a TLS index in a TLS slot in the array. If the data associated with an index will fit in an LPVOID value, you can store the data directly in the TLS slot. However, if you are using a large number of indexes in this way, it is better to allocate separate storage, consolidate the data, and minimize the number of TLS slots in use.

The following diagram illustrates how TLS works.

(스레드가 생성되면 시스템(OS)는 TLS를 위해서 NULL 값으로 array를 초기화 한다. 그리고 이값을 스레드 에서 할당해서 사용하면 된다. 각각 스레드는 TLS Index를 이용해서 TLS Slot array에 값을 저장한다.)


사용자 삽입 이미지

The process has two threads, Thread 1 and Thread 2. It allocates two indexes for use with TLS, gdwTlsIndex1 and gdwTlsIndex2. Each thread allocates two memory blocks (one for each index) in which to store the data, and stores the pointers to these memory blocks in the corresponding TLS slots. To access the data associated with an index, the thread retrieves the pointer to the memory block from the TLS slot and stores it in the lpvData local variable.

(위 그림을 보면 2개의 스레드1, 스레드2가 각각 TLS인덱스를 사용하는 모습을 알수 있다. 각각의 스레드는 TLS slot 메모리 블럭(data 포인터)를 가지고 있다.)


(아래 예제는 DLL에서 TLS를 사용하는 방법이다...)

It is ideal to use TLS in a dynamic-link library (DLL). Use the following steps to implement TLS in a DLL:

  1. Declare a global variable to contain the TLS index. For example:
    static DWORD gdwTlsIndex;
  2. Use the TlsAlloc function during initialization to allocate the TLS index. For example, include the following call in the DllMain function during DLL_PROCESS_ATTACH:
    gdwTlsIndex = TlsAlloc();
  3. For each thread using the TLS index, allocate memory for the data, then use the TlsSetValue function to store the address of the memory block in the TLS slot associated with the index. For example, include the following code in your DllMain during DLL_THREAD_ATTACH:
    LPVOID lpvBuffer; lpvBuffer = (LPVOID) LocalAlloc(LPTR, 256); TlsSetValue(gdwTlsIndex, lpvBuffer);
  4. When a function requires access to the data associated with a TLS index, specify the index in a call to the TlsGetValue function. This retrieves the contents of the TLS slot for the calling thread, which in this case is a pointer to the memory block for the data. For example, include the following code in any of the functions in your DLL:
    LPVOID lpvData; lpvData = TlsGetValue(gdwTlsIndex);
  5. When each thread no longer needs to use a TLS index, it must free the memory whose pointer is stored in the TLS slot. When all threads have finished using a TLS index, use the TlsFree function to free the index. For example, use the following code in your DllMain during DLL_THREAD_DETACH:
    lpvBuffer = TlsGetValue(gdwTlsIndex); LocalFree((HLOCAL) lpvBuffer);

    and the following code during DLL_PROCESS_DETACH:

    TlsFree(gdwTlsIndex);

 

출처 : Windows Developer's BIBLE MSDN ->