In-depth understanding of critical_section

Source: Internet
Author: User

The critical section is a mechanism to prevent multiple threads from executing a specific code section at the same time. This topic does not attract much attention, so people cannot fully understand it. When you need to track the performance of multi-thread processing in the code
Windows
The deep understanding of the central critical section is very useful. This article studies the principle of critical section in depth to reveal useful information in the process of finding deadlocks and verifying performance problems. It also contains a convenient utility that can display all critical sections and their current status.

 

In our many years of programming practices, the Win32 critical section has not received many "under
Hood "is very strange. Of course, you may have basic knowledge about the initialization and use of the critical section, but have you ever spent time researching
Critical_section
Structure? Some very meaningful good things in this structure are ignored for a long time. We will supplement this and introduce you to some meaningful skills that are useful for tracking imperceptible multi-threaded error handling. More importantly, use our
The mycriticalsections utility can understand how
Perform minor extensions to provide very useful features for debugging and Performance Tuning (to download the complete code, see the link at the top of this Article ).

 

To be honest, the authors often ignore the critical_section structure because its implementation in the following two major Win32 code libraries is very different: Microsoft
Windows 95 and Windows nth Si invade the leyun Street, and the zookeeper hooks the zookeeper.
XP), but there is no need to list them here. The key lies in that Windows XP has developed very well, and developers may soon stop
Supported operating systems. This is what we do in this article.

 

It is true that Microsoft. NET Framework is currently the most popular, but good legacy Win32 programming will not soon disappear. If you have existing
Win32 code, you will find that our tools and descriptions of the critical section are very useful. However, please note that we only discuss Windows NT and its subsequent versions, but it does not involve
This is very important for any related content.

 

Critical section: Brief Introduction

 

If you are very familiar with the critical section and can apply it without thinking about it, you can skip this section. Otherwise, read down to quickly review the content. If you are not familiar with the basic content, the content after this section does not make much sense.

 

