在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于LDREX和STREX的原理

馬哥Linux運維 ? 來源:wind ? 作者:wind ? 2022-07-01 10:25 ? 次閱讀

前言

這個是在面試的時候遇到的問題,當時沒有答出來。回到家以后查了查,整理記錄下來。原問題:什么指令集支持原子操作?其原理是什么?如果考慮到全部的指令集,問題太大了,這里簡化下。以X86和ARM為例。原子操作是不可分割的操作,在執行完畢時它不會被任何事件中斷。在單處理器系統(UniProcessor,簡稱 UP)中,能夠在單條指令中完成的操作都可以認為是原子操作,因為中斷只能發生在指令與指令之間。比如,C語言代碼d056f370-f87e-11ec-ba43-dac502259ad0.png ?如果未經優化,有可能生成如下匯編: d06173ea-f87e-11ec-ba43-dac502259ad0.png ?這樣在有多個進程執行這段代碼時,就有可能產生并發問題: d06dcb36-f87e-11ec-ba43-dac502259ad0.png ?這就會出現問題。在單處理器中,解決這個問題的方法是,將count++語句翻譯成單指令操作d07f982a-f87e-11ec-ba43-dac502259ad0.pngX86指令集支持inc操作,這樣count操作可以在一條指內完成。進程的上下文切換總是在一條指令執行之后完成,所以不會出現上述的并發問題。對于單處理器來說,一條處理器指令就是一個原子操作。同樣,ARM里的SWP和X86里的XCHG都是對于單處理器來說,是原子操作。但是,在多處理器系統(Symmetric Multi-Processor,簡稱 SMP)中情況有所不同,由于系統中有多個處理器在獨立的運行,即使在能單條指令中完成的操作也可能受到干擾。因為這個時候并發的主題不再是進程,而是處理器。

X86架構

Intel X86指令集提供了指令前綴lock用于鎖定前端串行總線FSB,保證了指令執行時不會收到其他處理器的干擾。比如:d08c24c8-f87e-11ec-ba43-dac502259ad0.png ?使用lock指令前綴之后,處理期間對count內存的并發訪問(Read/Write)被禁止,從而保證了指令的原子性。如圖所示:d0a07da6-f87e-11ec-ba43-dac502259ad0.pngX86LOCK其原理在Intel開發手冊有如下說明:
DescriptionCauses the processor’s LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal ensures that the processor has exclusive use of any shared memory while the signal is asserted.The LOCK prefix can be prepended only to the following instructions and only to those forms of the instructions where the destination operand is a memory operand: ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG. If the LOCK prefix is used with one of these instructions and the source operand is a memory operand, an undefined opcode exception (#UD) may be generated. An undefined opcode exception will also be generated if the LOCK prefix is used with any instruction not in the above list. The XCHG instruction always asserts the LOCK# signal regardless of the presence or absence of the LOCK prefix.The LOCK prefix is typically used with the BTS instruction to perform a read-modify-write operation on a memory location in shared memory environment.The integrity of the LOCK prefix is not affected by the alignment of the memory field. Memory locking is observed for arbitrarily misaligned fields.
在執行伴隨的指令期間使處理器的LOCK#信號有效(將指令變為原子指令)。在多處理器環境中,LOCK#信號確保處理器在信號有效時獨占使用任何共享存儲器。LOCK前綴只能附加在下面的指令之前,并且只適用于那些目標操作數是內存操作數的指令格式:ADD,ADC,AND,BTC,BTR,BTS,CMPXCHG,CMPXCH8B,CMPXCHG16B,DEC,INC, NEG,NOT,OR,SBB,SUB,XOR,XADD和XCHG。如果LOCK前綴與這些指令之一一起使用,并且源操作數是內存操作數,則可能會生成未定義的操作碼異常(#UD)。如果LOCK前綴與任何不在上述列表中的指令一起使用,也會產生未定義的操作碼異常。無論是否存在LOCK前綴,XCHG指令都始終聲明LOCK#信號。LOCK前綴通常與BTS指令一起使用,以在共享存儲器環境中的存儲器位置上執行讀取 – 修改 – 寫入操作。LOCK前綴的完整性不受存儲器字段對齊的影響。內存鎖定是針對任意不對齊的字段。

操作系統中的實現

Linux源碼中對于原子自增一是如下定義的:d0b19668-f87e-11ec-ba43-dac502259ad0.png ?LOCK_PREFIX的定義如下所示:d0c5afc2-f87e-11ec-ba43-dac502259ad0.png ?可見:在對稱多處理器架構的情況下,LOCK_PREFIX被解釋為指令前綴lock。而對于單處理器架構,LOCK_PREFIX不包含任何內容。另外,對于CAS,有cmpxchg指令進行操作。代碼如下:

		static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new){return cmpxchg(&v->counter, old, new);} #define cmpxchg(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: { volatile u8 *__ptr = (volatile u8 *)(ptr); asm volatile(lock "cmpxchgb %2,%1" : "=a" (__ret), "+m" (*__ptr) : "q" (__new), "0" (__old) : "memory"); break; } case __X86_CASE_W: { volatile u16 *__ptr = (volatile u16 *)(ptr); asm volatile(lock "cmpxchgw %2,%1" : "=a" (__ret), "+m" (*__ptr) : "r" (__new), "0" (__old) : "memory"); break; } case __X86_CASE_L: { volatile u32 *__ptr = (volatile u32 *)(ptr); asm volatile(lock "cmpxchgl %2,%1" : "=a" (__ret), "+m" (*__ptr) : "r" (__new), "0" (__old) : "memory"); break; } case __X86_CASE_Q: { volatile u64 *__ptr = (volatile u64 *)(ptr); asm volatile(lock "cmpxchgq %2,%1" : "=a" (__ret), "+m" (*__ptr) : "r" (__new), "0" (__old) : "memory"); break; } default: __cmpxchg_wrong_size(); } __ret; })
		

