最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一文看懂ARM平臺(tái)下獨(dú)占訪問(wèn)指令LDREX和STREX的原理

2022-11-02 17:07 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

為了實(shí)現(xiàn)線程間同步,一般都要在執(zhí)行關(guān)鍵代碼段之前加互斥(Mutex)鎖,且在執(zhí)行完關(guān)鍵代碼段之后解鎖。為了實(shí)現(xiàn)所謂的互斥鎖的概念,一般都需要所在平臺(tái)提供支持。

在計(jì)算機(jī)領(lǐng)域里,如果要在多線程的情況下要保持?jǐn)?shù)據(jù)的同步,需要引入稱作Load-Link(LL)和Store-Conditional(SC)的操作,通常簡(jiǎn)稱為L(zhǎng)L/SC。LL操作返回一個(gè)內(nèi)存地址上當(dāng)前存儲(chǔ)的值,后面的SC操作,會(huì)向這個(gè)內(nèi)存地址寫(xiě)入一個(gè)新值,但是只有在這個(gè)內(nèi)存地址上存儲(chǔ)的值,從上個(gè)LL操作開(kāi)始直到現(xiàn)在都沒(méi)有發(fā)生改變的情況下,寫(xiě)入操作才能成功,否則都會(huì)失敗。這個(gè)操作非常重要,是很多平臺(tái)實(shí)現(xiàn)基本原子操作的基礎(chǔ)。 對(duì)于ARM平臺(tái)來(lái)說(shuō),也在硬件層面上提供了對(duì)LL/SC的支持,LL操作用的是LDREX指令,SC操作用的是STREX指令。

本文主要用來(lái)說(shuō)明ARM平臺(tái)上特有的獨(dú)占訪問(wèn)指令LDREX和STREX的工作原理,以及如何使用。而它們也是ARM平臺(tái)上,實(shí)現(xiàn)互斥鎖等線程同步工具的基礎(chǔ)。

我們先來(lái)看看LDREX和STREX兩條指令的語(yǔ)義。其實(shí)LDREX和STREX指令,是將單純的更新內(nèi)存的原子操作分成了兩個(gè)獨(dú)立的步驟。

  1. LDREX用來(lái)讀取內(nèi)存中的值,并標(biāo)記對(duì)該段內(nèi)存的獨(dú)占訪問(wèn):

LDREX Rx, [Ry]

上面的指令意味著,讀取寄存器Ry指向的4字節(jié)內(nèi)存值,將其保存到Rx寄存器中,同時(shí)標(biāo)記對(duì)Ry指向內(nèi)存區(qū)域的獨(dú)占訪問(wèn)。如果執(zhí)行LDREX指令的時(shí)候發(fā)現(xiàn)已經(jīng)被標(biāo)記為獨(dú)占訪問(wèn)了,并不會(huì)對(duì)指令的執(zhí)行產(chǎn)生影響。

  1. STREX在更新內(nèi)存數(shù)值時(shí),會(huì)檢查該段內(nèi)存是否已經(jīng)被標(biāo)記為獨(dú)占訪問(wèn),并以此來(lái)決定是否更新內(nèi)存中的值:

STREX Rx, Ry, [Rz]

如果執(zhí)行這條指令的時(shí)候發(fā)現(xiàn)已經(jīng)被標(biāo)記為獨(dú)占訪問(wèn)了,則將寄存器Ry中的值更新到寄存器Rz指向的內(nèi)存,并將寄存器Rx設(shè)置成0。指令執(zhí)行成功后,會(huì)將獨(dú)占訪問(wèn)標(biāo)記位清除。而如果執(zhí)行這條指令的時(shí)候發(fā)現(xiàn)沒(méi)有設(shè)置獨(dú)占標(biāo)記,則不會(huì)更新內(nèi)存,且將寄存器Rx的值設(shè)置成1。一旦某條STREX指令執(zhí)行成功后,以后再對(duì)同一段內(nèi)存嘗試使用STREX指令更新的時(shí)候,會(huì)發(fā)現(xiàn)獨(dú)占標(biāo)記已經(jīng)被清空了,就不能再更新了,從而實(shí)現(xiàn)獨(dú)占訪問(wèn)的機(jī)制。

大致的流程就是這樣,但是ARM內(nèi)部為了實(shí)現(xiàn)這個(gè)功能,還有不少?gòu)?fù)雜的情況要處理。

