| RFC-0259:單調時鐘暫停和啟動時間軸 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 詳細說明在 S2Idle 期間暫停單調時鐘,並介紹啟動時間軸。 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2024-08-16 |
| 審查日期 (年-月-日) | 2024-09-11 |
問題陳述
暫停至閒置 RFC 指出,在暫停至閒置期間,單調時鐘應暫停。不過,在 Fuchsia 上執行的程式可能需要瞭解暫停期間經過的時間。如果我們暫停時鐘,但未提供替代方式讓這些程式追蹤時間,這些程式就會中斷。
摘要
這份 RFC 建議新增時間軸 (以下稱為「啟動時間軸」),在暫停至閒置期間持續進展,藉此解決上述問題。我們也會介紹時鐘、計時器和其他與時間軸互動的相關物件。
如果現有程式碼需要瞭解暫停期間經過的時間,就必須先修改程式碼,使用啟動時間軸,我們才會變更單調時鐘的暫停方式。
利害關係人
講師:jamesr@google.com
審查者:
- adamperry@google.com
- alizhang@google.com
- brunodalbo@google.com
- crjohns@google.com
- fmil@google.com
- gmtr@google.com
- johngro@google.com
- maniscalco@google.com
- miguelfrde@google.com
- tgales@google.com
- tmandry@google.com
已諮詢:
我們諮詢了 Fuchsia 許多團隊,才完成這份 RFC 的內容。包括但不限於下列團隊的成員:
- 科學鑑識
- 診斷
- Kernel
- 效能
- 安全性
- Starnix
- 計時
社交:
這份 RFC 的內容已在多份獨立文件中公開,並傳送至涵蓋大多數 Fuchsia 機構的各種郵寄清單。
需求條件
這項 RFC 對現有的單調時間軸和新的啟動時間軸都設下多項規定:
- 導入啟動時間軸,並在暫停期間暫停單調時鐘,不得妨礙應用程式實作現有功能。
- 啟動時鐘必須回報系統啟動後經過的總時間,包括暫停至閒置狀態所花費的時間。
- 單調時鐘不得包含暫停至閒置狀態所花費的時間。 在暫停至閒置 RFC 之前,系統暫停期間的單調時鐘行為未定義,因此我們在此明確定義該行為。
- 單調時鐘和開機時鐘必須單調遞增。
- 核心初始化計時器硬體時,單調時鐘和開機時鐘必須設為零。
- 計時器硬體初始化必須在使用者空間啟動前完成。
設計
這項提案說明瞭新的啟動時間軸行為,以及單調時間軸行為的變化。此外,本文也概述 Fuchsia 的哪些部分可能需要使用啟動時間軸,以配合暫停單調時鐘。未來 RFC 將提供更詳細的 API 異動說明。
命名注意事項
雖然每個主要作業系統都有時間軸,且系統暫停時不會暫停,但每個作業系統的時間軸名稱都不同。下表列出 Fuchsia 中的兩個時間軸,以及在其他作業系統中的名稱:
| 紫紅色 | Linux | BSD | Windows | OS X | Android |
|---|---|---|---|---|---|
| 單調時間 | CLOCK_MONOTONIC_RAW | CLOCK_UPTIME | 無偏誤時間 | 絕對時間 | 運作時間 |
| 啟動時間 | CLOCK_BOOTTIME | CLOCK_BOOTTIME | 即時或時間 | 連續時間 | ElapsedRealtime |
我們選擇「啟動時間軸」這個名稱,是為了與 Linux 和 BSD 使用的現有名稱相符,特別是因為 POSIX 相容性 (透過 Starnix) 是我們在 Zircon 核心中導入這個新時間軸的主要原因之一。
時間軸語意
在暫停至閒置期間,開機時間軸保證會進展。 相反地,如 RFC-230 所述,單調時間軸保證會在暫停期間暫停。不過,系統未暫停時,兩條時間軸的計時速度相同。核心首次初始化計時器硬體時,這兩個時間軸也會設為零,目前這項作業會在核心啟動初期執行。
受影響的 Fuchsia 部分
Fuchsia 的下列部分必須變更,才能配合暫停單調時鐘。這項 RFC 的目標是概略說明需要變更的領域。日後的 RFC 和設計文件會明確說明這些變更的內容和方式。
請注意,這裡列出的每個區域也應稽核其提供的 FIDL 服務,確保所有時間戳記欄位都記錄了作業時間表。時間戳記類型本身不會變更,但註解和變數名稱應清楚指出所用的時間軸。類型日後可能會變更,詳情請參閱「未來工作」一節。
- Kernel:許多核心 API 會採用或傳回單調時間戳記。您可能需要修改部分 API,才能同時支援這兩種時間軸,或是完全改用開機時間。
- Timekeeper:計算世界標準時間時,應改用開機時間。
- 診斷:診斷堆疊會在許多地方使用時間戳記 (封存器、記錄、檢查等)。必須稽核這些用途,確保正確無誤。
- 追蹤:追蹤功能目前會使用單調時間戳記為樣本加上註解,因此在暫停期間將無法運作。在這些間隔中保留追蹤記錄有許多實用案例,因此我們需要重建這些記錄。
- Starnix:Starnix 中所有
CLOCK_BOOTTIME的用法都必須改用啟動時間軸。 - 鑑識:異常終止報告和 Cobalt 都包含單調時間戳記;這些可能需要或不需要改用啟動時間戳記。
- 開發人員工具:FFX 可能需要新增功能來取得目前的啟動時間,並在擷取記錄時稽核單調時間的使用情形。
- 系統程式庫:部分語言專屬功能 (例如標準程式庫中的非同步執行器或時間 API) 可能需要考量新的時間軸。
- 軟體發布:Omaha 用戶端 (以及 SWD 堆疊中可能有的其他元件) 依賴單調時間,可能需要切換時間軸。
- Netstack:Netstack3 使用的計時器可能需要切換為使用啟動時間軸。
實作
實作作業將分階段進行。
第 1 階段:核心支援開機時間
Zircon 核心會導入啟動時間軸,並修改內部結構,以搭配新的時間軸運作。開機時間軸隨後會公開給使用者空間。這項異動需要進行一些 API 變更,因此需要另一份 RFC 文件記錄這些變更。
第 2 階段:Starnix 整合
Zircon 支援啟動時間軸後,Starnix 就能使用該時間軸支援 CLOCK_BOOTTIME 的實作項目,以及所有相關的下游功能。由於 Starnix 使用 @next vDSO,因此可以先與系統的其他部分整合,再與其他部分整合,這可能允許與第 1 階段提及的 RFC 核准程序平行化。
第 3 階段:在啟用暫停功能的裝置上維持功能
單調時鐘只會在系統暫停期間暫停。 因此,我們必須確保所有在支援暫停的裝置上執行的軟體,都改用第 1 階段導入的啟動時間軸。包括系統程式庫、診斷、追蹤、鑑識和時間管理員的變更。
只要可行,這項作業可以與第 2 階段同步進行。
第 4 階段:在暫停到閒置期間暫停單調時鐘
修正所有在啟用暫停功能的裝置上執行的程式碼後,我們就能在暫停期間暫停單調時鐘。這可能會突顯其他問題 (詳情請參閱「不明」一節)。如果這些問題導致重要的使用者歷程中斷,系統會還原暫停時鐘的 CL,並修正問題。如果重要使用者歷程未中斷,時鐘會保持暫停狀態,問題也會向前修正。
第 5 階段:在停用暫停功能的裝置上維持功能
如果軟體只能在停用暫停功能的裝置上執行,且必須瞭解暫停時間,則應視需要修改軟體,改用啟動時間。由於這些裝置的暫停至閒置支援優先順序較低,因此時間壓力較小。這個階段的變更包括軟體交付和開發人員工具。
Netstack3 也會在這一階段更新;即使它在啟用暫停功能的裝置上執行,單調時鐘暫停時,它使用的計時器也不會中斷,因此我們不需要封鎖它。
後續作業
喚醒向量
我們可能希望支援在開機時間軸上的特定時間點恢復系統。為此,我們必須在系統中正式定義喚醒向量的概念,並建立語意,以便建立以時間為準的喚醒向量。這部分留待日後的 RFC 處理。
時間軸感知 FIDL 時間戳記
FIDL 目前會使用 zx.Time 代表所有時間戳記,這會別名為 int64。最終,這類別將受益於:
- 儲存或以其他方式記錄參考時間軸,或
- 會改用各個參考時間軸的專屬時間類型。
我們會在日後的 RFC 中決定採用哪種做法,因為推出新時間軸並瞭解常見的使用模式,有助於我們做出更明智的決策。
效能
導入第二個時間軸並暫停單調時間軸,本質上不會影響效能。不過,未來 RFC 中有關各種 API 如何與啟動時間互動的設計決策,可能會對效能造成影響。相關 RFC 和設計文件應討論這些影響。
人體工學
這項異動會讓 Fuchsia 的時間推理更加複雜。程式碼作者必須先考量程式碼是否需要瞭解暫停間隔,再使用時間 API。不過,大多數程式應該都能使用單調時間軸,並忽略暫停期間,因為這段時間不會執行任何使用者空間執行緒。
回溯相容性
如「設計與實作」一節所述,目前有些程式碼會使用單調時鐘,但如果該時鐘在暫停至閒置期間暫停,這些程式碼可能無法正常運作。如「實作」一節所述,我們會先將這段程式碼遷移至啟動時間軸,再暫停時鐘。
安全性考量
有幾項重要的安全作業需要可信的時間來源。包括節流、驗證權杖和驗證憑證。目前,節流和權杖驗證需要可信執行環境 (TEE) 和/或雲端,因此並非 Fuchsia 這類高階 OS 的主要考量。
Fuchsia 會使用憑證驗證功能,驗證 HTTPS、SSH、Omaha、TUF 等服務的安全傳輸 (TLS)。這需要時間來源具有高度可信度,也就是時間來源必須在幾分鐘的誤差範圍內反映時間的實際情況。目前這項需求是由 Timekeeper 解決,該工具專門調整 UTC 時鐘,時間用戶端會從中提取時間。因此,如 RFC 先前所述,Timekeeper 必須改用開機時間。請注意,Timekeeper 會先建立可信度和精確度,再允許用戶端擷取時間,因此不需要額外作業即可確保這項作業安全無虞。
請注意,除了 Timekeeper 及其用戶端之外,任何開機時間的使用情況都「不應」處理重要的安全性用途;這些用途應透過 TEE 或使用 Timekeeper 提供的 UTC 時鐘。
隱私權注意事項
這項提案不會影響系統隱私權。
測試
您必須測試兩類不同的程式碼:
- 我們必須驗證使用單調時間軸的程式碼不受暫停期間的影響。我們打算使用 CQ 測試這項功能,並透過自動暫停功能進行大規模的本地測試。
- 我們必須確認所有需要切換至啟動時間軸的程式碼區域都能正常運作。這些領域的測試計畫由程式碼擁有者負責,並會在日後的文件和/或 RFC 中指定。
說明文件
從高層次來看,我們會在 fuchsia.dev 中新增頁面,說明新的啟動時間軸及其行為。我們也會修改現有的單調文件,反映在暫停至閒置期間,單調文件會暫停。
設計章節中提及的每個程式碼區域,隨後會負責以適當方式更新文件。
缺點、替代方案和未知事項
替代方案
可以想像,在暫停期間,我們不會暫停時鐘,因此不需要新的啟動時間表,這也是替代解決方案。很抱歉,這不符合我們的平台規定:
- Starnix 的預期行為:Linux 將 CLOCK_MONOTONIC 定義為「不計算系統暫停的時間」。因此,Starnix 必須提供相同的保證。我們可以透過使用者空間時鐘實作這項功能,但這會造成重大複雜情況,因為 Starnix 和 Fuchsia 的時鐘行為不同,也就是說,任何涉及時間和時間戳記的 IPC 或作業都必須考量差異。
- 部分現有程式碼的預期行為:部分程式碼的編寫前提是單調時間不會暫停。有些程式碼是假設會這樣而編寫。根據暫停至閒置 RFC,我們決定暫停單調時鐘是兩害相權取其輕的做法。
- 避免計時器「喚醒風暴」:假設系統長時間暫停,而單調時鐘在這段期間持續推進。系統中由程式設定的計時器數量不限,但系統要等到從暫停狀態恢復後,才會執行回呼。這可能會導致我們在繼續執行時,花費大量時間執行計時器回呼。
不明
在 Fuchsia 上執行的幾乎所有程式都會使用單調時間軸。如上一節所述,部分程式碼的編寫前提是單調時鐘在暫停期間會繼續運作。一旦我們暫停時鐘,這就會中斷,而且很可能以細微的方式中斷。
我們已盡可能找出並列舉所有需要切換至新時間軸的程式碼區域。我們不僅檢查程式碼,也與整個機構的許多利害關係人進行深入對話,我們有信心已找出大部分潛在的重大問題。
不過,我們可能遺漏了某些呼叫網站,或是錯誤地假設這些網站使用單調時間軸沒問題。很抱歉,我們無法輕易找出這些問題;這些是未知的未知問題,只有在暫停時鐘 (暫停至閒置期間) 並對系統暫停進行廣泛測試後,才會顯現出來。
既有技術和參考資料
RFC-0230:暫停至閒置 RFC