同步
原子操作的動(dòng)機(jī)來自于在共享資源時(shí)需要同步兩個(gè)或多個(gè)實(shí)體。一個(gè)簡單的例子可能是基于多線程 RTOS 的系統(tǒng)中的兩個(gè)線程,這兩個(gè)線程都需要偶爾向它們共享的 UART 外圍設(shè)備發(fā)送消息。
在操作中,一個(gè)線程可能會(huì)獲得對(duì) UART 的控制權(quán)并持有該控制權(quán),直到其整個(gè)消息被發(fā)送。否則,如果另一個(gè)線程決定在第一個(gè)線程未完成時(shí)發(fā)送消息,這兩個(gè)線程可能會(huì)通過 UART 發(fā)送替代字符,從而導(dǎo)致控制臺(tái)端口出現(xiàn)一堆難以理解的亂碼。
為了解決這個(gè)問題,我們可以定義一個(gè)資源,就像單個(gè)內(nèi)存位置一樣簡單,它包含一個(gè)指示 UART 是忙還是可用的數(shù)據(jù)字。假設(shè)這個(gè)位置的 0 表示 UART 空閑,而 1 表示它正在使用中。
當(dāng)線程 1 有消息要發(fā)送時(shí),它會(huì)讀取鎖定字。它看到它是 0,所以它寫一個(gè) 1 到這個(gè)位置。任何其他想要發(fā)送消息的線程都會(huì)發(fā)現(xiàn)這個(gè)鎖或信號(hào)量包含一個(gè) 1,并且會(huì)等到它被清除后再嘗試獲取資源以供自己使用。
如果檢查和設(shè)置鎖的過程被中斷,就會(huì)出現(xiàn)問題。
考慮以下情況:
任務(wù) 1 讀取鎖定字。
它找到包含零的單詞。
任務(wù) 1 由于更高優(yōu)先級(jí)的任務(wù)或?qū)е缕鋾和5闹袛喽V埂?/p>
當(dāng)任務(wù) 1 被掛起時(shí),任務(wù) 2 以更高的優(yōu)先級(jí)運(yùn)行。
任務(wù) 2 需要發(fā)送一條消息并讀取它發(fā)現(xiàn)包含零的鎖定字。
任務(wù) 1 將 1 寫入鎖定字,知道它現(xiàn)在擁有 UART 的唯一控制權(quán),直到其消息被發(fā)送。
由于所需資源不可用,任務(wù) 2 釋放控制權(quán)。
任務(wù) 1 繼續(xù)運(yùn)行,知道鎖包含 0,將 1 寫入鎖字。
現(xiàn)在,任務(wù) 1 和任務(wù) 2 都確定它們對(duì) UART 資源具有獨(dú)特的控制權(quán),并將交錯(cuò)地向其發(fā)送字符,因?yàn)樗麄兛吹剿谥饌€(gè)字符的基礎(chǔ)上變得可用。
原子操作
解決這個(gè)問題需要一個(gè)原子操作,以確保檢查和設(shè)置鎖定字的完整事務(wù)在任何其他代理(即使具有更高優(yōu)先級(jí)的代理)可以中斷正在進(jìn)行的關(guān)鍵操作之前完成。
原子操作只是以一個(gè)不間斷的順序完成的操作。即使這是一個(gè)復(fù)雜的事件序列。
對(duì)原子操作的支持內(nèi)置于 C11 及更高版本等語言標(biāo)準(zhǔn)中。但是,用于在機(jī)器指令級(jí)別和硬件級(jí)別實(shí)現(xiàn)這一點(diǎn)的實(shí)際機(jī)制必須存在于 CPU 的指令集架構(gòu) (ISA) 和系統(tǒng)硬件實(shí)現(xiàn)中,以確保正確操作。
在上述情況下,任務(wù) 1 必須完成所有測試和設(shè)置鎖的步驟,然后任何其他任務(wù)或?qū)嶓w才能訪問內(nèi)存中的鎖字。
在單核系統(tǒng)中,這通常可以通過簡單地在讀取鎖定字之前禁用所有中斷并在寫入鎖定后重新啟用它們來確保。通過這種方式,不會(huì)發(fā)生中斷,因此不會(huì)導(dǎo)致內(nèi)核在其測試和設(shè)置操作的中間搶占任務(wù) 1。
當(dāng)然,在具有其他總線主控器的單核系統(tǒng)的情況下,例如 DMA 控制器和可以直接寫入內(nèi)存的外圍設(shè)備,這可能會(huì)因這些其他總線主控器之一在錯(cuò)誤的時(shí)間寫入鎖定值而被違反。但是,可以通過確保存儲(chǔ)鎖變量的內(nèi)存不能被系統(tǒng)中的任何其他總線主控器訪問來防止這種情況發(fā)生。
多核復(fù)雜性
現(xiàn)在我們看看在同一個(gè)芯片上有多個(gè)計(jì)算元素的情況,比如多核芯片,其中使用內(nèi)存鎖定來確保在不同內(nèi)核上運(yùn)行的線程也可以共享資源而不會(huì)相互破壞。
在這種情況下,我們無法阻止不同的總線主機(jī)訪問鎖定位置。這是因?yàn)殒i定位置是每個(gè)內(nèi)核必須能夠讀取和設(shè)置的位置,以確保正確共享公共資源(如上述 UART)。
現(xiàn)在我們必須確保一個(gè)核心一旦啟動(dòng)就可以完成其讀-修改-寫序列,在任何其他核心或總線主控器可以訪問正在設(shè)置鎖的內(nèi)存位置之前。
在 Arm 架構(gòu)的 8.1 版及更高版本中,為此添加了新的原子指令。我將把這個(gè)例子集中在新的指令上。一種這樣的指令是 LDADD 指令及其變體。該指令從內(nèi)存中讀取一個(gè)值,將芯片上的一個(gè)寄存器中的值相加,然后將結(jié)果寫回內(nèi)存,同時(shí)保持內(nèi)存總線,直到整個(gè)操作完成。
這樣,系統(tǒng)可以保證沒有其他總線主控器可以修改內(nèi)存中的值,從而使兩個(gè)主控器都認(rèn)為他們擁有共享資源的所有權(quán)。
這段代碼完成后,處理器可以檢查讀取的值,以驗(yàn)證它實(shí)際上是資源的唯一所有者,并且它的值對(duì)應(yīng)于在操作開始之前可用的資源。
現(xiàn)實(shí)世界的影響
好消息是,如果您使用 RTOS 或操作系統(tǒng)在單核或多核線程環(huán)境中管理線程,這一切都在較低級(jí)別的系統(tǒng)代碼中得到處理。然而,了解底層指令集和內(nèi)存硬件必須設(shè)計(jì)為支持這些鎖定機(jī)制以使這一切正常工作是有用的。如果這些機(jī)制設(shè)計(jì)不正確或被直接操縱寄存器誤用,多個(gè)內(nèi)核可能會(huì)無意中同時(shí)控制打算在使用時(shí)獨(dú)占的資源。要調(diào)試這類情況,需要先進(jìn)的多核調(diào)試功能,其中可以觀察和控制在系統(tǒng)中的多個(gè)內(nèi)核上運(yùn)行的代碼。
調(diào)試多核同步
多核調(diào)試器可以通過顯示在多個(gè)內(nèi)核或線程上運(yùn)行的程序來幫助查找同步問題,以及根據(jù)另一個(gè)內(nèi)核上的斷點(diǎn)有選擇地停止和啟動(dòng)內(nèi)核的能力應(yīng)該是確定這種機(jī)制問題的理想選擇。
在圖 1 中,我們可以在 IAR Embedded Workbench 中看到帶有 4 個(gè) CPU 的 NXP i.MX 8。所有核心都可以單獨(dú)啟動(dòng)和停止。
圖 1:每個(gè)內(nèi)核獨(dú)立的調(diào)試器控制。(來源:IAR 系統(tǒng))
圖 2 顯示了在不同 CPU 上運(yùn)行的代碼中使用多個(gè)斷點(diǎn)并結(jié)合使用互斥鎖(Arm 提供的示例):_mutex_acquire() 和 _mutex_release(),設(shè)置標(biāo)志以阻止所使用對(duì)象的在素?cái)?shù)計(jì)算中。
圖 2:在單個(gè)內(nèi)核中使用互斥鎖和斷點(diǎn)。(來源:IAR 系統(tǒng))
最常見的錯(cuò)誤之一是濫用或未使用交叉觸發(fā)接口 (CTI)。對(duì)于 Arm,CoreSight 交叉觸發(fā)接口 (CTI) 通過交叉觸發(fā)矩陣 (CTM) 連接到每個(gè)內(nèi)核。CTI 使調(diào)試邏輯、ETM 跟蹤單元和 PMU 能夠相互交互并與其他 CoreSight 組件交互。這使得每個(gè)核心可以獨(dú)立地停止和重置。不得不操縱“自制”的 CTI 變通方法,手動(dòng)控制和停止內(nèi)核,也許動(dòng)態(tài)使用宏是一項(xiàng)不可能完成的任務(wù)。默認(rèn)情況下,這應(yīng)該并且需要由來自探針(CTI 接口信號(hào))和軟件調(diào)試端的良好調(diào)試器處理。圖 3 顯示了完全控制 CTI 的用例。
圖 3:使用交叉觸發(fā)接口 (CTI) 進(jìn)行完全控制。(來源:IAR 系統(tǒng))
一旦全部結(jié)合在一起,具有多核支持的調(diào)試器就可以在非對(duì)稱和對(duì)稱場景中控制內(nèi)核,甚至可以組合在一起。圖 4 顯示了運(yùn)行 4 個(gè) Cortex-A53 和 1 個(gè) Cortex-M4 的 NXP i.MX 8 設(shè)備。MCU 和 MPU 可以獨(dú)立停止、監(jiān)控和控制。雖然所有 4 個(gè) Cortex-A53 內(nèi)核或單個(gè)內(nèi)核都從主會(huì)話運(yùn)行,但可以在 Cortex-M4 合作伙伴端設(shè)置斷點(diǎn),并專注于可能正在運(yùn)行整個(gè)設(shè)備的安全監(jiān)視器的此應(yīng)用程序。
圖 4:在配備 4 個(gè) Cortex-A53 和 1 個(gè) Cortex-M4 的 NXP i.MX 8 設(shè)備上運(yùn)行的多核會(huì)話。(來源:IAR 系統(tǒng))
在應(yīng)用程序中使用并行性和并發(fā)性旨在更有效地使用可用內(nèi)核。然而,它的代價(jià)是增加了應(yīng)用程序的復(fù)雜性,以及如何將源代碼拆分成更小的部分以盡可能高效地運(yùn)行。
概括
在單個(gè)芯片或系統(tǒng)中同步多個(gè)內(nèi)核需要原子操作和執(zhí)行這些操作的硬件。首次開發(fā)這種硬件/軟件組合時(shí),支持多核調(diào)試和觀察的全功能調(diào)試器對(duì)于發(fā)現(xiàn)此類系統(tǒng)的問題至關(guān)重要。無法想象如何通過在整個(gè)代碼中使用 print 語句來實(shí)現(xiàn)相同的控制,并使所有內(nèi)容完美同步。每個(gè)開發(fā)人員都應(yīng)該得到一個(gè)可以處理多核并完全控制所有線程的調(diào)試解決方案。IAR Embedded Workbench 及其調(diào)試器功能提供了這樣一個(gè)工具,在開發(fā)和調(diào)試這些復(fù)雜系統(tǒng)時(shí)非常有用。
Aaron Bauch是IAR Systems的一名高級(jí)現(xiàn)場應(yīng)用工程師,與美國東部和加拿大的客戶合作。Aaron 曾為英特爾、Analog Devices 和 Digital Equipment Corporation 等公司從事嵌入式系統(tǒng)和軟件方面的工作。他的設(shè)計(jì)涵蓋了廣泛的應(yīng)用,包括醫(yī)療儀器、導(dǎo)航和銀行系統(tǒng)。Aaron 還以南新罕布什爾大學(xué)教授的身份教授了許多大學(xué)水平的課程,包括嵌入式系統(tǒng)設(shè)計(jì)。Bauch 先生擁有紐約州紐約市 The Cooper Union 的電氣工程學(xué)士學(xué)位和哥倫比亞大學(xué)的電氣工程碩士學(xué)位。
-
ARM
+關(guān)注
關(guān)注
134文章
9052瀏覽量
366827 -
uart
+關(guān)注
關(guān)注
22文章
1227瀏覽量
101177
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論