在ARM系統(tǒng)中,內(nèi)存有兩種不同且對(duì)立的屬性,即共享(Shareable)和非共享(Non-shareable)。共享意味著該段內(nèi)存可以被系統(tǒng)中不同處理器訪問(wèn)到,這些處理器可以是同構(gòu)的也可以是異構(gòu)的。而非共享,則相反,意味著該段內(nèi)存只能被系統(tǒng)中的一個(gè)處理器所訪問(wèn)到,對(duì)別的處理器來(lái)說(shuō)不可見(jiàn)。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??

為了實(shí)現(xiàn)獨(dú)占訪問(wèn),ARM系統(tǒng)中還特別提供了所謂獨(dú)占監(jiān)視器(Exclusive Monitor)的東西,其結(jié)構(gòu)大致如下:


可以看出來(lái),一共有兩種類型的獨(dú)占監(jiān)視器。每一個(gè)處理器內(nèi)部都有一個(gè)本地監(jiān)視器(Local Monitor),且在整個(gè)系統(tǒng)范圍內(nèi)還有一個(gè)全局監(jiān)視器(Global Monitor)。

如果要對(duì)非共享內(nèi)存區(qū)中的值進(jìn)行獨(dú)占訪問(wèn),只需要涉及本處理器內(nèi)部的本地監(jiān)視器就可以了;而如果要對(duì)共享內(nèi)存區(qū)中的內(nèi)存進(jìn)行獨(dú)占訪問(wèn),除了要涉及到本處理器內(nèi)部的本地監(jiān)視器外,由于該內(nèi)存區(qū)域可以被系統(tǒng)中所有處理器訪問(wèn)到,因此還必須要由全局監(jiān)視器來(lái)協(xié)調(diào)。

對(duì)于本地監(jiān)視器來(lái)說(shuō),它只標(biāo)記了本處理器對(duì)某段內(nèi)存的獨(dú)占訪問(wèn),在調(diào)用LDREX指令時(shí)設(shè)置獨(dú)占訪問(wèn)標(biāo)志,在調(diào)用STREX指令時(shí)清除獨(dú)占訪問(wèn)標(biāo)志。而對(duì)于全局監(jiān)視器來(lái)說(shuō),它可以標(biāo)記每個(gè)處理器對(duì)某段內(nèi)存的獨(dú)占訪問(wèn)。也就是說(shuō),當(dāng)一個(gè)處理器調(diào)用LDREX訪問(wèn)某段共享內(nèi)存時(shí),全局監(jiān)視器只會(huì)設(shè)置針對(duì)該處理器的獨(dú)占訪問(wèn)標(biāo)記,不會(huì)影響到其它的處理器。

當(dāng)在以下兩種情況下,會(huì)清除某個(gè)處理器的獨(dú)占訪問(wèn)標(biāo)記:

  1. 當(dāng)該處理器調(diào)用LDREX指令,申請(qǐng)獨(dú)占訪問(wèn)另一段內(nèi)存時(shí);

  2. 當(dāng)別的處理器成功更新了該段獨(dú)占訪問(wèn)內(nèi)存值時(shí)。

對(duì)于第二種情況,也就是說(shuō),當(dāng)獨(dú)占內(nèi)存訪問(wèn)內(nèi)存的值在任何情況下,被任何一個(gè)處理器更改過(guò)之后,所有申請(qǐng)獨(dú)占該段內(nèi)存的處理器的獨(dú)占標(biāo)記都會(huì)被清空。

現(xiàn)在的處理器基本上都是多核的,一個(gè)芯片上集成了多個(gè)處理器。而且對(duì)于一般的操作系統(tǒng),系統(tǒng)內(nèi)存基本上都被設(shè)置上了共享屬性,也就是說(shuō)對(duì)系統(tǒng)中所有處理器可見(jiàn)。因此,我們這里主要分析多核系統(tǒng)中對(duì)共享內(nèi)存的獨(dú)占訪問(wèn)的情況。

為了更加清楚的說(shuō)明,我們可以舉一個(gè)例子。假設(shè)系統(tǒng)中有兩個(gè)處理器內(nèi)核,而一個(gè)程序由三個(gè)線程組成,其中兩個(gè)線程被分配到了第一個(gè)處理器上,另外一個(gè)線程被分配到了第二個(gè)處理器上。且他們的執(zhí)行序列如下:


