TLS: Local TLS storage for threads

Source: Internet
Author: User
Tags define local

Local thread storage TLS

 

The local variables defined in the stack are safe for multithreading because different threads have their own stacks. Generally, the defined global variables can be read and written by all threads, so that they are not thread-safe. to ensure security, it is necessary to lock mutex access. What is Thread Local Storage (TLS), simply put, is a variable (usually a pointer pointing to a specific type), each thread has a copy, in the program, you can access each other in the same way (for example, using the same variable name or calling tlsgetvalue). Since there are copies, the interaction in the natural thread does not affect each other. For example, if one person is cloned from three, one of them is chopped and the other two are not hurt.

The VC compiler can implicitly define local variables of a thread, as long as the _ declspec (thread) prefix is added during definition. For example

_ Declspec (thread) int iglobal_1 = 1;
_ Declspec (thread) Double iglobal_2 = 2.0;
Iglobal_1 and iglobal_2 both have their own copies.

In addition, Windows provides several APIs to explicitly define local variables of a thread. These APIs are tlsalloc, tlsfree, tlssetvalue, and tlsgetvalue. Check the usage by yourself.

Okay. Now you can get into the question. Let's talk about its implementation.

 

It should be known that the operating system will use a structure to describe the thread, which is usually called the Teb (thread environment block). Each thread has a corresponding Teb. When switching the thread, it will also switch to different Teb. There is a pointer value pointing to the current Teb. When the thread is switched, the pointer value is changed. In this way, the thread-related values can be retrieved from the pointer value. In Windows, this thread pointer value is placed in the FS register.

What are some variables in Teb? Of course it is a thread-related variable. More specific information for yourself. The variable is a pointer to the thread TLS array. Called _ tls_array, this array can be used to manage thread-related data. The _ tls_array _ pointer is at the Teb offset 0x2 h in windows. Combined with the above, we can see mov ECx, dowrd ptr fs: [2ch], we should know that it is the _ tls_array pointer of the current thread and put it in the ECX register.

Now, we can get their own _ tls_array in different threads. At this time, we need to access the elements of the array, and the index is poor. Now, let's look at tlsalloc. Do you know what it means? No error occurs. In other words, assign an index number to me to indicate that the corresponding array item has been used. Tlsfree is to release the index number, indicating that the corresponding array item can be used again. Tlssetvalue, tlsgetvalue is to take an index and set a value or value to the corresponding array item.

Think about it. Why do I have the same index number and call tlsgetvalue in different threads? Because the starting pointer of the array has changed. In the computer, the base address + offset mode is displayed after the repeat operation. The base address remains unchanged, the offset is changed, and the value of the base address is different. The base address changes, the offset is unchanged, and the value of the base address is also different. This seems simple, but probably doesn't realize it. For example, in C ++, different objects have variable M_a, which can have different values, because different objects have different base addresses (that is, this pointer ), why can they use the same code to access the variable M_a, because the relative offset of the variable M_a remains unchanged.

Return to TLS. The index number corresponds to an offset. Because thread switching causes the _ tls_array switching, the values can be different. In this way, an index number is allocated with tlsalloc. In all threads, the corresponding elements of _ tls_array belong to you, not the current thread. Again, when an index is allocated, the index items in the _ tls_array array of all threads have been allocated. There are five threads, and you can manage five grids, it is not just a grid of the current thread. Because the indexes are the same, you can use the small grids of these arrays in the same way. Now you have a small grid. You can put something in it. You can decide what to put. You can put a pointer, an integer, or a character. Because it is put by yourself, you can know what you mean, it is useful for you to obtain it. Here, another simple but easy-to-ignore problem occurs. What is stored in the memory? Number? It can be said yes, but it is more accurate to put the state, but this state can be encoded by numbers (anything can be encoded by numbers, as long as you know the decoding method, this string of numbers makes sense to you ). 2 bits can represent four States, 4 bits can represent 16 States, and 32 bits can represent 4G states.

In fact, we have already completed explicit TLS allocation, that is, calling tlsalloc and other methods. How can we implement implicit TLS allocation?

 

When tlsalloc is called for the first time and the return value is checked, 1 is returned. Why is it 1 instead of 0? Because 0 has already been used, who is using it? Compiler.
Definition
_ Declspec (thread) int iglobal_1 = 1;
_ Declspec (thread) Double iglobal_2 = 2.0;
A segment. TLS is generated, which contains the two data and is kept in the execution file. When the program runs, each thread copies. TLS. The 0 index number of thread _ tls_array is occupied, and the corresponding lattice contains a pointer to the data (that is, pointing to the allocated data ). For example, you can imagine that the above statement implicitly defines a structure.
Struct tls_data
{
Int iglobal_1;
Double iglobal_2;
};
When each thread is running, the new structure is generated. When tlssetvalue is used, the pointer is set to the position corresponding to the _ tls_array and 0 index of the thread. Because the offset values of different variables are different in the structure, the base address changes, the offset remains unchanged, and the corresponding tls_data structure of the thread is obtained, and the offset changes with the base address, you can access different variables.

Analyze
_ Declspec (thread) int iglobal = 1;

Int main ()
{
Int I = iglobal;
Return 0;
}
Assembly Code
MoV eax, [_ tls_index] // place the index in eax, usually 0
MoV ECx, dword ptr fs: [2ch] // place the _ tls_array pointer corresponding to the thread in ECx
MoV edX, dword ptr [ECx + eax * 4]
// Each cell has 4 bytes. The _ tls_array elements are extracted and placed in EDX. The elements in this array are our hypothetical tls_data structure pointer.
MoV eax, dword ptr [edX + 104 H] // Add the offset of the variable in the structure to get the iglobal variable value
MoV dword ptr [ebp-4], eax // place the iglobal variable value in the stack variable, that is, in I

Note that the iglobal offset is not 0 because some variables have been defined, such as the errno variable of the thread and the variable used by the strtok function.

In this case, the compiler takes out a lattice of _ tls_array, manages it by itself, and implements another TLS style. We can also use tlsalloc to retrieve an index, and use new to output another sub-array. The sub-array pointer is placed in the _ tls_array element. The real Data Pointer is placed in the sub-array. In this way, we can implement local thread storage as needed. Without occupying the index of multiple _ tls_array.

Let's discuss the allocation and release of indexes in the _ tls_array array. There must be some way to mark that index is allocated, and that index can be used. If _ tls_array must put a pointer, we can set the unallocated index element to null, the allocated non-null, and check the value from front to back, the index of the first null element is allocated. However, this method cannot be used because arrays do not necessarily contain pointers or integers. integers do not have invalid values. You can create a bool array of the same size as a flag, or use a bit to judge to replace the bool array. If necessary, you can also define your own structure for marking. However, there must be a way to differentiate the assigned index number from the unassigned index number.

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/complex_ OK /archive/2009/07/15/4351673.aspx

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.