RFC-0240:物件上的非同步作業

RFC-0240:物件上的非同步作業
狀態已接受
領域
  • 核心
說明

定義 Zircon 中的非同步作業如何與物件及處理作業互動。

更小鳥
作者
審查人員
提交日期 (年月分)2024-02-06
審查日期 (年-月-日)2024-03-11

摘要

導致 Zircon 核心中的非同步作業是在核心物件上執行,而且與用來註冊這些作業的控制代碼沒有關聯。

提振精神

Zircon 定義核心物件的非同步等待作業。我們想新增具有副作用的非同步作業,例如非同步管道讀取。為此,我們必須釐清這些作業的語意,以及這些作業的語意,以及這些作業與涉及的控制代碼和/或物件的其他作業之間的互動情形。

object_wait_async 是非同步作業的範例,會在物件狀態變更時產生通訊埠封包。目前的 API 會嘗試分割目前在基礎物件上執行的作業與識別作業的控制代碼,因為兩者名稱相同。

相關人員

Zircon

講師:

FEC 委任的人員透過 RFC 程序來破壞這個 RFC。

審查者:

  • maniscalco@google.com
  • cpu@google.com
  • abarth@google.com

諮詢時間:

社會化:

相關規定

定義非同步核心作業 (包括 object_wait_async) 的關係,並處理傳輸和結束控制代碼等互動。

設計

總覽

Zircon 中的非同步作業會在物件 (而非控制代碼) 上運作。物件狀態的變更可能會影響這些作業。在用來參照物件的控制代碼中,變更不會影響非同步作業的行為,但有特別所述的管道中斷處。註冊後,非同步作業會持續進行,直到完成、明確取消,或所有對物件進行的控制代碼關閉為止。系統會更新在通訊埠上取消非同步作業的設施,以反映新的語意。

Syscall 變更

object_wait_async:

  • 從說明文件和備份程式碼中移除「如果處理程序關閉,系統會終止相關聯的作業,但佇列中的封包不會受到影響」。

註冊後,非同步等待時間會持續有效,直到物件狀態變更以符合觀察到的條件、明確取消等待,或所有與物件相關的控制代碼都關閉為止。

port_cancel:

  • 淘汰 port_cancel 並提供 port_cancel_key 做為替代項目,以取消使用指定金鑰的指定通訊埠上的所有作業。簽名:
zx_port_cancel_key(zx_handle_t port, uint32_t options, uint64_t key)

您也有機會新增 port_cancel 目前缺少的 options 參數。

或者,您也可以更新 port_cancel 的實作,忽略 source 參數。在實際運作時,系統會用不重複的金鑰註冊每項作業的可取消通訊埠作業。這個索引鍵通常就是分配來處理作業本身的資料結構位址。有證據顯示這項變更非常安全 (請參閱「回溯相容性」一節),但想要安全部署這項變更,並可在使用相同名稱的情況下取回 options 運算單元,這確實是很困難的。使用新的作業名稱可讓我們逐步更新程式碼,並追蹤舊作業的呼叫端。

object_wait_oneobject_wait_many,搭配 handle_close

  • 明確記錄的功能集沒有變化。在同步等待期間關閉控制代碼的文件已淘汰。

