RFC-0259:單色時鐘停權和啟動時間軸

RFC-0259:單調時鐘暫停和啟動時間軸
狀態已接受
區域
  • 系統
說明

詳細說明如何在 S2Idle 期間暫停單調時鐘,並介紹啟動時間表。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2024-08-16
審查日期 (年-月-日)2024-09-11

問題陳述

Suspend-To-Idle 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 的內容。這包括但不限於下列團隊的成員:

  • 科學鑑識
  • 診斷
  • 核心
  • 成效
  • 安全性
  • Starnix
  • 計時

社會化:

這份 RFC 的內容已在幾份獨立文件中公開,並傳送至涵蓋 Fuchsia 組織大部分成員的各種電子郵寄清單。

需求條件

這份 RFC 對現有的單調時間軸和新的啟動時間軸都設有幾項要求:

  • 在暫停期間引入啟動時間表,並暫停單調時鐘,「不得」阻止應用程式實作現有功能。
  • 啟動時鐘「必須」回報系統啟動後經過的總時間,包括在暫停待命模式中花費的時間。
  • 單調時鐘「不得」包含在暫停待命狀態中花費的時間。在 Suspend-To-Idle RFC 之前,系統暫停期間的單調時鐘行為並未定義,因此我們會在此處明確定義該行為。
  • 單調和啟動時鐘都必須以單調遞增的方式運作。
  • 當核心初始化計時器硬體時,單調和啟動時鐘都「必須」設為零。
    • 因此,計時器硬體初始化作業必須在使用者空間啟動前完成。

設計

這項提案說明新的啟動時間軸行為,以及單調時間軸行為的變更。這份文件也概略說明 Fuchsia 的哪些部分可能需要使用啟動時間表,以便配合暫停的單調時鐘。我們會在日後的 RFC 中,更詳細說明需要的 API 異動。

命名注意事項

雖然每個主要作業系統都有一個不會在系統暫停時暫停的時間軸,但每個作業系統對該時間軸的名稱都不同。以下表格列出 Fuchsia 中的兩個時間軸,以及在其他作業系統中的名稱:

紫紅色 Linux BSD Windows OS X Android
單調時間 CLOCK_MONOTONIC_RAW CLOCK_UPTIME 不偏頗的時間 絕對時間 運作時間
啟動時間 CLOCK_BOOTTIME CLOCK_BOOTTIME 即時或時間 連續時間 ElapsedRealtime

我們選擇「boot timeline」這個名稱,是為了與 Linux 和 BSD 使用的現有名稱相符,特別是因為 POSIX 相容性 (透過 Starnix) 是我們在 Zircon 核心中引入這項新時間軸的主要原因之一。

時間軸語意

系統會保證在暫停待命期間,開機時間表會持續。相反地,根據 RFC-230 的說明,單調時間軸在暫停期間保證會暫停。不過,如果系統未暫停,兩個時間軸都會以相同的速度運作。當核心首次初始化計時器硬體時,兩個時間軸也會設為零,目前是在核心啟動初期。

受影響的 Fuchsia 部分

為了配合暫停的單調時鐘,Fuchsia 的以下部分需要進行變更。這份 RFC 的目標是概略說明需要變更的領域。日後的 RFC 和設計文件將明確說明這些變更內容為何,以及如何進行變更。

請注意,此處列出的每個區域都應稽核其提供的 FIDL 服務,以確保任何時間戳記欄位都記錄了運作時間軸。時間戳記類型本身不會變更,但註解和變數名稱應清楚指出其運作時程。這些類型日後可能會變更,詳情請參閱「未來工作」一節。

  1. 核心:許多核心 API 會採用或傳回單調時間戳記。部分 API 可能需要修改,才能同時支援這兩個時間表,或完全改用啟動時間。
  2. Timekeeper:應改用啟動時間來計算世界標準時間。
  3. 診斷:診斷堆疊會在許多地方 (Archivist、記錄、檢查等) 使用時間戳記。每項使用情形都必須經過稽核,確保正確無誤。
  4. 追蹤:追蹤目前會使用單調時間戳記標註樣本,因此在停用期間將無法運作。在這些間隔中保留追蹤記錄有其用途,因此我們需要重新建構這些記錄。
  5. Starnix:Starnix 中所有 CLOCK_BOOTTIME 的用法都必須改用啟動時間表。
  6. 鑑識分析:異常終止報告和 Cobalt 都包含單調時間戳記;這些時間戳記可能需要改為使用啟動時間戳記,也可能不需要。
  7. 開發人員工具:FFX 可能需要新增功能來取得目前的啟動時間,並在擷取記錄時稽核其單調時間的用法。
  8. 系統程式庫:某些語言專屬功能 (例如標準程式庫中的非同步執行緒或時間 API) 可能需要考量新的時間表。
  9. 軟體提交:Omaha 用戶端 (以及 SWD 堆疊中的其他元件) 會依賴單調時間,因此可能需要切換時間軸。
  10. Netstack:Netstack3 使用計時器,可能需要或不需要切換至使用啟動時間表。

