01、前言
RISC-V的RVWMO模型主要包含了preserved program order、load value axiom、atomicity axiom、progress axiom和I/O Ordering。今天主要記錄下preserved program order(保留程序順序)中的Explicit Synchronization(顯示同步)。
02、顯式同步
顯示同步指的是:a操作在程序順序中先于b操作,a和b都訪問(wèn)常規(guī)主存,不是I/O區(qū)域,如果存在以下任何一個(gè)條件,那么a操作和b操作在全局內(nèi)存順序中的順序也不會(huì)變。
a和b之間有FENCE指令。
a擁有acquire語(yǔ)義。
b擁有release語(yǔ)義。
a和b都有RCsc語(yǔ)義。
a和b是配對(duì)的。
關(guān)于第一點(diǎn):默認(rèn)情況下,F(xiàn)ENCE指令確保所有在程序順序中位于FENCE之前的指令的內(nèi)存訪問(wèn)(“前導(dǎo)集”)在全局內(nèi)存順序中比在程序順序中位于FENCE之后的指令的內(nèi)存訪問(wèn)(“后續(xù)集”)出現(xiàn)得更早。不過(guò),為了性能上的考量,F(xiàn)ENCE可以選擇性進(jìn)一步地限制前導(dǎo)集和后續(xù)集為較小的內(nèi)存訪問(wèn)集。具體來(lái)說(shuō),F(xiàn)ENCE有PR、PW、SR和SW bits,它們限制了前導(dǎo)集和后續(xù)集所包含的指令類型。如果PR為1,那么前導(dǎo)集包括load;如果PW為1,那么前導(dǎo)集包含store;如果SR為1,那么后續(xù)集包括load;如果SW為1,那么后續(xù)集包括store。
FENCE中PR、PW、SR和SW這4bit可以組成16種FENCE語(yǔ)義,但不是每一種組合都有用的。其中有7中組合具有空的前導(dǎo)集或后續(xù)集,因此是無(wú)操作的。另外FENCE還有一個(gè)額外的編碼為FENCE.TSO,提供它主要是方便映射到“acquire+release”或RVTSO語(yǔ)義上。不過(guò)在這10(16-7+1)個(gè)選項(xiàng)中,只有下面6個(gè)在實(shí)踐中常用:
FENCE RW,RW
FENCE.TSO
FENCE RW,W
ENCE R,RW
·FENCE R,R
FENCE W,W
RISC-V手冊(cè)建議程序員只使用這6種FENCE指令,其他組合的FENCE指令可能不生效,而且會(huì)造成意外的結(jié)果。
關(guān)于第二點(diǎn):通常在關(guān)鍵代碼的臨界區(qū)開始時(shí)使用acquire操作,要求在程序順序在acquire之后的load和store操作也要在全局內(nèi)存順序上在acquire之后。這樣可以確保關(guān)鍵代碼臨界區(qū)內(nèi)位于acquire操作之后的所有l(wèi)oad和store可以獲取最新的數(shù)據(jù)。Acquire操作排序可以通過(guò)兩種方式來(lái)實(shí)現(xiàn)。
使用acquire語(yǔ)義的指令:它只針對(duì)同步變量本身強(qiáng)制排序
使用FENCE R,RW:它針對(duì)之前的所有l(wèi)oad強(qiáng)制排序
如下代碼1使用第一種方案,因?yàn)閍moswap使用了aq,所以臨界區(qū)的load和store保證出現(xiàn)于獲取鎖的amoswwap之后的全局內(nèi)存順序中。然而a1和a2指向不同的內(nèi)存位置,臨界區(qū)的load和store可能與它們亂序,也就是在全局內(nèi)存順序中,它們之間的順序不是固定的。
如下代碼2使用第二種方案,在這種情況下,盡管amoswap不強(qiáng)制使用aq進(jìn)行排序,但FENCE仍然強(qiáng)制amoswap在全局內(nèi)存順序中出現(xiàn)的時(shí)間比臨界區(qū)中的所有l(wèi)oad和store都要早。但使用FENCE的一個(gè)副作用就是,F(xiàn)ENCE還強(qiáng)制執(zhí)行了額外的排序,它還要求程序開始時(shí)的a2不相關(guān)的load指令出現(xiàn)的時(shí)間要早于臨界區(qū)的load和store。因此,F(xiàn)ENCE命令比aq命令在排序上更強(qiáng)硬些,當(dāng)然也更粗糙些。
關(guān)于第三點(diǎn):Release排序和acquire排序的工作原理類似,只是排序的方向相反。Release語(yǔ)義要求在release操作程序順序之前的所有l(wèi)oad和store也要在全局內(nèi)存順序上先于release操作。這樣可以確保在全局內(nèi)存順序中,臨界區(qū)的內(nèi)存訪問(wèn)出現(xiàn)在release釋放鎖的store之前。就像acquire語(yǔ)義一樣,release語(yǔ)義可以通過(guò)兩種方式來(lái)實(shí)現(xiàn):
使用帶release的指令
使用FENCE RW,W指令
例子就如同第二點(diǎn)中代碼1和代碼2。代碼1在關(guān)鍵代碼片段的末尾使用rl來(lái)確保順序,其中a3和a4與rl之間沒有固定關(guān)系,在全局內(nèi)存順序上沒有固定順序。代碼2在關(guān)鍵片段的末尾使用FENCE RW,W來(lái)確保順序。
關(guān)于第四點(diǎn):如果單獨(dú)使用RCpc語(yǔ)義,就不會(huì)強(qiáng)制store release到load acquire的順序,這有助于移植在TSO或RCpc內(nèi)存模型下編寫的代碼。為了確保store release到load acquire的順序,代碼必須使用RCsc的語(yǔ)義。
關(guān)于第五點(diǎn):在全局內(nèi)存順序中,SC必須出現(xiàn)在與其配對(duì)的LR之后。由于固有的語(yǔ)法數(shù)據(jù)依賴,通常使用LR/SC來(lái)執(zhí)行原子讀-修改-寫操作。但其實(shí)即使store的值在語(yǔ)法上不依賴于成對(duì)LR返回的值,這一點(diǎn)也適用。