這些是在依據帳號代碼識別的一或多個物件上的同步等待時間。我們目前記錄的是,關閉處理點會取消所有目前待處理的等待這些作業,但這在本質上來說非常罕見,因為某個執行緒關閉了處理常式,因此無法得知另一個呼叫 object_wait_{one,many} 的執行緒是否已解決該處理代碼。對 handle_closeobject_wait_{one,many} 進行競賽的程式可能會觀察 ZX_ERR_CANCELEDZX_ERR_BAD_HANDLE。我們可以透過將控制代碼與物件 (https://fxrev.dev/949517) 建立關聯,或讓程式更輕鬆地等待多個條件,以便同步處理使用者空間中對帳號的存取權,進而取消這些同步等待作業。目前定義不清楚控制代碼的作業中不夠明確,因此本提案不會變更行為。

channel_callchannel_call_etc

  • 明確記錄的功能集沒有變化。

這些程式碼目前包含隱式說明文件,與 ZX_ERR_CANCELED 傳回值中的 object_wait_{one,many} 相同。在一般情況下,使用 handle_cancel 時,這類作業也會發生與這類作業相同的競爭問題,不過由於這項作業會提供更多內部詳細資料,所以可能構成關閉無法在實務上競爭的情況。channel_call 的內部等待時間無法由呼叫端參數化,因此程式無法使用多個條件來協調關閉作業。如要提供無種族取消的取消機制,我們必須定義獨立的作業,例如 https://fxrev.dev/949517 中提議的作業。和 object_wait_{one,many} 一樣,儘管目前的行為懷疑這項 RFC 不會提議變更這些運算的行為。

頻道排序

管道在 Fuchsia 系統架構中扮演獨特的角色,且目前在核心中設有特殊情況邏輯,用於驗證只有在呼叫程序擁有處理常式時,管道帳號上的作業才會成功。系統中廣泛使用管道來交換資料和功能。這些檢查的目的是在管道在不同信任層級執行的程序之間傳遞時,確保管道的機密性和完整性。一旦某項程序取得管道的控制代碼,就會承諾專屬從該端點讀取和寫入訊息。為了使用此 RFC 中提議的語意保留這個屬性,並允許日後進行非同步管道作業,我們可以利用管道端點的另一個屬性,也就是該管道端點只有一個控制代碼。系統會將傳送至管道的帳號的移轉作業視為物件上的作業,有可能導致管道待處理的異動作業,或是移轉作業嘗試失敗。

物件狀態 (例如 READABLE 和 WRITABLE) 信號的觀察不會違反我們重視的屬性。即使在轉移此控制代碼後,程式仍可觀察管道是否可讀取或可寫入,因為該資訊並不具有系統狀態的功能或重要機密資訊。也就是說,針對有此提案的管道,object_wait_async 作業不必有不同行為。對非同步讀取等管道的未來作業將需要考慮與移轉的互動。

實作

這項變更對使用者空間的主要影響,就是取消非同步物件等待通訊埠物件上的等待。非同步調度工具程式庫必須針對可取消的作業分配並追蹤不重複鍵,而且如果不使用物件,就不必再追蹤處理值。將呼叫 port_cancel 的第二個參數從控制值變更為常值 0,透過機械方式將呼叫轉譯為 port_cancel_key

在核心上,觀察器、通訊埠與物件表示法之間的關係非常細微。這項變更會在取消程序期間移除控制點資料表鎖定的依附元件,並在日後重構處理控制邏輯,藉此減輕複雜度。就短期而言,最直接的實作方式,就是以空值 Handle 註冊非同步等待事件,並將已註冊的等待標示為已取消,並在觀察器觸發時清除觀察器狀態,以執行非同步等待取消作業。

效能

這項變更可減少非同步作業的核心排程數量,並減輕處理表鎖定作業的壓力,這可能對某些類型的負載有所幫助。我們目前的 Microbenchmark 搭配簡單的原型實作方式沒有顯著變化。使用者空間程式庫也可以儲存較少資訊,藉此取消已註冊的非同步作業。

人體工學

如果應用程式想取消個別非同步作業,就需要追蹤鍵/值。在實際導入作業中,除了保留處理值外,調度工具實作也會執行這項作業。

回溯相容性

這會以細微的方式變更 object_wait_asyncport_cancel 的記載和實際語意。這些變更不會影響維護這些屬性的程式:

  • 系統會以不重複的金鑰註冊每個等待時間
  • 等待物件的處理不會關閉,也不會轉移已註冊的等候

現今的一切通常都是如此。非同步等待通常會與狀態的分配建立關聯,以處理等待結果,而這些等待作業的 key 通常是根據這個配置的位址計算,而且此位址空間內必須有這個唯一值,或是以另一種唯一識別碼的形式提供。帳號代碼通常儲存在擁有資料結構中,如要關閉帳號代碼,必須執行某種關閉程序,以清除其參照。

https://fxrev.dev/984701 是一種原型,可將 source 參數忽略為 port_cancel。有一項 Zircon 核心測試會刻意重複使用金鑰,而樹狀結構中的所有其他測試案例均未修改。這表示對 port_cancel 的變更與目前的程式碼相容。

https://fxrev.dev/986494 是一種相關原型,可分離已註冊的控制代碼和觀察器的生命週期。這會評估我們是否仰賴關閉控制代碼來取消未完成的非同步等待。我們所有現有的測試都會通過這項變更,但經過這項變更,表明這項行為變更與目前的程式碼相容。

安全性考量

本提案可讓相關程序觀察物件狀態的變化,而在某些情況下,他們無法再處理這些異動。在此模型中,控制代碼代表啟動非同步作業的能力。在一般情況下,我們一般不會承諾,處理代碼代表物件專屬於不可重複控制代碼 (屬於管道) 以外的物件專屬存取權。

對於大多數授予可重複處理處理程序的物件類型而言,除非知道該帳號代碼的完整記錄回建立,或從可信任來源轉移,否則對於該帳號處理程序的處理程序,也無法推斷該帳號上有哪些其他的處理和操作。如果在轉移控制代碼後,系統允許在物件上保留非同步作業,這項分析作業就不會大幅改變,因為註冊商一樣能輕鬆保留重複的帳號代碼。

我們一律會為頻道提供不可用途的帳號代碼。我們會承諾提供管道專屬程序的專屬存取權。允許頻道前任擁有者觀察管道在轉移後首次可讀取的時間,可能不夠安全。導入的作業會與透過管道傳送的訊息內容互動時,請務必謹慎處理,確保只有目前處理者的擁有者可以執行這些作業。

測試

我們將使用 Zircon 的核心測試套件來測試通訊埠和非同步物件行為的變更。系統會檢查程式庫及其測試套件,評估程式庫相容性,尤其是在調度器程式庫中。現有的整合套件會與新行為的原型 (請參閱「回溯相容性」一節) 傳遞,在將變更部署至 object_wait_async 時,我們即可密切監控這些套件。

說明文件

您必須新增系統呼叫說明文件至新的 port_cancel_key,現有作業的說明文件也應如設計一節所述更新。

缺點、替代項目和未知

以帳號代碼為主軸的替代語意

另一種替代方法是,繼續將非同步作業與啟動的帳號代碼進行連結 (如目前部分說明文件建議),並在新增非同步作業時維持這個關係。這會增加這些新作業的複雜度,並使我們更難重構及最佳化核心的處理邏輯,同時為應用程式邏輯提供幾乎沒有的公用程式。

重複使用 port_cancel

我們可以將現有 port_cancelsource 參數替換為大小相同的 options 參數,不必定義新的 port_cancel_key 系統呼叫,在轉換期間,系統將不支援任何選項,這個欄位也不允許處理值。在這段過渡期間,我們會找出並更新所有呼叫端至 port_cancel,藉此在這個欄位中傳遞 0 值,而非目前提供的處理值。轉換期結束時,我們會開始強制將欄位設為零,此時就可以開始導入選項值。這個方法的一大挑戰在於,當所有呼叫端更新為新的語意時,可能難以偵測。最佳做法是在觸發前取消非同步等待,因此 port_cancel 的動態分析可能無法找出僅於異常錯誤處理或時間性情況下觸及的呼叫端。

優先藝術與參考資料

Zircon 處理解析度模型 - 草擬 2020 年的 RFC 報告,深入瞭解其中一些問題。

zx_handle_cancel - 草擬 RFC,定義在處理代碼上取消同步作業的機制,以避免處理解決進度。

非同步金鑰管理

zxwait 金鑰管理

fuchsia-Async 金鑰管理