大致經(jīng)歷的步驟如下:

  1. CPU2上的線程3最早執(zhí)行LDREX,鎖定某段共享內(nèi)存區(qū)域。它會(huì)相應(yīng)更新本地監(jiān)視器和全局監(jiān)視器。

  2. 然后,CPU1上的線程1執(zhí)行LDREX,它也會(huì)更新本地監(jiān)視器和全局監(jiān)視器。這時(shí)在全局監(jiān)視器上,CPU1和CPU2都對(duì)該段內(nèi)存做了獨(dú)占標(biāo)記。

  3. 接著,CPU1上的線程2執(zhí)行LDREX指令,它會(huì)發(fā)現(xiàn)本處理器的本地監(jiān)視器對(duì)該段內(nèi)存有了獨(dú)占標(biāo)記,同時(shí)全局監(jiān)視器上CPU1也對(duì)該段內(nèi)存做了獨(dú)占標(biāo)記,但這并不會(huì)影響這條指令的操作。

  4. 再下來(lái),CPU1上的線程1最先執(zhí)行了STREX指令,嘗試更新該段內(nèi)存的值。它會(huì)發(fā)現(xiàn)本地監(jiān)視器對(duì)該段內(nèi)存是有獨(dú)占標(biāo)記的,而全局監(jiān)視器上CPU1也有該段內(nèi)存的獨(dú)占標(biāo)記,則更新內(nèi)存值成功。同時(shí),清除本地監(jiān)視器對(duì)該段內(nèi)存的獨(dú)占標(biāo)記,還有全局監(jiān)視器所有處理器對(duì)該段內(nèi)存的獨(dú)占標(biāo)記。

  5. 下面,CPU2上的線程3執(zhí)行STREX指令,也想更新該段內(nèi)存值。它會(huì)發(fā)現(xiàn)本地監(jiān)視器擁有對(duì)該段內(nèi)存的獨(dú)占標(biāo)記,但是在全局監(jiān)視器上CPU1沒(méi)有了該段內(nèi)存的獨(dú)占標(biāo)記(前面一步清空了),則更新不成功。

  6. 最后,CPU1上的線程2執(zhí)行STREX指令,試著更新該段內(nèi)存值。它會(huì)發(fā)現(xiàn)本地監(jiān)視器已經(jīng)沒(méi)有了對(duì)該段內(nèi)存的獨(dú)占標(biāo)記(第4步清除了),則直接更新失敗,不需要再查全局監(jiān)視器了。

所以,可以看出來(lái),這套機(jī)制的精髓就是,無(wú)論有多少個(gè)處理器,有多少個(gè)地方會(huì)申請(qǐng)對(duì)同一個(gè)內(nèi)存段進(jìn)行操作,保證只有最早的更新可以成功,這之后的更新都會(huì)失敗。失敗了就證明對(duì)該段內(nèi)存有訪問(wèn)沖突了。實(shí)際的使用中,可以重新用LDREX讀取該段內(nèi)存中保存的最新值,再處理一次,再嘗試保存,直到成功為止。

還有一點(diǎn)需要說(shuō)明,LDREX和STREX是對(duì)內(nèi)存中的一個(gè)字(Word,32 bit)進(jìn)行獨(dú)占訪問(wèn)的指令。如果想獨(dú)占訪問(wèn)的內(nèi)存區(qū)域不是一個(gè)字,還有其它的指令: 1)LDREXB和STREXB:對(duì)內(nèi)存中的一個(gè)字節(jié)(Byte,8 bit)進(jìn)行獨(dú)占訪問(wèn); 2)LDREXH和STREXH:中的一個(gè)半字(Half Word,16 bit)進(jìn)行獨(dú)占訪問(wèn); 3)LDREXD和STREXD:中的一個(gè)雙字(Double Word,64 bit)進(jìn)行獨(dú)占訪問(wèn)。

在ARMv8指令集下,LDREX指令被改名成了LDXR指令,而STREX指令被改名成了STXR指令,功能基本上是一樣的,除了添加了一個(gè)新的特性。當(dāng)全局監(jiān)視器標(biāo)記的對(duì)某段內(nèi)存的獨(dú)占訪問(wèn)被清空后,將向所有標(biāo)記了對(duì)該段內(nèi)存獨(dú)占訪問(wèn)的CPU核都發(fā)送事件,將它們從WFE指令中喚醒,繼續(xù)執(zhí)行。




一文看懂ARM平臺(tái)下獨(dú)占訪問(wèn)指令LDREX和STREX的原理的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
大同县| 建宁县| 疏附县| 新郑市| 英吉沙县| 曲水县| 玉门市| 华宁县| 稻城县| 贺州市| 汨罗市| 万载县| 安图县| 息烽县| 辽阳县| 济南市| 增城市| 三原县| 凉山| 凉城县| 宜春市| 广平县| 阿尔山市| 平舆县| 东源县| 泽普县| 泽库县| 长武县| 寿光市| 永年县| 东乡| 泰州市| 西丰县| 胶州市| 民乐县| 益阳市| 开化县| 张家口市| 和平区| 巧家县| 岳阳县|