The complete amount and mutex of lock mechanism in Linux kernel
In the previous blog post, I analyzed the use of semaphores, read and write signals, and the source code implementation, and this post will discuss the use of completion and mutexes and some classic questions.
Viii. The amount of completion
The following discussion of the content of the completion amount, the first need to clarify the amount of completion expressed as an execution unit needs to wait for another execution unit to complete something behind the executable, it is a lightweight mechanism. In fact, it is designed to complete synchronization between processes, thus providing only a workaround to replace the synchronous signal, the initial value is initialized to 0. It is defined in Include\linux\completion.h.
8.1, for the execution of unit A, if the execution unit B does not execute the complete function, the execution unit A will sleep because the request is not process, until the complete function is called in the execution unit B, so the code b must wait until execution unit b finishes executing code c. This is similar to the semaphore synchronization mechanism, except that the calling function is different.
Figure 8.1 Example of the use of a complete amount
The following author will discuss its implementation mechanism. The author from the kernel to find out the relevant source code, in turn, such as 8.2 to Figure 8.5 shows. Since the Do_wait_for_common function in Figure 8.5 is implemented more, the approximate frame diagram of the truncated function is given.
Figure 8.2 Structure definition of completion amount
Figure 8.2 Shows the structure definition of the completion amount, the Donevariable is the object to be protected by the completion amount, and waitis the waiting queue for the process that requested the completion amount. as we can see from figure 8.3, when initialization is complete, the donevariable is initialized to 0, and the synchronization content is realized by comparing the signal volume, which can be found to be identical.
Figure 8.3 The kernel source of the complete amount
Coordination diagram8.1 In the completion of the source code, we found now for the execution unitA, it's done with the code now.a call wait_for_common function, this function of the source code implementation done variables, if done variable is not greater than 0, it has been in while loop. At this point, if the execution unit b Execute code c, execute complete function, at this time, the observation diagram 8.4 in the complete function implementation, you can find it done variable value 1. At this point, wait_for_common function will exit while cycle, while the Span lang= "en-us" xml:lang= "en-us" >done value minus 1 to indicate successful application completion.
Figure 8.4 The kernel source of the complete amount
Figure 8.5 The kernel source of the complete amount
At this point, the content of the completion amount is discussed here, overall, the content of the completion amount is relatively simple. The subsequent authors will discuss the use and implementation of mutex amounts.
Nine, mutual exclusion amount
The author will discuss the content of mutex. First of all, the proposed mutex is mainly due to the high cost of the process after using the semaphore. Mutexes provide two mechanisms, including classic mutexes and real-time mutex two, which are defined in file include\linux\mutex.h (Classic mutex ) and include\linux\rtmutex.h (real-time mutex ). , let's look at some of its specific content.
The content of the classic mutex is discussed first, and its structure is defined in 9.1. We focus on the variables of count,Wait_lock,wait_list and so on in the structure. is similar to the definition of read and write semaphores.
Figure 9.1 Structure definition of the classic mutex
In addition, about its usage and some of the previous locking mechanisms are actually similar, the specific function is to add the unlocked function to Mutex_lock and Mutex_unlock, and its internal source code implementation is to establish the atomic lock and spin lock related mechanisms, At the same time there are some aspects of queue maintenance, which we can see from its structure definition can be easily seen, here is not too much discussion, interested in the words can see the above hint of the two files.
Let's take a look at the contents of the real-time mutex, and before we introduce this, let's start by looking at an interesting question, the unrestricted priority reversal problem, which once caused the failure of the Mars probe in the United States (follow-up introduction).
The following is a concrete discussion of what is an unrestricted priority reversal problem, in general, the figure9.2 to Figure9.7 shows the process of the whole problem happening. First, there is currently an execution unitC acquires a mutex that is being executed in the protected critical section and is not intended to be rolled out within a short time. At this point, the "running" execution unit in the systemA applies for this mutex due to the execution unitC is using this mutex, soA can only waitC Finished, thoughThe priority of a is much higher thanC (how helpless). At this point, there is another execution unit B, which has a priority between A and C. Due to the occurrence of an outage of the system, the execution unit B directly preempted the C process and begins executing the critical section of the mutex. But this situation actually also preempted the execution unit A, although the execution unit A has a higher priority than the execution unit B (A is a tragedy). If execution Unit B continues, execution unit a waits longer, because execution unit c is preempted by execution unit B, so it can only wait for execution unit B to complete its operation. So it looks like execution unit B has a higher priority than execution unit a. This is what we call a no-limit priority reversal problem.
Figure 9.2 Execution Unit C Access critical section Figure 9.3 Execution Unit a wait for C to complete its operation
Figure 9.4 b preemption C and execution of the critical section diagram 9.5 b is executed in the critical section
Figure 9.6 b after execution c continue to perform critical section figure 9.7 a Final execution critical section
The following is a brief reference to the failure of the U.S. Mars probe: The1997-year-old U.S. Mars probe (which uses the VxWorks system ) encountered a priority reversal problem. First the Mars rover has an information bus, a high-priority bus task is responsible for the bus data access, access bus needs through a mutex (shared resources appear); There is a low-priority, not very frequent meteorological gathering task, it needs to write data on the bus, also need to access the mutex Finally, there is a medium-priority communication task that runs longer. Normally this system runs without problems, but one day, when the meteorological task obtains the mutual exclusion lock to the bus writes the data, an interrupt occurrence causes the communication task to be dispatched to be ready, the communication task has preempted the low priority meteorological task, but Wuqiaobuchengshu is, At this time the high-priority bus task is waiting for the meteorological task to write the data back to the mutex, but because the communication task preempted the CPU and the running time is longer, resulting in the meteorological task can not be CPU time to release the mutex, so that the original high-priority bus task can not be executed, The consequences of a bus task not being executed in time is considered by the Pathfinder to be a serious error, and finally the entire system is restarted. In fact, theVxWorks system allows for priority inheritance, but unfortunately engineers have stopped the function, making the Mars probe a tragedy.
Because the unlimited priority reversal problem cannot be solved by using the classic mutex, the reason is that the queue in the classic mutex is not implemented to queue the waiting process by priority. Real-time mutex in this case, we can simply look at its structure definition,9.8 shows.
Figure 9.8 Structure definition of real-time mutex
Since the classic mutex does not solve the waiting process priority queueing problem, so for real-time mutex, it is the implementation of the Wait_list implementation, see this variable is defined by the type of plist_head, it can be seen at a glance. In the plist_head list operand, it takes precedence inheritance relationships to wait for process queues to queue by process priority. Here the precedence inheritance is expressed as if the high-priority process is blocked on the mutex, which is currently owned by a low mutex, then the low-priority temporary elevation to high priority.
At this point, the content of the mutex is discussed here, after the above discussion, I believe that the reader of the content of the mutex has a better understanding of the following " big talk Linux kernel lock mechanism of the RCU, large kernel lock" will focus on the RCU mechanism of correlation analysis, Interested readers can continue to read the latter post. Due to the author's level limit, there are inevitably mistakes in the blog, readers are welcome to point out that we discuss each other and common progress.
Reprint Please specify source:http://blog.sina.com.cn/huangjiadong19880706