Atomic Operation and Synchronization Mechanism of Linux

Atomic Operation and Synchronization Mechanism of Linux


Concurrency
problems such as C language statement "count++;" are not optimized by the compiler to generate assembly code for multiple machine instructions to achieve.


Example:
Suppose the initial value of the count variable is 0. After process 1 executes "mov eax, [count]", the value of count is 0 in the register eax. At this time,
process 2 is scheduled for execution, preempting the control right of the CPU of process 1. Process 2 executes the assembly code of "count++;" and writes the accumulated count value
1 back to memory. Then, process 1 is scheduled for execution again, and CPU control returns to process 1. Process 1 continues to execute, the accumulated
value still 1, and it is written back to memory. Although process 1 and process 2 performed two "count++;" operations, the actual memory value of count is 1,
not 2!



Uniprocessor atomic operations
solve this problem by translating the "count++;" statement into a single-instruction operation.
The Intel x86 instruction set supports the inc operation of memory operands, so that the "count++;" operation can be done in one instruction. Because the context
switch is always after the execution of an instruction, the above-mentioned concurrency problem does not occur. For a single processor, a processor instruction
is an atomic operation.



Multiprocessors operate atomically
but in a multiprocessor environment, such as the SMP architecture, this conclusion no longer holds. We know that the execution process of the "inc [count]" instruction is divided into three steps:
1) Read count data from memory to cpu.
2) Accumulate the read value.
3) Write the modified value back to count memory.
This goes back to the situation similar to the previous concurrency problem, except that the topic of concurrency is no longer the process, but the processor.

The Intel x86 instruction set provides the instruction prefix lock to lock the front-side serial bus (FSB), which ensures that the instruction execution will not be interfered by other processors.
After using the lock instruction prefix, concurrent access (read/write) to count memory between processors is prohibited, thus ensuring the atomicity of the instruction.



The atomic operation of
arm is implemented in the instruction set of arm, and there is no instruction prefix lock, so how to complete the atomic operation?
Before ARMv6, the swp instruction completed atomic data exchange by locking the bus, but it affected system performance. After ARMv6, the ldrex
and strex instruction pairs are generally used to replace the function of the swp instruction.



Atomic operations in spinlocks
	1:
	lock   decb [lock->slock]
	jus 3
	2:
	rep nop
	cmpb   $0, [lock->slock]
	day 2
	jmp    1
	3:


The initial value of the lock->slock field is 1, and the value is 0 after the atomic operation decb is performed. If the sign bit is 0, execute the jns instruction to jump to 3 to complete the spin lock.

When applying for the spin lock again, the lock->slock value is -1 after the atomic operation decb is performed. The sign bit is 1, and the jns instruction is not executed. Enter label 2, execute a set of
nop instructions, and compare whether lock->slock is less than or equal to 0. If it is less than or equal to 0, return to label 2 for loop (spin). Otherwise, jump to label 1 to apply for the
spin lock again until the application is successful.

When the spin lock is released, lock->slock is set to 1, which ensures that other processes can obtain the spin lock.



Atomic operation
in semaphore The application operation of semaphore is realized by the function down
	lock   decl [sem->count]
	js 2
	1:
	<========== another section ==========>
	2:
	lea    [sem->count], eax
	call   __down_failed
	jmp 1


The sem->count of a semaphore is generally initialized to a positive integer. When applying for a semaphore, the atomic operation decl is performed, and sem->count is decremented by 1. If the value is reduced to a negative number
(the sign bit is 1), jump to label 2 in another segment, otherwise the application for the semaphore is successful.

Label 2 is compiled into another segment. After entering label 2, execute the lea instruction to take out the address of sem->count, put it in the eax register as a parameter, and then call the function
__down_failed to indicate that the semaphore application failed, and the process joins the waiting queue. Finally jump back to label 1 to end the semaphore application.


The release operation of the semaphore is realized by the function up.
	lock   incl sem->count
	day 2
	1:
	<========== another section ==========>
	2:
	lea    [sem->count], eax
	call   __up_wakeup
	jmp    1


When releasing the semaphore, perform the atomic operation incl to add 1 to sem->count. If the value is less than or equal to 0, it means that the process waiting for the queue to be blocked needs to wake up and jump to label 2,
otherwise the semaphore is released successfully.

Label 2 is compiled into another segment. After entering label 2, execute the lea instruction to take out the address of sem->count, put it in the eax register as a parameter, and then call the function __up_wakeup to
wake up the process waiting for the queue. Finally jump back to label 1 to end the semaphore release.

Example:

code 1 (low priority) (thread 1)
code 1down
code 1down processing code
code 1up


code 2 (high priority) (thread 2)
code 2down
code 2down processing code
code 2up

analysis:
run code 1down processing when code 1down is successful Code, (if code 2 just runs to code 2down, it is suspended because it does not get the semaphore), code 1 finishes processing
code 1down processing code, and when code 1up arrives, it will see if there are other threads waiting for the semaphore (thread 2 Waiting), so the system resumes thread 2 to run, runs
code 2down to process the code, and then runs to code
2up , and exits until thread 2 no longer runs when it finds out When the next code starts, it runs code 1 and other code until it is suspended again.


Original reference: http://www.cnblogs.com/fanzhidongyzby/p/3654855.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326524903&siteId=291194637