實作

實施這項政策將分幾個階段進行。

階段 1:開機時間的核心支援

啟動時間表將在 Zircon 核心中推出,內部結構也會修改,以便與新時間表搭配運作。然後將啟動時間表公開給使用者空間。這需要進行一些 API 變更,因此需要另一個 RFC 來記錄這些變更。

第 2 階段:Starnix 整合

一旦 Zircon 支援啟動時間表,Starnix 就能使用該時間表支援 CLOCK_BOOTTIME 的實作方式,以及所有相關的後續功能。由於 Starnix 會使用 @next vDSO,因此可在與系統的其他部分整合前先行整合,這可能會與第 1 階段提到的 RFC 核准並行。

階段 3:在啟用暫停功能的裝置上維持功能

單調時鐘只會在系統暫停期間暫停。因此,我們必須確保在支援暫停功能的裝置上執行的所有軟體,都會改用第 1 階段中介紹的啟動時間表。這包括系統程式庫、診斷、追蹤、鑑識和計時器的變更。

盡可能與第 2 階段同時進行。

階段 4:在 Suspend-To-Idle 期間暫停 Monotonic Clock

在支援暫停功能的裝置上執行的所有程式碼都已修正後,我們就可以在暫停期間暫停單調時鐘。這可能會突顯其他問題 (詳情請參閱「未知」一節)。如果這些問題會中斷重要使用者歷程,我們會恢復暫停計時的 CL,並修正問題。如果關鍵使用者歷程未中斷,則時鐘會繼續暫停,問題會在之後修正。

階段 5:在暫停功能停用的裝置上維持功能

軟體如果只在已停用暫停功能的裝置上執行,且必須瞭解暫停時間,則應修改為在必要時使用啟動時間。由於這些裝置對「暫停待命」的支援優先順序較低,因此這裡的時間壓力較小。這個階段的變更包括軟體提交和開發人員工具。

Netstack3 也會在這個階段更新;即使是在支援暫停的裝置上執行,當單調時鐘暫停時,其對計時器的使用方式也不會中斷,因此我們不需要在該時鐘上封鎖。

未來工作

喚醒向量

我們可能希望在開機時間表的特定時間點支援系統恢復功能。這樣一來,我們就必須在系統中正式定義喚醒向量的概念,並建立建立以時間為準的喚醒向量之語意。這項功能將在日後的 RFC 中討論。

時間軸感知 FIDL 時間戳記

FIDL 目前會使用 zx.Time 表示所有時間戳記,並將其別名為 int64。這類型最終將受惠於:

  1. 儲存或以其他方式記錄其參考時間表,或
  2. 已改為針對每個參考時間軸使用不同的時間類型。

我們會在日後的 RFC 中決定採用哪種方法,因為推出新時間表並瞭解常見的使用模式,有助於我們做出決定。

成效

引入第二個時間軸並暫停單調時間軸,不會對效能造成影響。不過,未來 RFC 中針對各種 API 與啟動時間互動方式所做的設計決策,可能會對效能造成影響。這些影響應在相關的 RFC 和設計文件中討論。

Ergonomics

這項變更會讓 Fuchsia 中時間的推理變得更複雜。程式碼作者必須思考,程式碼是否需要在使用時間 API 前,先瞭解暫停間隔。不過,由於在該期間內不會執行任何使用者空間執行緒,因此大多數程式應可使用單調時間軸,並忽略暫停期間。

回溯相容性

