一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么指令集支持原子操作

電子工程師 ? 來(lái)源:技術(shù)讓夢(mèng)想更偉大 ? 作者:技術(shù)讓夢(mèng)想更偉大 ? 2022-08-02 11:48 ? 次閱讀

前言

這個(gè)是在面試的時(shí)候遇到的問題,當(dāng)時(shí)沒有答出來(lái)?;氐郊乙院蟛榱瞬?,整理記錄下來(lái)。 原問題:什么指令集支持原子操作?其原理是什么?如果考慮到全部的指令集,問題太大了,這里簡(jiǎn)化下。以X86和ARM為例。 原子操作是不可分割的操作,在執(zhí)行完畢時(shí)它不會(huì)被任何事件中斷。在單處理器系統(tǒng)(UniProcessor,簡(jiǎn)稱 UP)中,能夠在單條指令中完成的操作都可以認(rèn)為是原子操作,因?yàn)橹袛嘀荒馨l(fā)生在指令與指令之間。 比如,C語(yǔ)言代碼 8186aa7e-0e86-11ed-ba43-dac502259ad0.png ? 如果未經(jīng)優(yōu)化,有可能生成如下匯編: ? 819e654c-0e86-11ed-ba43-dac502259ad0.png ? 這樣在有多個(gè)進(jìn)程執(zhí)行這段代碼時(shí),就有可能產(chǎn)生并發(fā)問題: ? 81aa7b5c-0e86-11ed-ba43-dac502259ad0.png ? 這就會(huì)出現(xiàn)問題。 在單處理器中,解決這個(gè)問題的方法是,將count++語(yǔ)句翻譯成單指令操作 81bab972-0e86-11ed-ba43-dac502259ad0.png X86指令集支持inc操作,這樣count操作可以在一條指內(nèi)完成。 進(jìn)程的上下文切換總是在一條指令執(zhí)行之后完成,所以不會(huì)出現(xiàn)上述的并發(fā)問題。對(duì)于單處理器來(lái)說,一條處理器指令就是一個(gè)原子操作。 同樣,ARM里的SWP和X86里的XCHG都是對(duì)于單處理器來(lái)說,是原子操作。 但是,在多處理器系統(tǒng)(Symmetric Multi-Processor,簡(jiǎn)稱 SMP)中情況有所不同,由于系統(tǒng)中有多個(gè)處理器在獨(dú)立的運(yùn)行,即使在能單條指令中完成的操作也可能受到干擾。因?yàn)檫@個(gè)時(shí)候并發(fā)的主題不再是進(jìn)程,而是處理器。

X86架構(gòu)

Intel X86指令集提供了指令前綴lock用于鎖定前端串行總線FSB,保證了指令執(zhí)行時(shí)不會(huì)收到其他處理器的干擾。 比如: 81c7a588-0e86-11ed-ba43-dac502259ad0.png 使用lock指令前綴之后,處理期間對(duì)count內(nèi)存的并發(fā)訪問(Read/Write)被禁止,從而保證了指令的原子性。 如圖所示: 81db363e-0e86-11ed-ba43-dac502259ad0.pngX86LOCK 其原理在Intel開發(fā)手冊(cè)有如下說明:

在執(zhí)行伴隨的指令期間使處理器的LOCK#信號(hào)有效(將指令變?yōu)樵又噶睿?。在多處理器環(huán)境中,LOCK#信號(hào)確保處理器在信號(hào)有效時(shí)獨(dú)占使用任何共享存儲(chǔ)器。 LOCK前綴只能附加在下面的指令之前,并且只適用于那些目標(biāo)操作數(shù)是內(nèi)存操作數(shù)的指令格式:ADD,ADC,AND,BTC,BTR,BTS,CMPXCHG,CMPXCH8B,CMPXCHG16B,DEC,INC, NEG,NOT,OR,SBB,SUB,XOR,XADD和XCHG。 如果LOCK前綴與這些指令之一一起使用,并且源操作數(shù)是內(nèi)存操作數(shù),則可能會(huì)生成未定義的操作碼異常(#UD)。如果LOCK前綴與任何不在上述列表中的指令一起使用,也會(huì)產(chǎn)生未定義的操作碼異常。無(wú)論是否存在LOCK前綴,XCHG指令都始終聲明LOCK#信號(hào)。 LOCK前綴通常與BTS指令一起使用,以在共享存儲(chǔ)器環(huán)境中的存儲(chǔ)器位置上執(zhí)行讀取 – 修改 – 寫入操作。 LOCK前綴的完整性不受存儲(chǔ)器字段對(duì)齊的影響。內(nèi)存鎖定是針對(duì)任意不對(duì)齊的字段。

