RISC-V強(qiáng)大的原子指令
RISC-V 把原子指令劃分成單獨(dú)的指令擴(kuò)展,命名為 'A'。該擴(kuò)展中主要包含兩部分,一個(gè) LR/SC 指令,即Load-Reserved/Store-Conditional,另外一個(gè)是 AMO 指令,RV32A 有兩種類(lèi)型的原子操作:
-
內(nèi)存原子操作(AMO)
-
加載保留/條件存儲(chǔ)(load reserved / store conditional)
內(nèi)存原子操作(AMO)
AMO是強(qiáng)大的“讀改寫(xiě)”指令,該操作加載rs1指向的存儲(chǔ)器位置的內(nèi)容,并將其存儲(chǔ)在寄存器 rd 中,然后與rs2中的值進(jìn)行二進(jìn)制運(yùn)算,并將結(jié)果保存回rd中,然后再寫(xiě)到rs1指向的存儲(chǔ)器位置。
為什么要amo指令?
AMO指令要求整個(gè)讀出,計(jì)算,寫(xiě)回必須為原子性質(zhì),就是讀出和寫(xiě)回之間,該存儲(chǔ)器地址不能被其它進(jìn)程訪(fǎng)問(wèn),通常總線(xiàn)會(huì)鎖定,這樣就支持多核SoC系統(tǒng)。雖然 RISC-V B位操作擴(kuò)展支持一系列復(fù)雜的位控制指令,但Atomic擴(kuò)展并不只是針對(duì)多處理器系統(tǒng),它還有助于那些必要的位操作需求比較簡(jiǎn)單的嵌入式系統(tǒng),從而精簡(jiǎn)軟件指令代碼。
AMO自旋鎖的示例如下:
-
先在寄存器t0中放入1(li t0, 1)。
-
load加載a0地址中的內(nèi)容到t1中,a0為鎖的地址。
-
比較t1和0(bnez),t1不等于0則跳轉(zhuǎn)到again,t1不等于0說(shuō)明鎖已經(jīng)被持有。
-
把t0(1)放到a0表示的地址中,含義為上鎖,把a(bǔ)0處的原值放到t1中。
-
比較t1和0(bnez),t1不等于0則跳轉(zhuǎn)到again,t1不等于0說(shuō)明鎖已經(jīng)被持有。
-
執(zhí)行關(guān)鍵區(qū)Critical section代碼。
-
解鎖,把x0(0)的值賦給(a0),把(a0)的值交給x0(丟棄)。注意,RISC-V架構(gòu)規(guī)定x0固定為0值。
再次申明,AMO指令要求整個(gè)讀出,計(jì)算,寫(xiě)回必須為原子性質(zhì),就是讀出和寫(xiě)回之間,該存儲(chǔ)器地址不能被其它進(jìn)程訪(fǎng)問(wèn),通??偩€(xiàn)會(huì)鎖定。AMO指令也可以支持釋放一致性模型,可以通過(guò)指令中的aq/rl位,來(lái)設(shè)置獲取或釋放屬性。
另外還提供 AMO 指令的原因是,它們?cè)诙嗵幚砥飨到y(tǒng)中擁有比加載保留/條件存儲(chǔ)更好的可擴(kuò)展性,例如可以用它們來(lái)實(shí)現(xiàn)高效的歸約。AMO 指令在于 I/O 設(shè)備通信時(shí)也很有用,可以實(shí)現(xiàn)總線(xiàn)事務(wù)的原子讀寫(xiě)。這種原子性可以簡(jiǎn)化設(shè)備驅(qū)動(dòng),并提高 I/O 性能。
LR/SC指令
雖然原子操作能解決多線(xiàn)程的競(jìng)爭(zhēng)問(wèn)題,但由于會(huì)將總線(xiàn)鎖住,導(dǎo)致其他核無(wú)法訪(fǎng)問(wèn)總線(xiàn),在核數(shù)眾多且頻發(fā)搶鎖的情況下,會(huì)造成總線(xiàn)長(zhǎng)期被鎖的情況,因此引入一種新的互斥類(lèi)型的存儲(chǔ)器訪(fǎng)問(wèn)指令,即LR(load reserved)/SC(store conditional)指令。LR指令是Load Reserved的縮寫(xiě),讀取保留;SC指令是Store Conditional 的縮寫(xiě),條件存儲(chǔ),即load reserved/store conditional。
LR指令是從內(nèi)存地址rs1中加載內(nèi)容到rd寄存器。然后在rs1對(duì)應(yīng)地址上設(shè)置保留標(biāo)記(reservation set)。
SC指令在把rs2值寫(xiě)到rs1地址之前,會(huì)先判斷rs1內(nèi)存地址是否有設(shè)置保留標(biāo)記,如果設(shè)置了,則把rs2值正常寫(xiě)入到rs1內(nèi)存地址里,并把rd寄存器設(shè)置成 0,表示保存成功。如果rs1內(nèi)存地址沒(méi)有設(shè)置保留標(biāo)記,則不保存,并把rd寄存器設(shè)置成1表示保存失敗。不管成功還是失敗,SC指令都會(huì)把當(dāng)前hart 保留的所有保留標(biāo)記全部清除。一個(gè)例子如下:
-
加載舊的值
-
比較舊的值與 a1 是否相等
-
相等則存入新的值
-
如果存入失敗,重新嘗試
-
…比較-交換成功之后的代碼…
-
比較-交換不成功