"Linux Kernel design and implementation" notes--Introduction to Kernel synchronization __linux

Source: Internet
Author: User
Tags mutex semaphore
Related Concepts Competitive Conditions

Multiple thread of execution (process/thread/interrupt handler) accesses a shared resource concurrently (in parallel) because the execution order is different, resulting in a different result, called a competition condition (race condition)

Give an example to explain

#include <thread>
using namespace std;
int  i = 0;
void Thread1 () {
    //for (int x=0;x<100000;x++) 
    i++;
}
void Thread2 () {
    //for (int x=0;x<100000;x++) 
    i++;
}
int main () {
    std::thread T1 (thread1);
    Std::thread T2 (THREAD1);
    T1.join ();
    T2.join ();
    printf ("i =%d\n", i);
}

T1,T2 Two threads may have a competitive condition when executed concurrently (of course the probability of a competitive condition is low, but if you remove the annotation, the competition condition is very easy to happen)
i++: This statement typically requires 3 machine instructions

mov eax,i
INC EAX
mov eax,i

If executed in the following order, there is no problem, the printed I is 2

Thread 1 Thread 2
MOV Eax,i (i=0)
INC EAX
MOV Eax,i (I=1)
MOV Eax,i (I=1)
INC EAX
MOV Eax,i (i=2)

However, two threads are likely to be executed in the following order, and there will be competitive conditions, the printed I is 1

Thread 1 Thread 2
MOV Eax,i (i=0)
INC EAX
MOV Eax,i (i=0)
MOV Eax,i (I=1)
INC EAX
MOV Eax,i (I=1)

The critical area (critical section) is a code snippet that accesses and operates a shared resource, in the example of a two-thread i++ statement

to avoid competitive conditions, the critical zone must be executed atomically and cannot be interrupted until the execution is completed. Usually lock the critical area, use the semaphore, the condition variable, and so on, the simple operation in the example can also use the atomic variable. The understanding of atomic nature

The interpretation of atomicity in the general book cannot be interrupted until the execution is completed. How to understand this sentence, my personal understanding is: Atomic variable this, implemented using a lock bus, a number of related instructions are executed continuously; using a lock (spin lock/Sleep Lock), semaphore, condition variable/completion variable these are not to say that all the instructions in the critical section are executed continuously, and may be executed in the critical section half way, Because the scheduler is preempted or interrupted, the CPU does not continue to execute within the critical zone, which means the execution is interrupted.
But that still guarantees the avoidance of competitive conditions, the reason is that if a process outside of the interrupted process is scheduled, the process will have to access the critical section, the lock or semaphore, and so on "stop", is not into the critical area, until the original interrupted critical section execution, release lock/signal volume, etc. It is possible for other processes to enter the critical section. Cause of concurrency disruption: Interrupts can occur almost at any time asynchronously, and can interrupt currently executing code soft interrupts and Tasklet: The kernel can wake or schedule soft interrupts and tasklet at any time, interrupting code that is currently executing Kernel preemption: The Linux kernel is preemptive, so the kernel's tasks may be preempted by another task and synchronized with user space: processes that are executing in the kernel may sleep, waking the Scheduler
Sequence, thus dispatching a new user process to execute SMP, where two or more processors can simultaneously execute synchronization in the code kernel lock

In order to avoid competition conditions, the kernel provides several mechanisms for synchronization, the basic idea is to lock, the critical area mutually exclusive access, the semaphore can also support more than one thread concurrent access. Contention for Locks

The other thread is trying to acquire the lock when it is occupied. The higher the contention of the lock, the lower the performance of the system (locking reduces system performance, such as sleep locks, spin locks), but must be used to ensure correctness. To reduce the lock contention, the lock granularity should be as small as possible, that is, the critical area should be as small as possible. Introduction to several synchronization methods

