ARM指令之精髓DMB,DSB,ISB指令
4.3.5 組合語言:指令隔離(barrier)指令和儲存器隔離指令
CM3 中的另一股新鮮空氣是一系列的隔離指令(亦可以譯成“屏障”、“路障”,可互換使用——譯者 注)。它們在一些結構比較複雜的儲存器系統中是需要的(典型地用於流水線和寫緩衝——譯者注)。在 這類系統中,如果沒有必要的隔離,會導致系統發生紊亂危象(race condition),(相當於數電中的“競爭 與冒險”——譯者注).
舉例來說,如果可以在執行時更改儲存器的對映關係或者記憶體保護區的設定,(通過寫 MPU 的寄存 器),就必須在更改之後立即補上一條 DSB 指令(資料同步指令)。因為對 MPU 的寫操作很可能會被放 到一個寫緩衝中。寫緩衝是為了提高儲存器的總體訪問效率而設的,但它也有副作用,其中之一,就是 會導致寫記憶體的指令被延遲幾個週期執行,因此對儲存器的設定不能即刻生效,這會導致緊臨著的下一 條指令仍然使用舊的儲存器設定——但程式設計師的本意顯然是使用新的儲存器設定。這種紊亂危象是後患 無窮的,常會破壞未知地址的資料,有時也會產生非法地址訪問 fault。紊亂危象還有其它的表現形式, 後續章節會一一介紹。CM3 提供隔離指令族,就是要消滅這些紊亂危象(在有些講解計算機體系體系結 構的書中,這類紊亂危象也被稱為“儲存器相關”——譯註)。
CM3 中共有3 條隔離指令,如表4.27 所列
表4.27 隔離指令
指令名 |
功能描述 |
DMB |
資料儲存器隔離。DMB 指令保證: 僅當所有在它前面的儲存器訪問操作 都執行完畢後,才提交(commit)在它後面的儲存器訪問操作。 |
DSB |
資料同步隔離。比 DMB 嚴格: 僅當所有在它前面的儲存器訪問操作 都執行完畢後,才執行在它後面的指令(亦即任何指令都要等待儲存器訪 問操作——譯者注) |
ISB |
指令同步隔離。最嚴格:它會清洗流水線,以保證所有它前面的指令都執 行完畢之後,才執行它後面的指令。 |
DMB 在雙口 RAM 以及多核架構的操作中很有用。如果 RAM 的訪問是帶緩衝的,並且寫完之後
馬上讀,就必須讓它“喘口氣”——用 DMB 指令來隔離,以保證緩衝中的資料已經落實到 RAM 中。 DSB 比 DMB 更保險(當然也是有執行代價的),它是寧可錯殺也不漏網——清空了寫緩衝,使得任 何它後面的指令,不管要不要使用先前的儲存器訪問結果,通通等待訪問完成。大蝦們可以在有絕 對信心時使用 DMB,新手還是使用 DSB 比較保險。
同 DMB/DSB 相比,ISB 指令看起來似乎最強悍,但是卻一身都是“愣勁”,不由分說就“動粗”。
不過它還有其它的用場——對於高階底層技巧:“自我更新”(self-mofifying)程式碼,非常有用。舉例 來說,如果某個程式從下一條要執行的指令處更新了自己,但是先前的舊指令已經被預取到流水線 中去了,此時就必須清洗流水線,把舊版本的指令洗出去,再預取新版本的指令。因此,必須在被 更新程式碼段的前面使用 ISB,以保證舊的程式碼從流水線中被清洗出去,不再有機會執行(譯者覺得 這種做法太工於技巧,有點“作秀”,現實程式設計中應該極少會用到,因此讀者不必太鑽它)。