操作系統(tǒng)中的實(shí)現(xiàn)

Linux源碼中對(duì)于原子自增一是如下定義的: 81ef3404-0e86-11ed-ba43-dac502259ad0.png ? LOCK_PREFIX的定義如下所示: 81fdce9c-0e86-11ed-ba43-dac502259ad0.png ? 可見:在對(duì)稱多處理器架構(gòu)的情況下,LOCK_PREFIX被解釋為指令前綴lock。而對(duì)于單處理器架構(gòu),LOCK_PREFIX不包含任何內(nèi)容。 另外,對(duì)于CAS,有cmpxchg指令進(jìn)行操作。代碼如下:

static__always_inlineintatomic_cmpxchg(atomic_t*v,intold,intnew)
{
returncmpxchg(&v->counter,old,new);
}


#definecmpxchg(ptr,old,new)
__cmpxchg(ptr,old,new,sizeof(*(ptr)))


#define__cmpxchg(ptr,old,new,size)
__raw_cmpxchg((ptr),(old),(new),(size),LOCK_PREFIX)


#define__raw_cmpxchg(ptr,old,new,size,lock)
({
__typeof__(*(ptr))__ret;
__typeof__(*(ptr))__old=(old);
__typeof__(*(ptr))__new=(new);
switch(size){
case__X86_CASE_B:
{
volatileu8*__ptr=(volatileu8*)(ptr);
asmvolatile(lock"cmpxchgb%2,%1"
:"=a"(__ret),"+m"(*__ptr)
:"q"(__new),"0"(__old)
:"memory");
break;
}
case__X86_CASE_W:
{
volatileu16*__ptr=(volatileu16*)(ptr);
asmvolatile(lock"cmpxchgw%2,%1"
:"=a"(__ret),"+m"(*__ptr)
:"r"(__new),"0"(__old)
:"memory");
break;
}
case__X86_CASE_L:
{
volatileu32*__ptr=(volatileu32*)(ptr);
asmvolatile(lock"cmpxchgl%2,%1"
:"=a"(__ret),"+m"(*__ptr)
:"r"(__new),"0"(__old)
:"memory");
break;
}
case__X86_CASE_Q:
{
volatileu64*__ptr=(volatileu64*)(ptr);
asmvolatile(lock"cmpxchgq%2,%1"
:"=a"(__ret),"+m"(*__ptr)
:"r"(__new),"0"(__old)
:"memory");
break;
}
default:
__cmpxchg_wrong_size();
}
__ret;
})

ARM架構(gòu)

