liunx内核中的互斥自旋锁和读写自旋锁的实现详解
生活随笔
收集整理的這篇文章主要介紹了
liunx内核中的互斥自旋锁和读写自旋锁的实现详解
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
今天把這兩個(gè)鎖的內(nèi)核實(shí)現(xiàn)源碼重新捋了一遍,基于liunx2,6.0,直接粘注釋版:
核心文件,x86下實(shí)現(xiàn)的spinlock
rwlock.h核心文件,x86實(shí)現(xiàn):
/* include/asm-x86_64/rwlock.h** Helpers used by both rw spinlocks and rw semaphores.** Based in part on code from semaphore.h and* spinlock.h Copyright 1996 Linus Torvalds.** Copyright 1999 Red Hat, Inc.* Copyright 2001,2002 SuSE labs ** Written by Benjamin LaHaise.** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version* 2 of the License, or (at your option) any later version.*/ #ifndef _ASM_X86_64_RWLOCK_H #define _ASM_X86_64_RWLOCK_H#include <linux/stringify.h>#define RW_LOCK_BIAS 0x01000000 #define RW_LOCK_BIAS_STR "0x01000000"#define __build_read_lock_ptr(rw, helper) \asm volatile(LOCK "subl $1,(%0)" \ //獲取讀鎖就是嘗試在lock上減1,因?yàn)镽W_LOCK_BIAS是非常大的一個(gè)數(shù)// 只有有寫(xiě)鎖的時(shí)候會(huì)直接減去0x01000000變?yōu)?,其他時(shí)候是不可能小于0的,所以沒(méi)有寫(xiě)鎖的情況下,去搶占這個(gè)讀鎖是沒(méi)有問(wèn)題的"js 2f" \ //判斷符號(hào)位是否為1,也即是否為負(fù)數(shù),如果是負(fù)數(shù),那么說(shuō)明已經(jīng)有寫(xiě)鎖啦,那你只能去2位置了"1:" \LOCK_SECTION_START("") \"2: call " helper "" \ //調(diào)用helper方法,helper即為_(kāi)_read_lock_failed,下面把這段實(shí)現(xiàn)摘抄出來(lái)了,我沒(méi)有獲取到鎖,只好調(diào)用這個(gè)方法"jmp 1b" \LOCK_SECTION_END \::"a" (rw) : "memory") //a:將輸入變量放入eax//這段代碼是從i386的semaphore下摘出來(lái)的asm("__read_lock_failed:"LOCK "incl (%eax)"//原子性增加eax寄存器中的值(也就是lock變量的值)"1: rep; nop" //進(jìn)行空操作,耗掉一點(diǎn)點(diǎn)時(shí)間"cmpl $1,(%eax)"// cmp影響符號(hào)位,lock變量和1相減如果是負(fù)數(shù),符號(hào)位為1"js 1b" //如果是負(fù)數(shù)那么就去1重新比較,直到可以獲得讀鎖LOCK "decl (%eax)"//說(shuō)明eax也就是lock大于等于1,進(jìn)行相減再次判斷是否為負(fù)數(shù),因?yàn)榭赡軆蓚€(gè)線程同時(shí)走這一步,嚴(yán)謹(jǐn)!!!!!"js __read_lock_failed"//負(fù)數(shù)說(shuō)明又沒(méi)搶到,繼續(xù)循環(huán)吧"ret"//搶到了,返回);#define __build_read_lock_const(rw, helper) \asm volatile(LOCK "subl $1,%0\n\t" \"js 2f\n" \"1:\n" \LOCK_SECTION_START("") \"2:\tpushq %%rax\n\t" \"leaq %0,%%rax\n\t" \"call " helper "\n\t" \"popq %%rax\n\t" \"jmp 1b\n" \LOCK_SECTION_END \:"=m" (*((volatile int *)rw))::"memory")#define __build_read_lock(rw, helper) do { \if (__builtin_constant_p(rw)) \__build_read_lock_const(rw, helper); \else \__build_read_lock_ptr(rw, helper); \//走這里} while (0)#define __build_write_lock_ptr(rw, helper) \asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)" \ //核心,寫(xiě)鎖只能有一個(gè),上來(lái)直接把那個(gè)大數(shù)減完了"jnz 2f" \ //看是否為0,不為0說(shuō)明絕對(duì)有讀鎖在占著,直接失敗去2處forward"1:" \LOCK_SECTION_START("") \"2: call " helper "" \同讀鎖邏輯,截取helper如下"jmp 1b" \LOCK_SECTION_END \::"a" (rw) : "memory")//這段代碼是從i386的semaphore下摘出來(lái)的asm("__write_lock_failed:"LOCK "addl $" RW_LOCK_BIAS_STR ",(%eax)" //大同小異,先加后減"1: rep; nop\n\t""cmpl $" RW_LOCK_BIAS_STR ",(%eax)""jne 1b"LOCK "subl $" RW_LOCK_BIAS_STR ",(%eax)""jnz __write_lock_failed""ret");#define __build_write_lock_const(rw, helper) \asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \"jnz 2f\n" \"1:\n" \LOCK_SECTION_START("") \"2:\tpushq %%rax\n\t" \"leaq %0,%%rax\n\t" \"call " helper "\n\t" \"popq %%rax\n\t" \"jmp 1b\n" \LOCK_SECTION_END \:"=m" (*((volatile long *)rw))::"memory")#define __build_write_lock(rw, helper) do { \if (__builtin_constant_p(rw)) \__build_write_lock_const(rw, helper); \else \__build_write_lock_ptr(rw, helper); \ //上讀鎖走這里} while (0)#endif看注釋可以很容易理解。
總結(jié)
以上是生活随笔為你收集整理的liunx内核中的互斥自旋锁和读写自旋锁的实现详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用线程自己join自己完成线程门栓
- 下一篇: getchar()函数的一些知识