spin_lock and semaphore

spin_lock, mutex, semaphore, wait_queue是幾種常見的drive中用的同步與互斥用的方式linux

更多信息能夠參考:優化

https://www.kernel.org/pub/linux/kernel/people/rusty/kernel-locking/atom


一. spin_lock實現方式(linux 2.4)

code: include\asm-i386\Spinlock.h
spa

typedef struct {
    volatile unsigned int lock;  //使用volatile修飾,使得編譯器每次都從內存讀寫改值,而不是優化或者忽略,或者使用寄存器中的值
#if SPINLOCK_DEBUG
    unsigned magic;
#endif
} spinlock_t;
static inline void spin_lock(spinlock_t *lock)
{
    "\n1:\t" \
    "lock ; decb %0\n\t" \
    "js 2f\n" \
    ".section .text.lock,\"ax\"\n" \
    "2:\t" \
    "cmpb $0,%0\n\t" \
    "rep;nop\n\t" \
    "jle 2b\n\t" \
    "jmp 1b\n" \
    ".previous"
        :"=m" (lock->lock) : : "memory");
上述代碼簡略分析:code

1) x86執行Lock指令,在多核處理器中,該指令可以保證某一核可以獨佔性的處理內存:In a multiprocessor environment, the LOCK# signal insures that the processor has exclusive use of any shared memory while the signal is asserted.
隊列

2). lock->lock變量減1 (聲明中爲volatile變量,則每次都從內存中讀取該值,而後減1)ip

3). js 2f: 若是減1以後結果爲negative,則跳轉到2內存

4). 定義2的符號內容:比較lock->lock與0的大小編譯器

5). 若是小於0,則跳轉到2同步

6). 不然則跳轉到1中

上述執行過程當中對asm的指令解析仍是不徹底正確,可是總的邏輯應該是:執行dec lock->lock,比較是否等於0,若是不等於0,則一直比較,直到等於0,則返回。其中Lock指令應該只在後續的一個執行週期內有效。

從上述代碼中能夠看出,spin_lock應該適用於多核處理器中的臨界變量同步。

關鍵詞:忙等,多處理器

從kernel_locking中的一些關於spin_lock的使用信息:

  1. For kernels compiled withoutCONFIG_SMP, and withoutCONFIG_PREEMPTspinlocks do not exist at all.

  2. You should always test your locking code withCONFIG_SMPandCONFIG_PREEMPTenabled,


二. atomic_add

code: include\asm-i386\Spinlock.h (Linux 2.4)

static __inline__ void atomic_add(int i, atomic_t *v)
{
    __asm__ __volatile__(
        LOCK "addl %1,%0"
        :"=m" (v->counter)
        :"ir" (i), "m" (v->counter));
}
1. 先執行Lock指令,讓某一個processor惟一的使用某一內存

2. 執行addl指令

從這個能夠看出,這個原子加運算對於多核處理器很是有效,且是原子操做,不會被別的運算打斷(只有一條指令)

三. wait_queue_head

code: include\linux\Wait.h (linux 2.4)

struct __wait_queue_head {
    wq_lock_t lock;   //wq_lock_t should be spin_lock

    struct list_head task_list;
};
wait_queue_head表明一個等待隊列,其中經過spin_lock或者rwlock_t來完成對列表(list_head task_list)的原子訪問. 能夠想象全部的操做都是基於list_head與lock的一些操做。

四. semaphore

code: include\asm-i386\Semaphore.h

struct semaphore {
    atomic_t count;
    int sleepers;
    wait_queue_head_t wait;
#endif
};
從kernel-locking中獲得的信息:

  1. 若是數據結果僅僅在用戶空間使用,應該使用semaphore,而不是spin_lock


五. 關於Preemption:

non-preemption: 除了中斷,你能夠一直擁有CPU直到用完(ie. you had that CPU until you have it up, except for interrupts). Preemption是在2.5才加進來的。

Preemption: 在用戶空間,高優先級任務能夠打斷正在進行的低優先級任務,spin_lock能夠disable preemption.

相關文章
相關標籤/搜索