在ARM架構(gòu)下,沒有LOCK#指令,其具體實(shí)現(xiàn)如下:## ARMv6之前 早期的ARM架構(gòu)是不支持SMP的,這些單核架構(gòu)的CPU實(shí)現(xiàn)原子操作的方式就是通過關(guān)閉CPU中斷來(lái)完成的。 在Linux對(duì)于ARM架構(gòu)的代碼下 有如下: 82115fe8-0e86-11ed-ba43-dac502259ad0.png ? 這個(gè)是好多操作共用的一套代碼。 對(duì)于cmpxchg: 82213e7c-0e86-11ed-ba43-dac502259ad0.png ? 可以看到,對(duì)v->counter的操作是一個(gè)臨界區(qū),指令的執(zhí)行不能被打斷,內(nèi)存的訪問也需要保持沒有干擾。 ARMv6以前的版本通過關(guān)本地中斷來(lái)保護(hù)這塊臨界區(qū),看起來(lái)相當(dāng)簡(jiǎn)單,其奧秘就在于ARMv6以前的版本不支持SMP。 比如經(jīng)典的read-modify-write問題,其本質(zhì)是保持一個(gè)對(duì)內(nèi)存read和write訪問的原子性問題,也就是說內(nèi)存的讀和寫的訪問不能被打斷。對(duì)該問題的解決可以通過硬件、軟件或者軟硬件結(jié)合的方法來(lái)進(jìn)行。 早期的ARM CPU給出的方案就是依賴硬件:SWP這個(gè)匯編指令執(zhí)行了一次讀內(nèi)存操作、一次寫內(nèi)存操作,但是從程序員的角度看,SWP這條指令就是原子的,讀寫之間不會(huì)被任何的異步事件打斷。具體底層的硬件是如何做的呢?這時(shí)候,硬件會(huì)提供一個(gè)lock signal,在進(jìn)行memory操作的時(shí)候設(shè)定lock信號(hào),告訴總線這是一個(gè)不可被中斷的內(nèi)存訪問,直到完成了SWP需要進(jìn)行的兩次內(nèi)存訪問之后再clear lock信號(hào)。 多說一點(diǎn)關(guān)于SWP和SWPB的內(nèi)容 這兩個(gè)指令是用來(lái)同步的,不是用來(lái)執(zhí)行原子操作的。在將獨(dú)占訪問引入ARM架構(gòu)之前,SWP和SWPB指令常用于同步。 其局限性是:如果中斷在觸發(fā)交換操作時(shí)觸發(fā),則處理器必須在執(zhí)行中斷之前完成指令的加載和存儲(chǔ)部分,從而增加中斷延遲。由于獨(dú)立加載和獨(dú)占存儲(chǔ)是單獨(dú)的指令,因此在使用新的同步基元時(shí)會(huì)降低此效果。 但是在多核系統(tǒng)中,交換指令期間阻止所有處理器訪問主存會(huì)降低系統(tǒng)性能。在處理器工作在不同頻率但是共享相同主存的多核系統(tǒng)中,情況尤其如此。 所以在ARMv6及以后的版本中,棄用了SWP,ARMv6架構(gòu)引入了獨(dú)占訪問內(nèi)存為止的概念,提供了更靈活的原子內(nèi)存更新。 ARMv6體系結(jié)構(gòu)以Load-Exclusive和Store-Exclusive同步原語(yǔ)LDREX和STREX的形式引入了Load Link和Store Conditional指令。從ARMv6T2開始,這些指令在ARM和Thumb指令集中可用。獨(dú)立加載和專有存儲(chǔ)提供了靈活和可擴(kuò)展的同步,取代了棄用的SWP和SWPB指令。 后來(lái)使用的是LDREX和STREX指令,在armv7之后就用了ldrex和strex: 82331822-0e86-11ed-ba43-dac502259ad0.png ? 訪存指令LDREX/STREX和普通的LDR/STR訪存指令不一樣,它是“獨(dú)占”訪存指令。這對(duì)指令訪存過程由一個(gè)稱作“exclusive monitor”的部件來(lái)監(jiān)視是否可以進(jìn)行獨(dú)占訪問。 ? 獨(dú)占訪存指令: (1)LDREX R1 ,[R0] 指令是以獨(dú)占的方式從R0所指的地址中取一個(gè)字存放到R0中; (2)STREX R2,R1,[R0] 指令是以獨(dú)占的方式用R1來(lái)更新內(nèi)存,如果獨(dú)占訪問條件允許,則更新成功并返回0到R2,否則失敗返回1到R2。 最后,大家知道答案嗎?

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19740

    瀏覽量

    232919
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7628

    瀏覽量

    139758
  • 指令集
    +關(guān)注

    關(guān)注

    0

    文章

    228

    瀏覽量

    23667