ARM架構

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

原文標題:對int變量賦值的操作是原子的嗎?為什么?

文章出處:【微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

審核編輯:彭靜

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3040

    瀏覽量

    74171
  • 處理器系統
    +關注

    關注

    0

    文章

    9

    瀏覽量

    7821
  • C語言代碼
    +關注

    關注

    0

    文章

    10

    瀏覽量

    9166

原文標題:對int變量賦值的操作是原子的嗎?為什么?

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    66ak2h14使用 ldrex過程中出錯

    我使用的開發板是EVMK2H,在使用自旋鎖時候會發現一直處于死鎖狀態,仿真器調試發現,無論我內存單元中的值是多少,執行 LDREX ? R2, [R0] ? ? ? ?;R0為內存單元地址 R2讀取到的值始終為0,請問在使用LDREX指令之前還需要做什么配置嗎?
    發表于 06-21 16:55

    stm32的Core_cm3.c文件

    STREX是Cortex用來實現互斥訪問,保護臨界資源的指令,LDREX執行后,只有離它最近的一條存儲指令(STR,STREX)才能執行,其他的存儲指令都會被駁回,而CLREX就是用于清除互斥訪問狀態
    發表于 07-02 06:19

    STM32F7 MPU設置跳入硬件錯誤中

    最近在使用STM32F746,將內部RAM的MPU屬性設置為MPU_ACCESS_SHAREABLE,發現如果程序中使用 ldrex 指令,會跳入硬件錯誤中斷,設置成
    發表于 01-30 04:07

    ARM平臺上特有的獨占訪問指令LDREXSTREX該怎樣去使用呢

    來說,也在硬件層面上提供了對LL/SC的支持,LL操作用的是LDREX指令,SC操作用的是STREX指令。本文主要用來說明ARM平臺上特有的獨占訪問指令LDREXSTREX的工作原理
    發表于 04-22 09:44

    AHB-lite總線如何處理獨占訪問

    設計。處理器從代碼總線正確引導,并執行指令(已禁用ITCM)。問題是我認為普通LDR / STR和LDREX / STREX在AXI總線上沒有區別。無論我怎么嘗試,STREX指令都將失敗(返回1
    發表于 08-18 11:11

    不能將STREX/LDREX與多核共享內存訪問一起使用嗎?

    我需要確認使用具有共享內存區域的 STREX/LDREX 不會創建全局獨占訪問標簽。所以我們不能將 STREX/LDREX 與多核共享內存訪問一起使用。我認為這違反了 cortex-M
    發表于 04-03 07:45

    關于各種pon的資料

    關于各種pon的資料
    發表于 07-30 15:43 ?0次下載

    關于DSP-AD的參考文件

    關于DSP-AD的參考文件
    發表于 04-12 14:27 ?3次下載
    <b class='flag-5'>關于</b>DSP-AD的參考文件

    關于LaunchPad溫度代碼

    關于LaunchPad溫度代碼。
    發表于 05-07 17:04 ?7次下載
    <b class='flag-5'>關于</b>LaunchPad溫度代碼

    關于STM32的計數與延時

    關于STM32的計數和延時
    的頭像 發表于 03-12 11:20 ?6729次閱讀

    淺談鴻蒙內核源碼的原子操作

    ARMv6架構引入了LDREXSTREX指令,以支持對共享存儲器更縝密的非阻塞同步。由此實現的原子操作能確保對同一數據的“讀取-修改-寫入”操作在它的執行期間不會被打斷,即操作的原子性。
    的頭像 發表于 04-25 16:05 ?1288次閱讀
    淺談鴻蒙內核源碼的原子操作

    關于PWM模式的理解

    關于PWM模式的理解
    發表于 11-30 14:06 ?3次下載
    <b class='flag-5'>關于</b>PWM模式的理解

    ARM指令集—SWP指令

    。 SWP指令主要是完畢ARM體系架構處理器的同步操作。在Linux操作系統中實現信號量的操作。可是此指令在ARMv6架構后就沒有採用了,而是通過擴展的LDREXSTREX實現。本片文章主要介紹SWP的功能...
    發表于 02-11 15:33 ?6次下載
    ARM指令集—SWP指令

    Vybrid非對稱多核架構的裸機固件

      另一方面是與運行在 Cortex-A5 上的主操作系統進行通信的通信基礎設施。libopencm3 實現目前不支持通信。可能最簡單的通信實現是定義一個可以從雙方訪問的共享內存區域(考慮使用使用獨占加載/存儲指令 LDREX/STREX 的同步機制)。
    的頭像 發表于 06-14 09:24 ?963次閱讀
    Vybrid非對稱多核架構的裸機固件

    關于量子糾纏的故事

    關于量子糾纏的故事還得從玻爾和愛因斯坦關于量子力學本質的爭論開始說起。
    的頭像 發表于 11-07 11:22 ?1985次閱讀
    主站蜘蛛池模板: 影音先锋午夜资源网站| 五月天激情综合网| 正在播放91大神调教偷偷| 天天爱天天操| 久久99精品久久久久久久野外| 最新天堂网| 高清欧美色欧美综合网站| 日本最黄| 91日韩精品天海翼在线观看| 青草久| 在线免费成人| 亚洲人成电影在线播放| 2015xxxx欧美| 手机在线观看免费视频| 天天操网| 夜夜操夜夜爽| 高清色黄毛片一级毛片| 欧美成人性色xxxxx视频大 | 欧美天天视频| 亚洲美女高清一区二区三区| 毛色毛片| brazzers720欧美丰满| 在线播放色| 韩国三级中文| 日本成人一级片| 亚洲综合婷婷| 狠狠干精品| 在线观看一二三区| 老师解胸罩喂我吃奶| 3344在线观看永久免费| 日本在线视频不卡| h视频在线观看视频观看| 欧美成人全部免费观看1314色| 91在线影视| 国产精品资源在线观看| 欧美成人午夜毛片免费影院| 天天综合天天做| 亚洲黄网址| 午夜欧美精品久久久久久久久| 小雪被老外黑人撑破了| 久久v|