Synchronization Method Main interface Notes
Atomic integer (32bit) operation atomic_t v;/* Definition v*/
atomic_t u = atomic_init (0);/* define U, initialize to 0*/
Atomic_set (&v, 4);/* v=4 *
Atomic_add (2, &v);/* v=v+2 *
Atomic_inc (&V);/* v=v+1 *
Atomic integer (64bit) operation Atomic64_t v;
Atomic bit operation unsigned long word = 0; To manipulate a normal pointer
Set_bit (0,&word); The No. 0 bit is set __set_bit in the form of a non-atomic operation
Set_bit (1,&word); The 1th bit is set Non-atomic operations are faster if atomic operations are not required
PRINTK ("%ul\n", word);//Print 3 "Linux kernel design and implementation" P147
Clear_bit (1,&word);/Clear 1th Place
Change_bit (0,&word)/reverse No. 0 Position
Spin lock Define_spinlock (Mr_lock); A spin lock can be located in a critical section only by one thread at a time
Spin_lock (&mr_lock); The protection mechanisms that are required to provide concurrent access for multiple processors
/* Critical Area * * Single processor, as a kernel to preempt whether the switch is turned on, if the kernel preemption is prohibited, compile-time spin lock will be completely removed from the kernel
Spin_unlock (&mr_lock); Self-rotating lock is not recursive
Spin lock and lower half part Lower half and process context share data/lower half and interrupt handler share data, need to lock The lower half can preempt the process context, and the interrupt handler can preempt the lower part
Read-Write Spin lock Define_rwlock (Mr_rwlock);
Read_lock (&mr_rwlock); shared by all readers
/* Critical section (read only) * *
Read_unlock (&mr_rwlock);
Write_lock (&mr_rwlock); The writer is mutually exclusive, the writer and the reader are mutually exclusive
/* Critical section (read/write) * *
Write_unlock (&mr_rwlock);
Signal Volume struct Semophore name; The contention thread sleeps, so the situation that the lock will be occupied for a long time
Sema_init (&name, Count); Using in the process context
Static Declare_mutex (name);
Init_mutex (SEM) Dynamic initialization of mutex signals
Static Declare_mutex (MR_SEM);
if (down_interruptible (&mr_sem)) {/* signal is received, semaphore not yet acquired/}
/* Critical Area * *
Up (&mr_sem);//releasing the given semaphore
Read and write signal volume Static Declare_rwsem (MR_RWSEM); Static definition
Init_rwsem (struct rw_semaphore *sem); Dynamic initialization
Down_read (&mr_rwsem);
/* Critical section (read only) * *
Up_read (&mr_rwsem);
Down_write (&mr_rwsem);
/* Critical section (read/write) * *
Up_write (&mr_rwsem);
Mutex Define_mutex (name); Sleep locks for handling mutexes
Mutex_init (&mutex); Dynamic initialization
Mutex_lock (&mutex) No recursive locking and unlocking.
/* Critical Area * * No more interruptions or lower half execution
Mutex_unlock (&mutex)
Complete variable Declare_completion (Mr_comp) Wait, know the mission is done, send a signal
Init_completion (); Dynamic creation
Wait for task to call Wait_for_completion ();
The task call that generated the event Complete ()//Send a signal to wake a specific event

About the large kernel lock blk, the content of sequential lock See "Linux Kernel Design and implementation" P160 prohibit preemption

Kernel preemption code uses a spin lock as a token for a non-preemption zone
You can disable preemption

More concise solution to the data access problem on each processor, GET_CPU () get the processor number, before returning the processor number will first shut down the kernel preemption

int CPU;
CPU = get_cpu;//Prohibit kernel preemption, set CPU to current CPU
//* For each CPU data operation */*
in giving kernel preemption, "CPU" can be changed, so no longer effective * * *
put_up ();
Order and Barriers

To ensure the order of the reason multiprocessor, hardware device synchronization problems, need to be in the program code in the specified order to read memory and write memory. When interacting with hardware, it is often necessary to ensure that given read operations are on multiple processors before other read/write operations, you may need to read data in the order in which they are written.

For efficiency, compilers (compiler Optimizations) and processors (unordered execution) may reorder read and write. All CPUs that may be reordered read-write are provided with machine instructions to ensure that they are executed sequentially. You can also instruct the compiler not to reorder the sequence of instructions around the point.
e.g.
May reorder
A=1;
b=2;
Impossible to reorder
A=1;
B=a; Explain the reason of the guarantee order by example

a=1,b=2

Thread 1 Thread 2
A=3;
MB ();
b=4; C=b;
RMB ();
D=a;

If there is no memory barrier, on some processors, C may accept a new value of B 4,d accepted a original value of 1 several methods

Full Interface List

Screenshot from "Linux Kernel Design and implementation" chapter 10th









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.