A critical section is a lightweight mechanism that allows only one thread to execute a given code segment at a time. A critical section is usually used to modify global data (such as collection classes. Events, multi-user terminal execution programs, and semaphores are also used for multi-thread synchronization. However, unlike the critical section, they do not always execute control conversions to the kernel mode, which is expensive. As you can see later, to obtain a non-occupying critical section, you only need to make few modifications to the memory, which is very fast. It will only jump to kernel mode when trying to obtain an occupied critical section. The disadvantage of this lightweight feature is that the critical section can only be used to synchronize threads in the same process.

 

The critical section is represented by the rtl_critical_section structure defined in winnt. h. Because your c ++ Code usually declares
Critical_section type variable, so you may not understand this. After studying WINBASE. H, you will find that:

typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;

 

We will reveal the essence of the rtl_critical_section structure in a short time. At this point, the important problem lies in the critical_section (also known
Rtl_critical_section) is only a structure with accessible fields. These fields can be operated by the Kernel32 API.

 

Pass the critical section to initializecriticalsection
(Or, more accurately, when the address is passed), the critical section begins to exist. After initialization, the Code passes the critical section to entercriticalsection and
Leavecriticalsection API. After a thread is returned from entercriticalsection, all other calls
The entercriticalsection thread will be blocked until the first thread calls leavecriticalsection
So far. Finally, when this critical section is no longer needed, a good coding habit is to pass it to deletecriticalsection.

 

In ideal cases where the critical section is not used
Because it only reads and modifies the memory location in the user mode. Otherwise (an exception will be encountered later), the thread in the critical section is prevented from effectively completing this task without consuming additional
CPU
Cycle. The blocked threads wait in the inner-core mode. These threads cannot be scheduled before the owner of the critical section releases them. If multiple threads are blocked in one critical section, when the other thread releases the critical section, only one thread obtains the critical section.

 

In-depth study: rtl_critical_section Structure

 

Even if you have used the critical section in your daily work, it is very likely that you do not really know anything beyond the document. In fact, there are a lot of content that is very easy to grasp. For example, it is seldom known that the critical section of a process is stored in a linked list and can be enumerated. Actually, windbg
Yes! Locks
Command to list all critical partitions in the target process. The utility we will talk about later also applies the little-known feature of the critical section. To truly understand how the tool works, it is necessary to grasp the internal structure of the critical section. Keep this in mind. Now we are studying
The rtl_critical_section structure. For convenience, the structure is listed as follows:

struct RTL_CRITICAL_SECTION{PRTL_CRITICAL_SECTION_DEBUG DebugInfo;LONG LockCount;LONG RecursionCount;HANDLE OwningThread;HANDLE LockSemaphore;ULONG_PTR SpinCount;};

 

Each field is described in the following sections.

 

DebuginfoThis field contains a pointer pointing to the adjoint structure allocated by the system. The type of this structure is
Rtl_critical_section_debug. This structure contains more valuable information and is also defined in winnt. h. We will conduct further research on it later.

 

LockcountThis is the most important field in the critical section. It is initialized as a value-1; this value is equal to or greater than 0
The critical section is occupied. When it is not equal to-1, the owningthread field (This field is incorrectly defined in winnt. H-it should be DWORD rather
Handle) contains the thread ID that owns this critical section. The difference between this field and the value (recursioncount-1) indicates how many other threads are waiting to obtain the critical section.

 

Recursioncount
This field contains the number of times that the owner thread has obtained the critical section. If the value is zero, the next thread that attempts to obtain the critical section will succeed.

 

OwningthreadThis field contains the thread identifier of the thread currently occupying this critical section. This thread ID corresponds
The IDS returned by APIs such as getcurrentthreadid are the same.

 

Locksemaphore
The name of this field is incorrect. It is actually an auto-Reset event, not a signal. It is a kernel object handle used to notify the operating system that the critical section is currently idle. The operating system automatically creates a handle when a thread attempts to obtain the critical section for the first time but is blocked by another thread that already has the critical section. Should be called
Deletecriticalsection (it will issue a closehandle call that calls the event and release the debug structure if necessary). Otherwise, the resource will leak.

 

SpincountUsed only for multi-processor systems. Msdn
This field is described as follows: "In a multi-processor system, if this critical section is unavailable, the calling thread will rotate dwspincount before waiting for signals related to this critical section.
Times. If the critical section becomes available during the rotation operation, the call thread avoids waiting for the operation ." Rotating counting can provide better performance on a multi-processor computer because rotating in a loop is usually faster than waiting in kernel mode. This field defaults to zero, but can be used
Initializecriticalsectionandspincount API sets it to a different value.

 

Rtl_critical_section_debug Structure

 

We noticed that in the rtl_critical_section structure, the debuginfo field points to
Rtl_critical_section_debug structure, which is given as follows:

struct _RTL_CRITICAL_SECTION_DEBUG{WORD   Type;WORD   CreatorBackTraceIndex;RTL_CRITICAL_SECTION *CriticalSection;LIST_ENTRY ProcessLocksList;DWORD EntryCount;DWORD ContentionCount;DWORD Spare[ 2 ];}

 

This structure is allocated and initialized by initializecriticalsection. It can be composed of NTDLL
Pre-allocated array allocation within, can also be allocated by the process heap. Rtl_critical_section
This adjoint structure of includes a set of matching fields, which have different roles: two are difficult to understand, and the other two provide the key to understanding the structure of this critical blockchain, the two are set repeatedly, and the last two are not used.

 

The following describes the rtl_critical_section field.

 

TypeThis field is not used and is initialized to a value of 0.

 

CreatorbacktraceindexThis field is only used for diagnosis. In the Registry
HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution
Keyfield, globalflag, and stacktracedatabasesizeinmb under options \ yourprogram
Value. Note that these values are only displayed when you run the gflags command described later. When these registry values are correctly set, creatorbacktraceindex
Fields are filled by an index value used in the stack trace. Search for the phrase "create user mode stack trace" in the gflags document in msdn
Database "and" enlarging the user-mode stack trace Database ", you can find more information about this content.

 

CriticalsectionPoint to the rtl_critical_section related to this structure.Figure
1
This section describes the basic structure and rtl_critical_section and rtl_critical_section_debug.
Relationship with other participants in the event chain.

 



Figure 1 process of critical section


 

ProcesslockslistList_entry is a standard windows
Data structure. Rtl_critical_section_debug contains a part of the linked list, allowing you to traverse the critical section forward and backward. The utility provided later in this article describes how to use
The flink and blink fields move between Members in the linked list. Any device driver or study windows
Kernel users will be very familiar with this data structure.

 

Entrycount/contentioncount
These fields are incremented at the same time for the same reason. This is the number of threads that enter the waiting state because the critical zone cannot be obtained immediately. With lockcount and recursioncount
Different fields will never decrease.

 

Spares
These two fields are not used or even initialized (although these fields are cleared when the critical section structure is deleted ). It will be explained later that you can use these unused fields to save useful diagnostic values.

 

Even if rtl_critical_section_debug
Contains multiple fields, which is also a necessary component of the regular critical section structure. In fact, if the system happens to be unable to obtain this structure from the process heap, initializecriticalsection
Returns the lasterror result of status_no_memory, and then returns the incomplete structure of the critical section.

 

Critical Zone status

 

When the program runs, enters, and leaves the critical section, rtl_critical_section and rtl_critical_section_debug
Fields in the structure change according to the status of the critical section. These fields are
The bookkeeping code is updated, which will be seen later. If the program is multi-threaded and Its thread access is a public resource protected by the critical section, these States are more meaningful.

 

However, no matter how the code thread is used, there are two States. In the first case, if the lockcount field has a value not equal to-1
This critical section is occupied. The owningthread field contains the thread identifier of the thread that owns this critical section. In multi-threaded programs, lockcount and recursioncount
Indicates how many threads are blocked in the critical section. In the second case, if recursioncount is a value greater than 1
The number of times that the owner thread has re-obtained the critical section (which may not be necessary). The critical section can be called either by calling entercriticalsection or by calling
Tryentercriticalsection. Any value greater than 1 indicates that the Code may be less efficient or may cause errors in the future. For example
Class methods may re-enter the critical section without any need.

 

Note: In most cases, the lockcount and recursioncount fields contain their initial values-1 and
0. This is very important. In fact, for a single-threaded program, you cannot only check these fields to determine whether a critical section has been obtained. However, multithreading programs leave some marks to determine whether two or more threads attempt to have the same critical section at the same time.

 

One of the tags you can find is that the locksemaphore field contains a non-zero value even when the critical section is not occupied. This indicates that at a time, one or more threads are blocked in this critical section-
The event handle is used to notify the critical section that it has been released. One of the threads waiting for the critical section can now obtain the critical section and continue execution. Because OS
The event handle is automatically allocated when another thread is blocked in the critical section. If you forget to delete it when you no longer need the critical section, the locksemaphore field may cause resource leakage in the program.

 

Another State that may be encountered in a multithreaded program is entrycount and contentioncount.
The field contains a value greater than zero. The two fields store the number of times a thread is blocked in the critical section. Each time this event occurs, the two fields are incremented, but will not be decreased during the existence of the critical section. These fields can be used to indirectly determine the execution path and features of the program. For example, entrycount
When the critical section is very high, it means that the critical section has experienced a lot of competition and may become a potential bottleneck in the code execution process.

 

When studying a deadlock program, we will also find a State that does not seem to be capable of logical interpretation. The lockcount field of a frequently used critical section contains a value greater than-1.
It is owned by the thread, but the owningthread
The field is zero (so you cannot find out which thread causes the problem ). The testing program is multi-threaded, which can be used in single-processor computers and multi-processor computers. Although lockcount
It is different from other values in each operation, but this program is always deadlocked in the same critical section. We would like to know if any other developer has encountered an API call sequence that causes this status.

 

Build a better mouse trap

 

When we learn how to work in the critical section, we occasionally get some important discoveries. Using these discoveries, we can get a very good practical tool. The first discovery is processlockslist.
List_entry
Field, which reminds us that the critical section of the process may be enumerable. Another major discovery is that we know how to find the header of the critical section list. Another important discovery is that it can be written without any loss.
Spare of rtl_critical_section
Field (at least in all our tests ). We also found that some critical section routines of the system can be easily rewritten without modifying the source file.

 

Initially, we started with a simple program that checks all the critical sections in a process and lists their current states to see if they are available. If yes, find out which thread owns and how many threads are blocked in the critical section? This method is applicable
OS enthusiasts are more suitable, but it is not very useful for programmers who just want to understand their programs.

 

Even the "Hello World" program in the simplest Console mode has many critical sections. Most of them are created by system DLL such as USER32 or GDI32.
DLL rarely causes deadlocks or performance problems. We hope there is a way to filter out these critical sections, leaving only those critical sections of the Code concerned. Rtl_critical_section_debug
The spare field in the structure can do this well. One or two of them can be used to indicate that these critical sections are from user-written code, not from OS.

 

As a result, the next logical question is how to determine which critical sections are from your written code. Some readers may still remember libctiny. Lib in the under the hood column of Matt pietrek in December January 2001. One technique used by libctiny is a lib
File, which overrides the standard implementation of key visual c ++ runtime routines. Place the libctiny. Lib file in other lib of the linker line
Previously, the linker used this implementation instead of using a later version with the same name in the import/export library provided by Microsoft.

 

To apply similar techniques to the critical section, we create an alternative version of initializecriticalsection and its related import and export libraries. Place the Lib File
Before kernel32.lib, the linker will link our version, instead of the version in Kernel32. Initializecriticalsection
The implementation is shown in figure 2. This code is very simple in concept. It first calls the actual
Initializecriticalsection. Next, it obtains the Code address for calling initializecriticalsection and attaches it
One of the standby fields in the rtl_critical_section_debug structure. How can we determine the address of the called code? X86 call
The Command places the return address in the stack. The criticalsectionhelper code knows that the returned address is located at a known fixed position in the stack frame.

 

The actual result is: Any EXE or DLL correctly linked to criticalsectionhelper. Lib will be imported into our DLL
(Criticalsectionhelper. dll) and occupies the critical section where the standby field is applied. This makes things much easier. Now, our utility can simply traverse all the critical sections in the process and display only the critical section information with the correct reserved fields. So what is the price for this utility? Please wait for more information!

 

Because all your critical sections now contain the addresses when initializing them, the utility can identify each critical section by providing their initialization addresses. The original Code address itself is not so useful. Fortunately, dbghelp. dll
It makes it easy to convert code addresses to source files, row numbers, and function names. Even if a critical section does not have your signature, you can submit the address
Dbghelp. dll. If you declare it as a global variable, and if the symbol is available, you can determine the name of the critical section in the original source code. By the way, if you set
_ Nt_symbol_path environment variable, and set dbghelp to use its symbol Server Download function, so that dbghelp
To make full use of this function, we will get very good results.

 

Mycriticalsections Utility

 

We combined all these ideas and proposed the mycriticalsections program. Mycriticalsections
Is a command line program. You can see some options when running the program without parameters:

Syntax: MyCriticalSections <PID> [options]Options:/a = all critical sections/e = show only entered critical sections/v = verbose

 

The only required parameter is the program id or PID (in decimal format ). You can obtain the PID using multiple methods, but the simplest method may be through the task
Manager. If no other options are available, mycriticalsections lists the status of all critical zones from the code module.
Criticalsectionhelper. dll
Link to these code modules. If there is a symbol that can be used for this (some) module, the code will try to provide the name of the critical section and the location where it is initialized.

 

To view how mycriticalsections works, run the demo. exe program, which is included in the downloaded file. Demo. exe
Only two critical zones are initialized, and a thread enters these two critical zones. Figure 3 shows the result of running "mycriticalsections 2040" (2040 of which is demo. EXE's
PID ).

 

In this figure, two critical zones are listed. In this example, they are named csmain and yetanothercriticalsection. Each address: Line displays
The address and name of critical_section. The "initialized in" row contains the critical_section in which it is initialized.
Function name. The "initialized at" line of the Code displays the source file and the row number in the initialization function.

 

For the csmain critical section, you will see that the number of locks is 0, and the number of recursion is
1 indicates a critical section that has been obtained by a thread, and no other thread is waiting for this critical section. Because no thread is blocked in this critical section, the entry count field is 0.

 

Now, we can see that yetanothercriticalsection has three recursion numbers. You can quickly view the Demo code to see that the main thread calls
Entercriticalsection occurs three times, so the occurrence of the event is consistent with expectation. However, another second thread tries to obtain the critical section and has been blocked. Similarly, lockcount
The field is also 3. This output shows a waiting thread.

 

Mycriticalsections has some options that make it very useful for more brave explorers. /V
The switch displays more information for each critical section. The rotation number and lock signal fields are particularly important. You will often see NTDLL and other DLL
It has some non-zero-number critical partitions. If a thread is locked during the process of obtaining the critical zone, the locked signal field is a non-zero value. The/V Switch also displays
The content of the standby field in the rtl_critical_section_debug structure.

 

The/a switch displays all critical sections in the process, even if there is no criticalsectionhelper. dll signature. If you use
/A, please prepare for a large number of outputs. Real hackers want to use/a and/V at the same time to display the maximum details of all content in the process. One of the minor advantages of using/A is that NTDLL
In the left-side navigation pane. This critical section is occupied during the dllmain call and other important periods. Ldrploaderlock
It is one of the reasons for the formation of many apparently obscure deadlocks. (To enable mycriticalsection to correctly mark the ldrploaderlock instance
The PDB file of NTDLL is available .)

 

/E enables the program to only display the currently occupied critical section. When the/a switch is not used, only the critical section occupied in the Code is displayed (as indicated by the signature in the backup field ). Use/
When the switch is enabled, the system displays all the critical zones in the process, regardless of their source.

 

When do you want to run mycriticalsections?
What about it? A very clear time is when the program is deadlocked. Check the occupied critical section to see if anything surprised you. Even if the deadlocked program is running under the control of the debugger, you can use
Mycriticalsections.

 

Another way to use mycriticalsections is to adjust the performance of programs with a large number of threads. When blocking a frequently used, non-reentrant function in the debugger
Mycriticalsections. If many threads execute the same task, it is very easy to cause a situation where a thread is spent most of its time waiting for a frequently used critical section. If there are multiple frequently used critical zones, the consequences will be the same as the watering hose in the garden. To solve a contention problem, you only need to transfer the problem to the next critical section that is prone to blocking.

 

A good way to check which critical sections are most likely to cause contention is to set a breakpoint close to the end of the program. When a breakpoint occurs, run mycriticalsections and find
The critical section of the entry Count value. These critical sections cause most blocking and thread conversion.

 

Although mycriticalsections runs on Windows 2000 and later, you still need a newer version of dbghelp. dll-5.1
Version. This version is available in Windows XP. You can also obtain this version from other tools that use dbghelp. For example, debugging tools for Windows usually has the latest dbghelp. dll.

 

In-depth study of important critical zone routines

 

The last section is for brave readers who want to understand the inner story of the critical section. After carefully studying NTDLL, you can create a pseudo code for these routines and their support subroutines (see download
NTDLL (criticalsections). cpp ). The following Kernel32 APIs form public interfaces in the critical section:

InitializeCriticalSectionInitializeCriticalSectionAndSpinCountDeleteCriticalSectionTryEnterCriticalSectionEnterCriticalSectionLeaveCriticalSection

 

The first two APIs only focus on the ntdll api rtlinitializecriticalsection and
Rtlinitializecriticalsectionandspincount thin packing. All remaining routines are submitted to functions in Ntdll. In addition
The call of rtlinitializecriticalsection is another one around rtlinitializecriticalsectionandspincount
Call the thin package, and its rotation value is 0. When using the critical section, you actually use the following ntdll api behind the scenes:

RtlInitializeCriticalSectionAndSpinCountRtlEnterCriticalSectionRtlTryEnterCriticalSectionRtlLeaveCriticalSectionRtlDeleteCriticalSection

 

In this discussion, we use the Kernel32 name, because most Win32 programmers are more familiar with it.

 

Initializecriticalsectionandspincount is very easy to initialize the critical section. Rtl_critical_section
The field in the structure is assigned the start value. Similarly, assign the rtl_critical_section_debug structure and initialize it.
The return value in the rtllogstackbacktraces call is assigned to creatorbacktraceindex, and the link to the previous critical section is established.

 

By the way, creatorbacktraceindex generally receives 0 values. However, if there are gflags and umdh
Utility, you can enter the following command:

Gflags /i MyProgram.exe +ustGflags /i MyProgram.exe /tracedb 24

 

These commands Add the registry key under "Image File Execution options" of myprogram. Next execution of myprogram
This field receives a non-0 value. For more information, see the Knowledge Base Article q26834320.umdhtools.exe: How to Use umdh.exe to find memory.
Leaks ". The first 64 rtl_critical_section_debug
The structure is not allocated by the process heap, but an array from the. Data Section in Ntdll.

 

After the use of the critical section, deletecriticalsection (the section name is incorrect because it only deletes rtl_critical_section _
Debug. If an event is created because the thread is blocked when trying to obtain the critical section, zwclose is called to destroy the event. Next
After rtlcriticalsectionlock is protected (NTDLL protects its internal critical section list with a critical section-
You guessed it.) Clear the debugging information from the chain and update the linked list of the critical section to reflect the clearing operation on the information. The memory is filled by a null value. If the memory is obtained from the process heap
Rtlfreeheap will release its memory. Finally, fill in rtl_critical_section with zero.

 

Two APIs are available for resources protected by the critical section-tryentercriticalsection and
Entercriticalsection. If a thread needs to enter a critical section, but can execute useful work while the blocked resources become available
Tryentercriticalsection is the API you need. This routine tests whether the critical section is available. If the critical section is occupied, the Code returns the value.
False. This thread is given the opportunity to continue executing another task. Otherwise, the function is equivalent to entercriticalsection.

 

If this thread does need to own this resource before continuing, use entercriticalsection. In this case, cancel the spin count for a multi-processor computer.
Test. This routine is similar to tryentercriticalsection. no matter whether the critical section is idle or already owned by this thread, the bookkeeping of this critical section is adjusted. Note: The most important
Lockcount increments are completed by the x86 "Lock" prefix, which is very important. This ensures that only one CPU can modify the lockcount at a time.
Field. (In fact, the Win32 interlockedincrement API is only an add command with the same lock prefix .)

 

If the call thread cannot obtain the critical section immediately, call rtlpwaitforcriticalsection.
Place the thread in the waiting state. In a multi-processor system, entercriticalsection rotates the spincount
Number of times specified, and test the availability of the critical area in each loop access. If the critical section changes to idle during the cycle, the thread obtains the critical section and continues execution.

 

Rtlpwaitforcriticalsection
It may be the most complex and important process given here. This is not surprising, because if there is a deadlock and a critical section is involved, the use of the debugger to enter the process may display
At least one thread in the zwwaitforsingleobject call in rtlpwaitforcriticalsection.

 

As shown in the pseudo code, there is a bit of bookkeeping work in the rtlpwaitforcriticalsection, such as increasing entrycount and
Contentioncount field. But more importantly, it sends out the waiting for locksemaphore and the processing of the waiting result. By default, a null pointer is passed as the third parameter
Zwwaitforsingleobject
Call. The request Never times out. If timeout is allowed, a debugging message string is generated and the waiting starts again. If the process cannot be returned successfully from the waiting state, an error will occur to stop the process. Finally
When zwwaitforsingleobject is returned successfully
Return. The thread now has the critical section.

 

Rtlpwaitforcriticalsection must realize that the process is being shut down and is waiting for the loader to lock
(Ldrploaderlock) critical section. Rtlpwaitforcriticalsection mustNo
This thread is allowed to be blocked, but you must skip this wait and continue to close the thread.

 

Leavecriticalsection is not as complex as entercriticalsection. If you are downgrading recursioncount
If the result is not 0 (meaning that the thread still has the critical section), the routine will return in error_success status. This is why we need to use the appropriate number of leave calls to balance
Enter. If the count is 0, the owningthread field is cleared and the lockcount value is decreased. If there are other threads waiting, such as lockcount
Call rtlpunwaitcriticalsection if the value is greater than or equal to 0. Create this helper routine
Locksemaphore (if it does not exist) and sends this signal to remind the operating system that the thread has released the critical section. As part of the notification, wait for one of the threads to exit the waiting status and prepare for running.

 

Finally, how does the mycriticalsections program determine the start point of the critical blockchain? If you have access to NTDLL
To find and traverse the list. First, locate the rtlcriticalsectionlist symbol and clear its content (it points to the first
Rtl_critical_section_debug structure) and start traversing. However, not all systems have debugging symbols, rtlcriticalsectionlist
The variable address varies with Windows
. To provide a solution that works properly for all versions, we have designed the following tentative solutions. Observe the steps taken to start a process. The NTDLL
(These names are taken from the debug symbols of NTDLL ):

RtlCriticalSectionLockDeferedCriticalSection (this is the actual spelling!)LoaderLockFastPebLockRtlpCalloutEntryLockPMCritSectUMLogCritSectRtlpProcessHeapsListLock

 

Because the offset 0xa0 in the process environment block (peb) is checked
You can find the loader lock at the address, so it is easier to locate the start position of the chain. We read debugging information about the loader lock and traverse the two links along the chain to locate
Rtlcriticalsectionlock, at which point the first critical section of the chain is obtained. For more information about the methods, seeFigure 4.

 



Figure 4 initialization sequence


 

Summary

 

Almost all multi-threaded programs use the critical section. Sooner or later, you will encounter a critical section that deadlocks the code, and it is difficult to determine how to enter the current state. If you have a better understanding of the working principles of the critical section, this situation will not be As frustrating as it was when it first appeared. You can study a seemingly vague critical section and determine who owns it and other useful details. If you are willing to add our library to your linker line, you can easily obtain a large amount of information about the use of your program's critical section. By using unused fields in the critical section structure, our code can only isolate and name the critical section used by your module, and inform it of its accurate status.

 

Bold readers can easily expand our code to do more extraordinary work. For example
Intercept entercriticalsection and
Leavecriticalsection, which stores the last successful acquisition and release of the critical section. Similarly, the critsect dll has an easy-to-call
API, used to enumerate the critical sections in your own code. Using Windows Forms in. NET Framework, you can easily create a GUI version
Mycriticalsections. It is very likely to expand our code. We are very happy to see innovative methods found and created by other people.

 

For more information, see:
Global flag reference: Create Kernel Mode stack trace
Database
Gflags examples: enlarging the user-mode stack trace
Database
Under the Hood: reduce EXE and DLL size with libctiny. Lib

 

Matt pietrekIs a software architect and author. He works at the compuware/numbench lab and is named
Head architect of boundschecker and distributed analyzer products. He has created three books on Windows programming and isMsdn
Magazine
. His web site (http://www.wheaty.net) has FAQs and information about previous articles and columns.

 

Jay HilyardIs the boundschecker of the compuware/numbench lab.
The software engineer of the group. He, his wife, and their cats are new residents of the new State of New York. The contact information is [email protected] or the web site http://www.smidgeonsoft.com.

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.