如設計和實作部分所述,目前有部分程式碼會使用單調時鐘,且在暫停待命期間暫停時鐘後,可能無法正常運作。如「實作」一節所述,系統會在暫停時鐘前,將這段程式碼遷移至啟動時間表。

安全性考量

有幾項安全性關鍵作業需要可信任的時間來源。包括節流、驗證符記和驗證憑證。目前,節流和符記驗證功能需要信任執行環境 (TEE) 和/或雲端,因此並非 Fuchsia 高階作業系統的主要考量。

憑證驗證功能會在 Fuchsia 中使用,用於驗證 HTTPS、SSH、Omaha、TUF 和其他安全傳輸 (TLS)。這需要時間來源具備高度可信度,也就是說,時間來源必須反映出實際時間的真實情況,誤差範圍在幾分鐘內。目前 Timekeeper 可滿足這項需求,它會專門調整 UTC 時鐘,讓時間用戶端可從中擷取時間。因此,如同 RFC 先前所述,Timekeeper 必須改用啟動時間。請注意,Timekeeper 會在可信度和精確度建立之前,防止用戶端擷取時間,因此不需要額外工作就能確保這項作業的安全性。

請注意,在 Timekeeper 和其用戶端以外使用開機時間時,不得處理重要安全性用例;這些用例應透過 TEE 或使用 Timekeeper 提供的世界標準時間時鐘。

隱私權注意事項

這項提案不會影響系統隱私權。

測試

您必須測試兩個不同的程式碼類別:

  1. 我們必須驗證使用單調時間軸的程式碼,在暫停期間不會受到暫停影響。我們希望透過 CQ 和自動暫停功能進行廣泛的本機測試。
  2. 我們必須驗證所有需要切換至啟動時間表函式運作的程式碼區域。這些領域的測試計畫將交由相關程式碼擁有者負責,並會在日後的說明文件和/或 RFC 中指定。

說明文件

我們會在 fuchsia.dev 中新增一個頁面,概略說明新的啟動時間表和運作方式。我們也會修改現有的單調文檔,反映出該文檔會在暫停待命期間暫停。

設計部分中提到的每個程式碼區塊都會負責更新相關說明文件,但這項工作不一定需要由該區塊的作者負責。

缺點、替代方案和未知因素

替代方案

我們可以設想其他解決方案,在暫停期間不暫停時鐘,因此不需要新的啟動時間表。很抱歉,這不符合我們的平台規定:

  1. Starnix 的預期:Linux 將 CLOCK_MONOTONIC 定義為「不計算系統暫停的時間」。因此,Starnix 必須提供相同的保證。我們可以使用使用者空間時鐘實作這項功能,但這會帶來重大的複雜性,因為 Starnix 和 Fuchsia 會有不同的時鐘行為,也就是說,任何涉及時間和時間戳記的 IPC 或作業都必須考量差異。
  2. 部分現有程式碼的預期結果:部分程式碼是假設單調時間不會暫停。有些內容是假設會發生這種情況而寫的。根據 Suspend-To-Idle RFC 的部分內容,我們決定暫停單調時鐘是較不嚴重的惡行。
  3. 避免計時器「喚醒風暴」:假設系統暫停一段很長的時間,且單調時鐘在這個期間持續運作,系統中由程式設定的計時器數量可能會達到截止期限,但系統必須從暫停狀態恢復,才能執行回呼。這可能會導致在暫停後執行計時器回呼時,花費大量時間。

未知

幾乎所有在 Fuchsia 上執行的程式都會使用單調時間軸。如先前所述,部分程式碼是假設單調時鐘會在暫停期間繼續運作。我們暫停計時後,這項功能就會中斷,而且很可能會以細微的方式中斷。

我們已盡力找出並列出所有需要切換至新時間軸的程式碼區域。我們不僅檢查程式碼,也與許多內部利益相關者進行深入討論。我們相信已找出大部分的潛在中斷情形。

不過,我們可能錯過了一些呼叫網站,或是誤以為使用單調時間軸即可處理的情況。很遺憾,我們沒有簡單的方法來識別這些問題,因為這些問題是未知的未知數,只有在我們暫停暫停待命期間的計時器,並對系統暫停功能進行廣泛測試後,這些問題才會出現。

既有技術與參考資料

RFC-0230:Suspend-To-Idle RFC