理解MIPS指令集中的ll (load linked) 和 sc
你用ll指令讀取一個內存中的數據並存到一個寄存器,然后在寄存器修改(或不)這個值,隨后用sc指令將它寫入到同樣的(原來的)位置。
而sc指令只在你修改寄存器中的值的期間,沒有任何一個處理器改變它內存中的值 這種情況下,將值寫入。
它同時需要(的副作用是)設置一個指示狀態的變量來表明是否成功寫入。(成功為1,失敗為0) 當新的值成功地被寫入了,那么可以認為這個線程在沒有別的線程干涉的情況下完成了(一個值的)讀-改-寫過程。
如果失敗了,接下來就取決於程序是要放棄這個操作還是再試一次了,不過至少它(ll&sc)不會生成一個隱性的(不被察覺的)競爭危害。
LL(Load Linked,鏈接加載)以及SC(Store Conditional,條件存儲)
LL 指令的功能是從內存中讀取一個字,以實現接下來的 RMW(Read-Modify-Write) 操作;
SC 指令的功能是向內存中寫入一個字,以完成前面的 RMW 操作。
LL/SC 指令的獨特之處在於,它們不是一個簡單的內存讀取/寫入的函數,當使用 LL 指令從內存中讀取一個字之后,
比如 LL d, off(b),處理器會記住 LL 指令的這次操作(會在 CPU 的寄存器中設置一個不可見的 bit 位),同時 LL 指令讀取的地址 off(b) 也會保存在處理器的寄存器中。
接下來的 SC 指令,比如 SC t, off(b),會檢查上次 LL 指令執行后的 RMW 操作是否是原子操作(即不存在其它對這個地址的操作),
如果是原子操作,則 t 的值將會被更新至內存中,同時 t 的值也會變為1,表示操作成功;
反之,如果 RMW 的操作不是原子操作(即存在其它對這個地址的訪問沖突),則 t 的值不會被更新至內存中,且 t 的值也會變為0,表示操作失敗。
SC 指令執行失敗的原因有兩種:
- 在 LL/SC 操作序列的過程中,發生了一個異常(或中斷),這些異常(或中斷)可能會打亂 RMW 操作的原子性。
- 在多核處理器中,一個核在進行 RMW 操作時,別的核試圖對同樣的地址也進行操作,這會導致 SC 指令執行的失敗。
在IBM的那篇文章中,並沒有說明SC是如何實現RMW是否有沖突的操作的。
在一般實現中,處理器有兩個專門的域給LL和SC指令,即上文中的“不可見的bit位”以及保存ll操作地址的“寄存器”。
再LL之后,處理器會監測各種事件,當發生異常或者有別的處理器對該地址發了invalid請求時,會將不可見的bit位重置,從而導致后面的SC失敗。
由於這樣的bit位只有一位,存ll的寄存器也只有一個,因此,LL/SC無法實現嵌套,也即無法實現嵌套鎖,這是程序員使用LL/SC所需要注意的。