• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數(shù)據(jù)加載中……

            原子操作

            在多進程(線程)訪問資源時,能夠確保所有其他的進程(線程)都不在同一時間內訪問相同的資源。

              原子操作:UPSMP的異同

              -----------------------------------------------------------

              原子操作是不可分割的,在執(zhí)行完畢不會被任何其它任務或事件中斷。在單處理器系統(tǒng)(UniProcessor)中,能夠在單條指令中完成的操作都可以認為是" 原子操作",因為中斷只能發(fā)生于指令之間。這也是某些CPU指令系統(tǒng)中引入了test_and_settest_and_clear等指令用于臨界資源互斥的原因。但是,在對稱多處理器(Symmetric Multi-Processor)結構中就不同了,由于系統(tǒng)中有多個處理器在獨立地運行,即使能在單條指令中完成的操作也有可能受到干擾。我們以decl (遞減指令)為例,這是一個典型的"讀-改-寫"過程,涉及兩次內存訪問。設想在不同CPU運行的兩個進程都在遞減某個計數(shù)值,可能發(fā)生的情況是:

              1 CPU A(CPU A上所運行的進程,以下同)從內存單元把當前計數(shù)值(2)裝載進它的寄存器中;

              2 CPU B從內存單元把當前計數(shù)值(2)裝載進它的寄存器中。

              3 CPU A在它的寄存器中將計數(shù)值遞減為1

              4 CPU B在它的寄存器中將計數(shù)值遞減為1

              5 CPU A把修改后的計數(shù)值(1)寫回內存單元。

              6 CPU B把修改后的計數(shù)值(1)寫回內存單元。

              我們看到,內存里的計數(shù)值應該是0,然而它卻是1。如果該計數(shù)值是一個共享資源的引用計數(shù),每個進程都在遞減后把該值與0進行比較,從而確定是否需要釋放該共享資源。這時,兩個進程都去掉了對該共享資源的引用,但沒有一個進程能夠釋放它--兩個進程都推斷出:計數(shù)值是1,共享資源仍然在被使用。

              原子性不可能由軟件單獨保證--必須需要硬件的支持,因此是和架構相關的。x86 平臺上,CPU提供了在指令執(zhí)行期間對總線加鎖的手段。CPU芯片上有一條引線#HLOCK pin,如果匯編語言的程序中在一條指令前面加上前綴"LOCK",經(jīng)過匯編以后的機器代碼就使CPU在執(zhí)行這條指令的時候把#HLOCK pin的電位拉低,持續(xù)到這條指令結束時放開,從而把總線鎖住,這樣同一總線上別的CPU就暫時不能通過總線訪問內存了,保證了這條指令在多處理器環(huán)境中的原子性。

              Linux內核中的原子操作

              -----------------------------------------------------------

              原子操作大部分使用匯編語言實現(xiàn),因為c語言并不能實現(xiàn)這樣的操作。

              * x86的原子操作實現(xiàn)代碼中,定義了LOCK宏,這個宏可以放在隨后的內聯(lián)匯編指令之前。如果是SMPLOCK宏被擴展為lock指令;否則被定義為空 -- CPU無需防止其它CPU的干擾,鎖內存總線完全是在浪費時間。

              #ifdef CONFIG_SMP

              #define LOCK "lock ; "

              #else

              #define LOCK ""

              #endif

              * typedef struct { volatile int counter; } atomic_t;

              在所有支持的體系結構上原子類型atomic_t都保存一個int值。在x86的某些處理器上,由于工作方式的原因,原子類型能夠保證的可用范圍只有24位。volatile是一個類型描述符,要求編譯器不要對其描述的對象作優(yōu)化處理,對它的讀寫都需要從內存中訪問。

              

              * #define ATOMIC_INIT(i) { (i) }

              用于在定義原子變量時,初始化為指定的值。如:

              static atomic_t count = ATOMIC_INIT(1);

              * static __inline__ void atomic_add(int i, atomic_t *v)

              ----------------------------------------

              將v指向的原子變量加上i。該函數(shù)不關心原子變量的新值,返回void類型。

              在下面的實現(xiàn)中,使用了帶有C/C++表達式的內聯(lián)匯編代碼,格式如下(參考《AT&T ASM Syntax)

              __asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modify);

              __asm__ __volatile__指示編譯器原封不動保留表達式中的匯編指令系列,不要考慮優(yōu)化處理。涉及的約束還包括:

              1. 等號約束(=):只能用于輸出操作表達式約束,說明括號內的左值表達式v->counterwrite-only的。

              2. 內存約束(m):表示使用不需要借助寄存器,直接使用內存方式進行輸入或輸出。

              3. 立即數(shù)約束(i):表示輸入表達式是一個立即數(shù)(整數(shù)),不需要借助任何寄存器。

              4. 寄存器約束(r):表示使用一個通用寄存器,由GCC%eax/%ax/%al%ebx/%bx/%bl%ecx/%cx/%cl%edx/%dx/%dl中選取一個合適的。

              {

              __asm__ __volatile__(

              LOCK "addl %1,%0"

              :"=m" (v->counter)

              :"ir" (i), "m" (v->counter));

              }

              * static __inline__ int atomic_sub_and_test(int i, atomic_t *v)

              ----------------------------------------

              從v 指向的原子變量減去i,并測試是否為0。若為0,返回真,否則返回假。由于x86subl指令會在結果為0時設置CPUzero標志位,而且這個標志位是CPU私有的,不會被其它CPU影響。因此,可以執(zhí)行一次加鎖的減操作,再根據(jù)CPUzero標志位來設置本地變量c,并相應返回。

              {

              unsigned char c;

              __asm__ __volatile__(

              LOCK "subl %2,%0; sete %1"

              :"=m" (v->counter), "=qm" (c)

              :"ir" (i), "m" (v->counter) : "memory");

              return c;

              }

              ------------------------------------

              #define atomic_read(v) ((v)->counter)

              讀取v指向的原子變量的值。由于該操作本身就是原子的,只需要一次內存訪問就能完成,因此定義為一個宏,并用C代碼實現(xiàn)。

              #define atomic_set(v,i) (((v)->counter) = (i))

              設置v指向的原子變量的值為i。由于該操作本身就是原子的,只需要一次內存訪問就能完成,因此定義為一個宏,并用C代碼實現(xiàn)。

              static __inline__ void atomic_sub(int i, atomic_t *v)

              從v指向的原子變量減去i

              static __inline__ void atomic_inc(atomic_t *v)

              遞增v指向的原子變量。

              static __inline__ void atomic_dec(atomic_t *v)

              遞減v指向的原子變量。

              static __inline__ int atomic_dec_and_test(atomic_t *v)

              遞減v指向的原子變量,并測試是否為0。若為0,返回真,否則返回假。

              static __inline__ int atomic_inc_and_test(atomic_t *v)

              遞增v指向的原子變量,并測試是否為0。若為0,返回真,否則返回假。

              static __inline__ int atomic_add_negative(int i, atomic_t *v)

              將v指向的原子變量加上i,并測試結果是否為負。若為負,返回真,否則返回假。這個操作用于實現(xiàn)semaphore

            posted on 2009-10-19 18:47 肥仔 閱讀(838) 評論(0)  編輯 收藏 引用 所屬分類: C++ 基礎

            一级做a爰片久久毛片免费陪| 久久久国产亚洲精品| 一本久久a久久精品综合香蕉| 久久国产亚洲精品麻豆| 国产精品久久午夜夜伦鲁鲁| 久久超碰97人人做人人爱| 久久天天躁狠狠躁夜夜avapp| 国产69精品久久久久APP下载| 婷婷久久精品国产| 久久久久亚洲av综合波多野结衣| 色诱久久av| 久久精品国产亚洲AV香蕉| 国产精品99久久久精品无码| 7777精品久久久大香线蕉| 久久久久久精品久久久久| 婷婷久久香蕉五月综合加勒比 | 久久狠狠高潮亚洲精品| 激情伊人五月天久久综合| 91久久福利国产成人精品| 久久综合一区二区无码| 久久婷婷国产综合精品| 色综合久久久久网| 欧美精品一区二区久久| 久久久噜噜噜久久中文字幕色伊伊 | 国产69精品久久久久APP下载 | 99久久99这里只有免费费精品| 久久综合九色综合精品| 久久中文字幕视频、最近更新| 亚洲中文久久精品无码ww16| 久久精品一区二区| 欧美精品国产综合久久| 欧美久久综合性欧美| 亚洲伊人久久大香线蕉综合图片| 久久精品男人影院| 久久精品国产2020| 久久精品国产色蜜蜜麻豆| 日韩人妻无码一区二区三区久久| 精品久久久久久无码人妻蜜桃| 亚洲av成人无码久久精品| 国内精品久久久久久久coent| 久久精品国产亚洲AV嫖农村妇女|