轉自:http://blog.csdn.net/zqy2000zqy/article/details/1137878
read_lock()和write_lock()的流程說明如下:
鎖變數的初值為RW_LOCK_UNLOCKED(0x01000000),鎖變數為正時為未鎖狀態,反之為上鎖狀態。
read_lock()對鎖變數減1,如果結果為負,則說明已被某個write_lock()上鎖。然後read_lock()對鎖變數加1,釋 放read_lock狀態,接著等待鎖變數的值變為1;一旦鎖變數變為1,read_lock()再次對鎖變數減1 ,如果非負則成功,否則重複上述過程。
write_lock()對鎖變數減0x01000000,如果結果非零,則說明已被write_lock()或read_lock()上鎖。然 後write_lock()對鎖變數加0x01000000,釋放write_lock()狀態,接著等待鎖變數的值變為0x01000000;一旦鎖變 量變為0x01000000,write_lock()再次對鎖變數減0x01000000,如果為零則成功,否則重複上述過程。
read_lock(&mr_rwlock);
write_lock(&mr_rwlock);
deadlocks as the write lock spins, waiting for all readers to release the lockincluding yourself. If you ever need to write, obtain the write lock from the very start. If the line between your readers and writers is muddled, it might be an indication that you
do not need to use reader-writer locks. In that case, a normal spin lock is optimal.
執行上面2行代碼的進程將阻塞到write_lock(&mr_rwlock); 因為mr_rwlock讀鎖沒有釋放
可以多個同時讀,但是讀-寫, , 寫-寫 都是 互斥的
原理和 spin_lock一樣
include/linux/spinlock.h 中定義了write_lock,由於不是SMP,所以定義如下 : 就是禁止搶佔就夠了,不會被別人搶到鎖
#define _write_lock(lock) /
do { /
preempt_disable(); /
_raw_write_lock(lock); /
__acquire(lock); /
} while(0)
#define _raw_write_lock(lock) do { (void)(lock); } while(0)
arm代碼 (自由CONFIG_SMP時候才會用到)
static inline void _raw_spin_lock(spinlock_t *lock)
{
unsigned long tmp;
igned long tmp, tmp2;
__asm__ __volatile__(
"1: ldrex %0, [%2]/n"
" adds %0, %0, #1/n"
" strexpl %1, %0, [%2]/n"
" rsbpls %0, %1, #0/n"
" bmi 1b"
: "=&r" (tmp), "=&r" (tmp2)
: "r" (&rw->lock)
: "cc", "memory");
}
static inline void _raw_write_lock(rwlock_t *rw)
{
unsigned long tmp;
__asm__ __volatile__(
"1: ldrex %0, [%1]/n"
" teq %0, #0/n"
" strexeq %0, %2, [%1]/n"
" teq %0, #0/n"
" bne 1b"
: "=&r" (tmp)
: "r" (&rw->lock), "r" (0x80000000)
: "cc", "memory");
}
static inline void _raw_read_lock(rwlock_t *rw)
{
unsigned long tmp, tmp2;
__asm__ __volatile__(
"1: ldrex %0, [%2]/n"
" adds %0, %0, #1/n"
" strexpl %1, %0, [%2]/n"
" rsbpls %0, %1, #0/n"
" bmi 1b"
: "=&r" (tmp), "=&r" (tmp2)
: "r" (&rw->lock)
: "cc", "memory");
}
都是用原子操作指令
原子操作和以上也類似 :
static inline void atomic_set(atomic_t *v, int i)
{
unsigned long tmp;
__asm__ __volatile__("@ atomic_set/n"
"1: ldrex %0, [%1]/n"
" strex %0, %2, [%1]/n"
" teq %0, #0/n"
" bne 1b"
: "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
}