Make a brief note in case you forget.
The reason we need to synchronize is that we have concurrent access to shared resources. The code snippet that we will access or manipulate the shared resource is called a "critical section", which is called a "race condition" if the two execution threads are executing simultaneously in the same critical section. Here the term execution thread refers to any code instance that is executing, such as a process executed in the kernel, an interrupt handler, or a kernel thread.
To give a simple example, i++ operation. The operation can be converted to the following sequence of machine instructions:
1. Get the value of the current variable I and save it to a register.
2. Add the value of the register to 1.
3. Write the new value of I back into memory.
When two threads enter this critical section at the same time, if I initial value is 7, we expect to do the following:
Thread 1 Thread 2
Get I (7) --
Add I (7->8)--
Write back I (8) --
-- Get I (8)
- - Increase I (8->9)
--Write back I (9)
However the implementation may be:
Thread 1 Thread 2
Get I (7) Get I (7)
Add I (7->8)--
--Increase I (7->8)
Write back I (8)--
--Write back I (8)
As described above, concurrent access to shared resources, the I value may appear as 8, resulting in unexpected functionality.
Several methods and interfaces are available in the Linux kernel to address the above problems.
1. Atomic Access
That is, atomic execution obtains I, adds I, and writes back I 3 instructions. Examples of related interfaces are as follows:
#include <linux/types.h>
typedef struct {
volatile int counter;
} atomic_t;
#include <asm/atomic.h>
atomic_t v = atomic_init (0); /* Define V and initialize to 0 */
Atomic_set (&v, 4); /* v = 4 (atomic) */
Atomic_add (2, &v); /* v = v+2 = 6 (atomic) */
Atomic_inc (&V); /* v = v+1 =7 (atomic) */
Of course, only a small number of operations are shown here, more reference man manual.
2. Spin Lock
Treat a critical section as a room and treat the execution thread as a person.
The spin lock means that when thread a enters the room (the critical section), it is locked. At this point, the execution thread B came to the door, and found that it was locked, waiting at the door to a lock out.
One key message here is "Wait", which consumes a lot of CPU time, so the execution thread holding the spin lock should be as short as possible. Doing so can cause performance problems.
The interface definition associated with the spin lock is in <linux/spinlock.h>, and its basic use is as follows:
Define_spinlock (Mr_lock);
Spin_lock (&mr_lock);
/* Critical section ... */
Spin_unloc (&mr_lock);
3. Signal Volume
Or the analogy between the room and the person above, the semaphore is also a kind of lock.
At this point, the execution thread B comes to the door and discovers that the gate has been locked. At this time it does not wait, but in the Doorway table registration, find a chair to sleep, so there is a benefit, CPU resources can be idle, rather than wasted waiting. A came out, found that the form has a name, according to the name to find B give him a punch. B Wake up and go to the room.
The specific implementation of the semaphore is defined in <asm/semaphore.h>, using the following example:
/* Declare a semaphore, named Mr_sem, for Semaphore count */
Static Declare_mutem (MR_SEM);
/* Try to get the semaphore */
if (down_interruptible (&mr_sem)) {
/* signal is received, the semaphore is not acquired */
}
/* Critical section ... */
Up (&mr_sem); /* Release a given semaphore */
Because the semaphore is in contention, sleep rather than wait, it is possible for Yu Yu to be held for a long time. Conversely, if the lock holding time is short, the use of semaphores is not appropriate due to the overhead of sleep, maintenance wait queues, and wake-up costs that may be longer than the total amount of time the lock is occupied.
"Reading Notes", "Linux kernel design and implementation" Kernel synchronization Introduction & Kernel Synchronization method