原文標(biāo)題:對(duì) int 變量賦值的操作是原子的嗎?

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    X86和ARM中的指令集支持原子操作

    裸機(jī)開發(fā)與RTOS開發(fā)一個(gè)非常重要的區(qū)別在于多線程之間的消息傳遞和數(shù)據(jù)共享問題,然而在這中間變量的原子操作是一個(gè)非常重要的話題,不同的處理器架構(gòu)和編譯選項(xiàng)都可能生成不同的指令,從而影響到變量的
    發(fā)表于 07-06 16:10 ?2226次閱讀
    X86和ARM中的<b class='flag-5'>指令集</b><b class='flag-5'>支持</b><b class='flag-5'>原子</b><b class='flag-5'>操作</b>

    RISC-V指令集概述

    精度浮點(diǎn)擴(kuò)展)、M(整數(shù)乘除法)、A(原子擴(kuò)展)、C(壓縮擴(kuò)展)等擴(kuò)展指令。例如,在RV64I基礎(chǔ)上,添加原子、整數(shù)乘除法、雙精度浮點(diǎn)、壓縮指令,則該
    發(fā)表于 11-30 23:30

    Hexagon DSP的指令集

    Hexagon處理器指令集被劃分成了特定的指令類。類的不同決定了指令可以被如何以并行方式結(jié)合。指令類與指令的類型相符合。例如ALU32類包含
    發(fā)表于 09-19 18:13

    請(qǐng)問有STM32 SDIO指令集

    最近在做SD卡,但不是用原子哥的SPI模式,用SDIO模式,但不知道SDIO指令集,數(shù)據(jù)手冊(cè)上只有寥寥幾個(gè)指令,網(wǎng)上查了許久沒有結(jié)果。望哪位兄弟給一份指令集。qq 741060785謝
    發(fā)表于 02-19 21:25

    簡(jiǎn)單介紹ARM的指令集

    處理器架構(gòu)是處理器廠商為同一個(gè)系列的處理器規(guī)定的一個(gè)規(guī)范。ARM架構(gòu)是一種精簡(jiǎn)指令集(RISC)架構(gòu),具有以下RISC架構(gòu)特點(diǎn):較大的通用寄存器堆。load/store體系結(jié)構(gòu),其中數(shù)據(jù)處理操作僅對(duì)
    發(fā)表于 08-18 10:58

    微處理器指令集設(shè)計(jì)

    微處理器指令集設(shè)計(jì)垂直指令格式指令類型及其使用頻度CISC指令集特點(diǎn) RISC指令集特點(diǎn)指令集設(shè)
    發(fā)表于 10-29 17:13 ?64次下載
    微處理器<b class='flag-5'>指令集</b>設(shè)計(jì)

    SAM88RCRI 指令集

    SAM88RCRI 指令集支持寄存器卷操作,它可完成8 位算術(shù)操作和邏輯操作,共有41條指令集
    發(fā)表于 11-27 11:06 ?34次下載

    ARM指令集詳解

    ARM指令集詳解 內(nèi)容提要 ARM指令集 ARM指令集分類與指令格式 ARM指令的尋址方式 ARM
    發(fā)表于 03-09 09:39 ?263次下載
    ARM<b class='flag-5'>指令集</b>詳解

    8086匯編指令集

    8086匯編指令集 數(shù)據(jù)傳送指令集MOV功能: 把源操作數(shù)送給目的操作數(shù)語(yǔ)法: MOV 目的操作數(shù),源
    發(fā)表于 12-25 09:42 ?4663次閱讀

    sse指令集

    sse指令集 SSE(Streaming SIMD Extensions,單指令多數(shù)據(jù)流擴(kuò)展)指令集是Intel在Pentium III處理器中率先推出的。其實(shí),早在PIII正式推出之前
    發(fā)表于 12-25 10:59 ?1654次閱讀

    thumb指令集是什么_thumb指令集與arm指令集的區(qū)別

    。thumb不是一個(gè)完整的體系結(jié)構(gòu),不能指望處理器只執(zhí)行thumb指令集而不支持arm指令集。 thumb指令集分為:分支指令、數(shù)據(jù)傳送
    發(fā)表于 11-03 17:34 ?1.9w次閱讀
    thumb<b class='flag-5'>指令集</b>是什么_thumb<b class='flag-5'>指令集</b>與arm<b class='flag-5'>指令集</b>的區(qū)別

    mips指令集指的是什么

    指令集是存儲(chǔ)在CPU內(nèi)部,對(duì)CPU運(yùn)算進(jìn)行指導(dǎo)和優(yōu)化的硬程序。擁有這些指令集,CPU就可以更高效地運(yùn)行。MIPS指令集屬于精簡(jiǎn)指令集,MIPS的所有
    發(fā)表于 12-16 10:25 ?1.3w次閱讀

    risc指令集是什么_有哪些

     RISC指令集是高性能CPU的發(fā)展方向。它與傳統(tǒng)的CISC(復(fù)雜指令集)相對(duì)。相比而言,RISC的指令格式統(tǒng)一,種類比較少,尋址方式也比復(fù)雜指令集少。當(dāng)然處理速度就提高很多了。目前在
    發(fā)表于 12-19 11:55 ?2w次閱讀
    risc<b class='flag-5'>指令集</b>是什么_有哪些

    ARM架構(gòu)及ARM指令集 Thumb指令集你了解多少?

    ARM架構(gòu)及ARM指令集、Thumb指令集你了解多少?
    的頭像 發(fā)表于 02-26 16:09 ?7436次閱讀

    精簡(jiǎn)指令集的特點(diǎn)_精簡(jiǎn)指令集有哪些指令

    精簡(jiǎn)指令集計(jì)算機(jī)RISC的特點(diǎn)是指令及其格式精少,操作和控制簡(jiǎn)捷。具體有下列幾個(gè)方面。
    的頭像 發(fā)表于 08-10 11:26 ?1.4w次閱讀