MIPS中LL/SC指令介紹
在多執行緒程式中,為了實現對共享變數的互斥訪問,一般都會用spinlock實現,而spinlock需要一個TestAndSet的原子操作。而這種原子操作是需要專門的硬體支援才能完成的,在MIPS中,是通過特殊的Load,Store操作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所需要注意的。
原文見:http://www.sigma.me/tag/ll